@@ -0,0 +1,24 @@
|
||||
syntax = "proto2";
|
||||
|
||||
package ext;
|
||||
|
||||
import "google/protobuf/descriptor.proto";
|
||||
|
||||
option go_package = "github.com/syncthing/syncthing/proto/ext";
|
||||
|
||||
extend google.protobuf.MessageOptions {
|
||||
optional bool xml_tags = 74001;
|
||||
}
|
||||
|
||||
extend google.protobuf.FieldOptions {
|
||||
optional string xml = 75005;
|
||||
optional string json = 75006;
|
||||
optional string default = 75007;
|
||||
optional bool restart = 75008;
|
||||
optional bool device_id = 75009;
|
||||
optional string goname = 75010;
|
||||
}
|
||||
|
||||
extend google.protobuf.EnumValueOptions {
|
||||
optional string enumgoname = 76010;
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: ext.proto
|
||||
|
||||
package ext
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
var E_XmlTags = &proto.ExtensionDesc{
|
||||
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||
ExtensionType: (*bool)(nil),
|
||||
Field: 74001,
|
||||
Name: "ext.xml_tags",
|
||||
Tag: "varint,74001,opt,name=xml_tags",
|
||||
Filename: "ext.proto",
|
||||
}
|
||||
|
||||
var E_Xml = &proto.ExtensionDesc{
|
||||
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||
ExtensionType: (*string)(nil),
|
||||
Field: 75005,
|
||||
Name: "ext.xml",
|
||||
Tag: "bytes,75005,opt,name=xml",
|
||||
Filename: "ext.proto",
|
||||
}
|
||||
|
||||
var E_Json = &proto.ExtensionDesc{
|
||||
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||
ExtensionType: (*string)(nil),
|
||||
Field: 75006,
|
||||
Name: "ext.json",
|
||||
Tag: "bytes,75006,opt,name=json",
|
||||
Filename: "ext.proto",
|
||||
}
|
||||
|
||||
var E_Default = &proto.ExtensionDesc{
|
||||
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||
ExtensionType: (*string)(nil),
|
||||
Field: 75007,
|
||||
Name: "ext.default",
|
||||
Tag: "bytes,75007,opt,name=default",
|
||||
Filename: "ext.proto",
|
||||
}
|
||||
|
||||
var E_Restart = &proto.ExtensionDesc{
|
||||
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||
ExtensionType: (*bool)(nil),
|
||||
Field: 75008,
|
||||
Name: "ext.restart",
|
||||
Tag: "varint,75008,opt,name=restart",
|
||||
Filename: "ext.proto",
|
||||
}
|
||||
|
||||
var E_DeviceId = &proto.ExtensionDesc{
|
||||
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||
ExtensionType: (*bool)(nil),
|
||||
Field: 75009,
|
||||
Name: "ext.device_id",
|
||||
Tag: "varint,75009,opt,name=device_id",
|
||||
Filename: "ext.proto",
|
||||
}
|
||||
|
||||
var E_Goname = &proto.ExtensionDesc{
|
||||
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||
ExtensionType: (*string)(nil),
|
||||
Field: 75010,
|
||||
Name: "ext.goname",
|
||||
Tag: "bytes,75010,opt,name=goname",
|
||||
Filename: "ext.proto",
|
||||
}
|
||||
|
||||
var E_Enumgoname = &proto.ExtensionDesc{
|
||||
ExtendedType: (*descriptor.EnumValueOptions)(nil),
|
||||
ExtensionType: (*string)(nil),
|
||||
Field: 76010,
|
||||
Name: "ext.enumgoname",
|
||||
Tag: "bytes,76010,opt,name=enumgoname",
|
||||
Filename: "ext.proto",
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterExtension(E_XmlTags)
|
||||
proto.RegisterExtension(E_Xml)
|
||||
proto.RegisterExtension(E_Json)
|
||||
proto.RegisterExtension(E_Default)
|
||||
proto.RegisterExtension(E_Restart)
|
||||
proto.RegisterExtension(E_DeviceId)
|
||||
proto.RegisterExtension(E_Goname)
|
||||
proto.RegisterExtension(E_Enumgoname)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("ext.proto", fileDescriptor_95fe6908ffcf64d3) }
|
||||
|
||||
var fileDescriptor_95fe6908ffcf64d3 = []byte{
|
||||
// 305 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0xd1, 0x3d, 0x4b, 0x03, 0x31,
|
||||
0x18, 0xc0, 0x71, 0x8e, 0x16, 0xdb, 0x66, 0xec, 0x24, 0x82, 0xb5, 0x6e, 0x9d, 0xee, 0x10, 0x41,
|
||||
0x31, 0x74, 0x52, 0x14, 0x1c, 0x44, 0x28, 0xe2, 0xe0, 0x52, 0xd2, 0xcb, 0xd3, 0x34, 0x92, 0x97,
|
||||
0x72, 0x49, 0x24, 0x6e, 0xea, 0x37, 0xf0, 0x2b, 0x39, 0x69, 0x27, 0xfd, 0x06, 0xd2, 0xd1, 0xef,
|
||||
0xe0, 0x0b, 0x77, 0x97, 0x93, 0x42, 0x87, 0xdb, 0x42, 0xf8, 0xff, 0x1e, 0x12, 0x1e, 0xd4, 0x01,
|
||||
0x6f, 0xe3, 0x79, 0xa6, 0xad, 0xee, 0x36, 0xc0, 0xdb, 0xad, 0x3e, 0xd3, 0x9a, 0x09, 0x48, 0x8a,
|
||||
0xab, 0x89, 0x9b, 0x26, 0x14, 0x4c, 0x9a, 0xf1, 0xb9, 0xd5, 0x59, 0x99, 0xe1, 0x21, 0x6a, 0x7b,
|
||||
0x29, 0xc6, 0x96, 0x30, 0xd3, 0xdd, 0x89, 0xcb, 0x3c, 0xae, 0xf2, 0xf8, 0x02, 0x8c, 0x21, 0x0c,
|
||||
0x2e, 0xe7, 0x96, 0x6b, 0x65, 0x36, 0x9f, 0x5f, 0x9a, 0xfd, 0x68, 0xd0, 0x1e, 0xb5, 0xbc, 0x14,
|
||||
0x57, 0x84, 0x19, 0xbc, 0x87, 0x1a, 0x5e, 0x8a, 0xee, 0xf6, 0x1a, 0x3c, 0xe3, 0x20, 0x68, 0xc5,
|
||||
0xbe, 0xdf, 0x72, 0xd6, 0x19, 0xe5, 0x2d, 0xde, 0x47, 0xcd, 0x5b, 0xa3, 0x55, 0x9d, 0xf9, 0x09,
|
||||
0xa6, 0x88, 0xf1, 0x11, 0x6a, 0x51, 0x98, 0x12, 0x27, 0x6c, 0x9d, 0xfb, 0x0d, 0xae, 0xea, 0x73,
|
||||
0x9a, 0x81, 0xb1, 0x24, 0xab, 0xa5, 0x0f, 0x8b, 0xf0, 0xbb, 0xd0, 0xe3, 0x21, 0xea, 0x50, 0xb8,
|
||||
0xe3, 0x29, 0x8c, 0x39, 0xad, 0xc3, 0x8f, 0x01, 0xb7, 0x4b, 0x71, 0x4e, 0xf1, 0x21, 0xda, 0x60,
|
||||
0x5a, 0x11, 0x09, 0x75, 0xf4, 0x69, 0x51, 0x3e, 0x39, 0xe4, 0xf8, 0x04, 0x21, 0x50, 0x4e, 0x06,
|
||||
0xbc, 0xbb, 0x86, 0x4f, 0x95, 0x93, 0xd7, 0x44, 0xb8, 0xff, 0xb5, 0x7c, 0x7d, 0x94, 0x03, 0x56,
|
||||
0xd8, 0xf1, 0xc1, 0xeb, 0xb2, 0x17, 0xbd, 0x2f, 0x7b, 0xd1, 0xe7, 0xb2, 0x17, 0xdd, 0x0c, 0x18,
|
||||
0xb7, 0x33, 0x37, 0x89, 0x53, 0x2d, 0x13, 0x73, 0xaf, 0x52, 0x3b, 0xe3, 0x8a, 0xad, 0x9c, 0x8a,
|
||||
0xd9, 0x09, 0x78, 0xfb, 0x17, 0x00, 0x00, 0xff, 0xff, 0xcd, 0x40, 0x4c, 0x73, 0x42, 0x02, 0x00,
|
||||
0x00,
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright (C) 2020 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
//+build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
//go:generate go run scripts/protofmt.go .
|
||||
|
||||
// First generate extensions using standard proto compiler.
|
||||
//go:generate protoc -I ../ -I . --gogofast_out=Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor,paths=source_relative:ext ext.proto
|
||||
|
||||
// Then build our vanity compiler that uses the new extensions
|
||||
//go:generate go build -o scripts/protoc-gen-gosyncthing scripts/protoc_plugin.go
|
||||
|
||||
// Inception, go generate calls the script itself that then deals with generation.
|
||||
// This is only done because go:generate does not support wildcards in paths.
|
||||
//go:generate go run generate.go lib/config lib/fs
|
||||
|
||||
// Use the standard compiler here. We can revisit this later, but we don't plan on exposing this via any APIs.
|
||||
//go:generate protoc -I ../ -I . --gogofast_out=paths=source_relative:.. lib/protocol/bep.proto
|
||||
|
||||
func main() {
|
||||
for _, path := range os.Args[1:] {
|
||||
matches, err := filepath.Glob(filepath.Join(path, "*proto"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Println(path, "returned:", matches)
|
||||
args := []string{
|
||||
"-I", "..",
|
||||
"-I", ".",
|
||||
"--plugin=protoc-gen-gosyncthing=scripts/protoc-gen-gosyncthing",
|
||||
"--gosyncthing_out=paths=source_relative:..",
|
||||
}
|
||||
args = append(args, matches...)
|
||||
cmd := exec.Command("protoc", args...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
log.Fatal("Failed generating", path)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package config;
|
||||
|
||||
import "repos/protobuf/gogoproto/gogo.proto";
|
||||
|
||||
import "ext.proto";
|
||||
|
||||
enum AuthMode {
|
||||
option (gogoproto.goproto_enum_stringer) = false;
|
||||
|
||||
AUTH_MODE_STATIC = 0;
|
||||
AUTH_MODE_LDAP = 1 [(ext.enumgoname) = "AuthModeLDAP"];
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package config;
|
||||
|
||||
enum BlockPullOrder {
|
||||
BLOCK_PULL_ORDER_STANDARD = 0;
|
||||
BLOCK_PULL_ORDER_RANDOM = 1;
|
||||
BLOCK_PULL_ORDER_IN_ORDER = 2;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package config;
|
||||
|
||||
import "lib/config/folderconfiguration.proto";
|
||||
import "lib/config/deviceconfiguration.proto";
|
||||
import "lib/config/guiconfiguration.proto";
|
||||
import "lib/config/ldapconfiguration.proto";
|
||||
import "lib/config/optionsconfiguration.proto";
|
||||
import "lib/config/observed.proto";
|
||||
|
||||
import "ext.proto";
|
||||
|
||||
message Configuration {
|
||||
int32 version = 1 [(ext.xml) = "version,attr"];
|
||||
repeated FolderConfiguration folders = 2;
|
||||
repeated DeviceConfiguration devices = 3;
|
||||
GUIConfiguration gui = 4 [(ext.goname) = "GUI"];
|
||||
LDAPConfiguration ldap = 5 [(ext.goname) = "LDAP"];
|
||||
OptionsConfiguration options = 6;
|
||||
repeated ObservedDevice ignored_devices = 7 [(ext.json) = "remoteIgnoredDevices", (ext.xml) = "remoteIgnoredDevice"];
|
||||
repeated ObservedDevice pending_devices = 8;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package config;
|
||||
|
||||
import "lib/protocol/bep.proto";
|
||||
import "lib/config/observed.proto";
|
||||
|
||||
import "ext.proto";
|
||||
|
||||
message DeviceConfiguration {
|
||||
bytes device_id = 1 [(ext.goname) = "DeviceID", (ext.xml) = "id,attr", (ext.json) = "deviceID", (ext.device_id) = true];
|
||||
string name = 2 [(ext.xml) = "name,attr,omitempty"];
|
||||
repeated string addresses = 3 [(ext.xml) = "address,omitempty", (ext.default) = "dynamic"];
|
||||
protocol.Compression compression = 4 [(ext.xml) = "compression,attr"];
|
||||
string cert_name = 5 [(ext.xml) = "certName,attr,omitempty"];
|
||||
bool introducer = 6 [(ext.xml) = "introducer,attr"];
|
||||
bool skip_introduction_removals = 7 [(ext.xml) = "skipIntroductionRemovals,attr"];
|
||||
bytes introduced_by = 8 [(ext.xml) = "introducedBy,attr", (ext.device_id) = true];
|
||||
bool paused = 9;
|
||||
repeated string allowed_networks = 10 [(ext.xml) = "allowedNetwork,omitempty"];
|
||||
bool auto_accept_folders = 11;
|
||||
int32 max_send_kbps = 12;
|
||||
int32 max_recv_kbps = 13;
|
||||
repeated ObservedFolder ignored_folders = 14;
|
||||
repeated ObservedFolder pending_folders = 15;
|
||||
int32 max_request_kib = 16 [(ext.goname) = "MaxRequestKiB", (ext.xml) = "maxRequestKiB", (ext.json) = "maxRequestKiB"];
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package config;
|
||||
|
||||
import "lib/config/foldertype.proto";
|
||||
import "lib/config/size.proto";
|
||||
import "lib/config/pullorder.proto";
|
||||
import "lib/config/versioningconfiguration.proto";
|
||||
import "lib/config/blockpullorder.proto";
|
||||
|
||||
import "lib/fs/types.proto";
|
||||
import "lib/fs/copyrangemethod.proto";
|
||||
|
||||
import "ext.proto";
|
||||
|
||||
message FolderDeviceConfiguration {
|
||||
bytes device_id = 1 [(ext.goname) = "DeviceID", (ext.xml) = "id,attr", (ext.json) = "deviceID", (ext.device_id) = true];
|
||||
bytes introduced_by = 2 [(ext.xml) = "introducedBy,attr", (ext.device_id) = true];
|
||||
}
|
||||
|
||||
message FolderConfiguration {
|
||||
string id = 1 [(ext.goname) = "ID", (ext.xml) = "id,attr"];
|
||||
string label = 2 [(ext.xml) = "label,attr", (ext.restart) = false];
|
||||
fs.FilesystemType filesystem_type = 3;
|
||||
string path = 4 [(ext.xml) = "path,attr"];
|
||||
FolderType type = 5 [(ext.xml) = "type,attr"];
|
||||
repeated FolderDeviceConfiguration devices = 6;
|
||||
int32 rescan_interval_s = 7 [(ext.xml) = "rescanIntervalS,attr", (ext.default) = "3600"];
|
||||
bool fs_watcher_enabled = 8 [(ext.goname) = "FSWatcherEnabled", (ext.xml) = "fsWatcherEnabled,attr", (ext.default) = "true"];
|
||||
int32 fs_watcher_delay_s = 9 [(ext.goname) = "FSWatcherDelayS", (ext.xml) = "fsWatcherDelayS,attr", (ext.default) = "10"];
|
||||
bool ignore_perms = 10 [(ext.xml) = "ignorePerms,attr"];
|
||||
bool auto_normalize = 11 [(ext.xml) = "autoNormalize,attr", (ext.default) = "true"];
|
||||
Size min_disk_free = 12;
|
||||
VersioningConfiguration versioning = 13;
|
||||
int32 copiers = 14;
|
||||
int32 puller_max_pending_kib = 15 [(ext.goname) = "PullerMaxPendingKiB", (ext.xml) = "pullerMaxPendingKiB", (ext.json) = "pullerMaxPendingKiB"];
|
||||
int32 hashers = 16;
|
||||
PullOrder order = 17;
|
||||
bool ignore_delete = 18;
|
||||
int32 scan_progress_interval_s = 19;
|
||||
int32 puller_pause_s = 20;
|
||||
int32 max_conflicts = 21 [(ext.default) = "-1"];
|
||||
bool disable_sparse_files = 22;
|
||||
bool disable_temp_indexes = 23;
|
||||
bool paused = 24;
|
||||
int32 weak_hash_threshold_pct = 25;
|
||||
string marker_name = 26;
|
||||
bool copy_ownership_from_parent = 27;
|
||||
int32 mod_time_window_s = 28 [(ext.goname) = "RawModTimeWindowS"];
|
||||
int32 max_concurrent_writes = 29 [(ext.default) = "2"];
|
||||
bool disable_fsync = 30;
|
||||
BlockPullOrder block_pull_order = 31;
|
||||
fs.CopyRangeMethod copy_range_method = 32 [(ext.default) = "standard"];
|
||||
bool case_sensitive_fs = 33 [(ext.goname) = "CaseSensitiveFS", (ext.xml) = "caseSensitiveFS", (ext.json) = "caseSensitiveFS"];
|
||||
bool follow_junctions = 34 [(ext.goname) = "JunctionsAsDirs", (ext.xml) = "junctionsAsDirs", (ext.json) = "junctionsAsDirs"];
|
||||
|
||||
// Legacy deprecated
|
||||
bool read_only = 9000 [deprecated=true, (ext.xml) = "ro,attr,omitempty"];
|
||||
double min_disk_free_pct = 9001 [deprecated=true];
|
||||
int32 pullers = 9002 [deprecated=true];
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package config;
|
||||
|
||||
enum FolderType {
|
||||
FOLDER_TYPE_SEND_RECEIVE = 0;
|
||||
FOLDER_TYPE_SEND_ONLY = 1;
|
||||
FOLDER_TYPE_RECEIVE_ONLY = 2;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package config;
|
||||
|
||||
import "lib/config/authmode.proto";
|
||||
|
||||
import "ext.proto";
|
||||
|
||||
message GUIConfiguration {
|
||||
bool enabled = 1 [(ext.xml) = "enabled,attr", (ext.default) = "true"];
|
||||
string address = 2 [(ext.goname) = "RawAddress", (ext.default) = "127.0.0.1:8384"];
|
||||
string unix_socket_permissions = 3 [(ext.goname) = "RawUnixSocketPermissions", (ext.xml) = "unixSocketPermissions,omitempty"];
|
||||
string user = 4 [(ext.xml) = "user,omitempty"];
|
||||
string password = 5 [(ext.xml) = "password,omitempty"];
|
||||
AuthMode auth_mode = 6 [(ext.xml) = "authMode,omitempty"];
|
||||
bool use_tls = 7 [(ext.goname) = "RawUseTLS", (ext.xml) = "tls,attr", (ext.json) = "useTLS"];
|
||||
string api_key = 8 [(ext.goname) = "APIKey", (ext.xml) = "apikey,omitempty"];
|
||||
bool insecure_admin_access = 9 [(ext.xml) = "insecureAdminAccess,omitempty"];
|
||||
string theme = 10 [(ext.default) = "default"];
|
||||
bool debugging = 11 [(ext.xml) = "debugging,attr"];
|
||||
bool insecure_skip_host_check = 12 [(ext.xml) = "insecureSkipHostcheck,omitempty", (ext.json) = "insecureSkipHostcheck"];
|
||||
bool insecure_allow_frame_loading = 13 [(ext.xml) = "insecureAllowFrameLoading,omitempty"];
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package config;
|
||||
|
||||
import "lib/config/ldaptransport.proto";
|
||||
|
||||
import "ext.proto";
|
||||
|
||||
|
||||
message LDAPConfiguration {
|
||||
string address = 1 [(ext.xml) = "address,omitempty"];
|
||||
string bind_dn = 2 [(ext.goname) = "BindDN", (ext.xml) = "bindDN,omitempty", (ext.json) = "bindDN"];
|
||||
LDAPTransport transport = 3 [(ext.xml) = "transport,omitempty"];
|
||||
bool insecure_skip_verify = 4 [(ext.xml) = "insecureSkipVerify,omitempty", (ext.default) = "false"];
|
||||
string search_base_dn = 5 [(ext.goname) = "SearchBaseDN", (ext.xml) = "searchBaseDN,omitempty", (ext.json) = "searchBaseDN"];
|
||||
string search_filter = 6 [(ext.xml) = "searchFilter,omitempty"];
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package config;
|
||||
|
||||
import "repos/protobuf/gogoproto/gogo.proto";
|
||||
|
||||
import "ext.proto";
|
||||
|
||||
enum LDAPTransport {
|
||||
option (gogoproto.goproto_enum_stringer) = false;
|
||||
|
||||
LDAP_TRANSPORT_PLAIN = 0 [(ext.enumgoname) = "LDAPTransportPlain"];
|
||||
LDAP_TRANSPORT_TLS = 2 [(ext.enumgoname) = "LDAPTransportTLS"];
|
||||
LDAP_TRANSPORT_START_TLS = 3 [(ext.enumgoname) = "LDAPTransportStartTLS"];
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package config;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
import "ext.proto";
|
||||
|
||||
message ObservedFolder {
|
||||
google.protobuf.Timestamp time = 1 [(ext.xml) = "time,attr"];
|
||||
string id = 2 [(ext.goname) = "ID", (ext.xml) = "id,attr"];
|
||||
string label = 3 [(ext.xml) = "label,attr"];
|
||||
}
|
||||
|
||||
message ObservedDevice {
|
||||
google.protobuf.Timestamp time = 1 [(ext.xml) = "time,attr"];
|
||||
bytes id = 2 [(ext.goname) = "ID", (ext.json) = "deviceID", (ext.xml) = "id,attr", (ext.device_id) = true];
|
||||
string name = 3 [(ext.xml) = "name,attr"];
|
||||
string address = 4 [(ext.xml) = "address,attr"];
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package config;
|
||||
|
||||
import "lib/config/tuning.proto";
|
||||
import "lib/config/size.proto";
|
||||
|
||||
import "ext.proto";
|
||||
|
||||
message OptionsConfiguration {
|
||||
repeated string listen_addresses = 1 [(ext.goname) = "RawListenAddresses", (ext.default) = "default"];
|
||||
repeated string global_discovery_servers = 2 [(ext.goname) = "RawGlobalAnnServers", (ext.xml) = "globalAnnounceServer", (ext.json) = "globalAnnounceServers", (ext.default) = "default"];
|
||||
bool global_discovery_enabled = 3 [(ext.goname) = "GlobalAnnEnabled", (ext.xml) = "globalAnnounceEnabled", (ext.json) = "globalAnnounceEnabled", (ext.default) = "true"];
|
||||
bool local_discovery_enabled = 4 [(ext.goname) = "LocalAnnEnabled", (ext.xml) = "localAnnounceEnabled", (ext.json) = "localAnnounceEnabled", (ext.default) = "true"];
|
||||
int32 local_announce_port = 5 [(ext.goname) = "LocalAnnPort", (ext.xml) = "localAnnouncePort", (ext.json) = "localAnnouncePort", (ext.default) = "21027"];
|
||||
string local_announce_multicast_address = 6 [(ext.goname) = "LocalAnnMCAddr", (ext.xml) = "localAnnounceMCAddr", (ext.json) = "localAnnounceMCAddr", (ext.default) = "[ff12::8384]:21027"];
|
||||
int32 max_send_kbps = 7;
|
||||
int32 max_recv_kbps = 8;
|
||||
int32 reconnection_interval_s = 9 [(ext.goname) = "ReconnectIntervalS", (ext.default) = "60"];
|
||||
bool relays_enabled = 10 [(ext.default) = "true"];
|
||||
int32 relays_reconnect_interval_m = 11 [(ext.goname) = "RelayReconnectIntervalM", (ext.xml) = "relayReconnectIntervalM", (ext.json) = "relayReconnectIntervalM", (ext.default) = "10"];
|
||||
bool start_browser = 12 [(ext.default) = "true"];
|
||||
bool nat_traversal_enabled = 14 [(ext.goname) = "NATEnabled", (ext.xml) = "natEnabled", (ext.json) = "natEnabled", (ext.default) = "true"];
|
||||
int32 nat_traversal_lease_m = 15 [(ext.goname) = "NATLeaseM", (ext.xml) = "natLeaseMinutes", (ext.json) = "natLeaseMinutes", (ext.default) = "60"];
|
||||
int32 nat_traversal_renewal_m = 16 [(ext.goname) = "NATRenewalM", (ext.xml) = "natRenewalMinutes", (ext.json) = "natRenewalMinutes", (ext.default) = "30"];
|
||||
int32 nat_traversal_timeout_s = 17 [(ext.goname) = "NATTimeoutS", (ext.xml) = "natTimeoutSeconds", (ext.json) = "natTimeoutSeconds", (ext.default) = "10"];
|
||||
int32 usage_reporting_accepted = 18 [(ext.goname) = "URAccepted", (ext.xml) = "urAccepted", (ext.json) = "urAccepted"];
|
||||
int32 usage_reporting_seen = 19 [(ext.goname) = "URSeen", (ext.xml) = "urSeen", (ext.json) = "urSeen"];
|
||||
string usage_reporting_unique_id = 20 [(ext.goname) = "URUniqueID", (ext.xml) = "urUniqueID", (ext.json) = "urUniqueId"];
|
||||
string usage_reporting_url = 21 [(ext.goname) = "URURL", (ext.xml) = "urURL", (ext.json) = "urURL", (ext.default) = "https://data.syncthing.net/newdata"];
|
||||
bool usage_reporting_post_insecurely = 22 [(ext.goname) = "URPostInsecurely", (ext.xml) = "urPostInsecurely", (ext.json) = "urPostInsecurely", (ext.default) = "false"];
|
||||
int32 usage_reporting_initial_delay_s = 23 [(ext.goname) = "URInitialDelayS", (ext.xml) = "urInitialDelayS", (ext.json) = "urInitialDelayS", (ext.default) = "1800"];
|
||||
bool restart_on_wakeup = 24 [(ext.default) = "true"];
|
||||
int32 auto_upgrade_interval_h = 25 [(ext.default) = "12"];
|
||||
bool upgrade_to_pre_releases = 26;
|
||||
int32 keep_temporaries_h = 27 [(ext.default) = "24"];
|
||||
bool cache_ignored_files = 28 [(ext.default) = "false"];
|
||||
int32 progress_update_interval_s = 29 [(ext.default) = "5"];
|
||||
bool limit_bandwidth_in_lan = 30 [(ext.default) = "false"];
|
||||
Size min_home_disk_free = 31 [(ext.default) = "1 %"];
|
||||
string releases_url = 32 [(ext.goname) = "ReleasesURL", (ext.xml) = "releasesURL", (ext.json) = "releasesURL", (ext.default) = "https://upgrades.syncthing.net/meta.json"];
|
||||
repeated string always_local_nets = 33;
|
||||
bool overwrite_remote_device_names_on_connect = 34 [(ext.goname) = "OverwriteRemoteDevNames", (ext.default) = "false"];
|
||||
int32 temp_index_min_blocks = 35 [(ext.default) = "10"];
|
||||
repeated string unacked_notification_ids = 36 [(ext.goname) = "UnackedNotificationIDs", (ext.xml) = "unackedNotificationID", (ext.json) = "unackedNotificationIDs"];
|
||||
int32 traffic_class = 37;
|
||||
string default_folder_path = 38 [(ext.default) = "~"];
|
||||
bool set_low_priority = 39 [(ext.default) = "true"];
|
||||
int32 max_folder_concurrency = 40 [(ext.goname) = "RawMaxFolderConcurrency"];
|
||||
string crash_reporting_url = 41 [(ext.goname) = "CRURL", (ext.xml) = "crashReportingURL", (ext.json) = "crURL", (ext.default) = "https://crash.syncthing.net/newcrash"];
|
||||
bool crash_reporting_enabled = 42 [(ext.goname) = "CREnabled", (ext.default) = "true"];
|
||||
int32 stun_keepalive_start_s = 43 [(ext.default) = "180"];
|
||||
int32 stun_keepalive_min_s = 44 [(ext.default) = "20"];
|
||||
repeated string stun_servers = 45 [(ext.goname) = "RawStunServers", (ext.default) = "default"];
|
||||
Tuning database_tuning = 46 [(ext.restart) = true];
|
||||
int32 max_concurrent_incoming_request_kib = 47 [(ext.goname) = "RawMaxCIRequestKiB", (ext.xml) = "maxConcurrentIncomingRequestKiB", (ext.json) = "maxConcurrentIncomingRequestKiB"];
|
||||
|
||||
// Legacy deprecated
|
||||
bool upnp_enabled = 9000 [deprecated = true, (ext.goname) = "DeprecatedUPnPEnabled"];
|
||||
int32 upnp_lease_m = 9001 [deprecated = true, (ext.goname) = "DeprecatedUPnPLeaseM", (ext.xml) = "upnpLeaseMinutes,omitempty"];
|
||||
int32 upnp_renewal_m = 9002 [deprecated = true, (ext.goname) = "DeprecatedUPnPRenewalM", (ext.xml) = "upnpRenewalMinutes,omitempty"];
|
||||
int32 upnp_timeout_s = 9003 [deprecated = true, (ext.goname) = "DeprecatedUPnPTimeoutS", (ext.xml) = "upnpTimeoutSeconds,omitempty"];
|
||||
repeated string relay_servers = 9004 [deprecated = true];
|
||||
double min_home_disk_free_pct = 9005 [deprecated = true];
|
||||
int32 max_concurrent_scans = 9006 [deprecated = true];
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package config;
|
||||
|
||||
import "repos/protobuf/gogoproto/gogo.proto";
|
||||
|
||||
enum PullOrder {
|
||||
option (gogoproto.goproto_enum_stringer) = false;
|
||||
|
||||
PULL_ORDER_RANDOM = 0;
|
||||
PULL_ORDER_ALPHABETIC = 1;
|
||||
PULL_ORDER_SMALLEST_FIRST = 2;
|
||||
PULL_ORDER_LARGEST_FIRST = 3;
|
||||
PULL_ORDER_OLDEST_FIRST = 4;
|
||||
PULL_ORDER_NEWEST_FIRST = 5;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package config;
|
||||
|
||||
import "repos/protobuf/gogoproto/gogo.proto";
|
||||
|
||||
import "ext.proto";
|
||||
|
||||
message Size {
|
||||
option (gogoproto.goproto_stringer) = false;
|
||||
|
||||
double value = 1 [(ext.xml) = ",chardata"];
|
||||
string unit = 2 [(ext.xml) = "unit,attr"];
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package config;
|
||||
|
||||
import "repos/protobuf/gogoproto/gogo.proto";
|
||||
|
||||
enum Tuning {
|
||||
option (gogoproto.goproto_enum_stringer) = false;
|
||||
|
||||
TUNING_AUTO = 0;
|
||||
TUNING_SMALL = 1;
|
||||
TUNING_LARGE = 2;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package config;
|
||||
|
||||
import "ext.proto";
|
||||
|
||||
// VersioningConfiguration is used in the code and for JSON serialization
|
||||
message VersioningConfiguration {
|
||||
option (ext.xml_tags) = false;
|
||||
|
||||
string type = 1;
|
||||
map<string, string> parameters = 2 [(ext.goname) = "Params", (ext.json) = "params"];
|
||||
int32 cleanup_interval_s = 3 [(ext.default) = "3600"];
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package fs;
|
||||
|
||||
enum CopyRangeMethod {
|
||||
COPY_RANGE_METHOD_STANDARD = 0;
|
||||
COPY_RANGE_METHOD_IOCTL = 1;
|
||||
COPY_RANGE_METHOD_COPY_FILE_RANGE = 2;
|
||||
COPY_RANGE_METHOD_SEND_FILE = 3;
|
||||
COPY_RANGE_METHOD_DUPLICATE_EXTENTS = 4;
|
||||
COPY_RANGE_METHOD_ALL_WITH_FALLBACK = 5;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package fs;
|
||||
|
||||
enum FilesystemType {
|
||||
FILESYSTEM_TYPE_BASIC = 0;
|
||||
FILESYSTEM_TYPE_FAKE = 1;
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package protocol;
|
||||
|
||||
import "repos/protobuf/gogoproto/gogo.proto";
|
||||
|
||||
option (gogoproto.goproto_getters_all) = false;
|
||||
option (gogoproto.sizer_all) = false;
|
||||
option (gogoproto.protosizer_all) = true;
|
||||
option (gogoproto.goproto_enum_stringer_all) = true;
|
||||
option (gogoproto.goproto_enum_prefix_all) = false;
|
||||
option (gogoproto.goproto_unkeyed_all) = false;
|
||||
option (gogoproto.goproto_unrecognized_all) = false;
|
||||
option (gogoproto.goproto_sizecache_all) = false;
|
||||
|
||||
// --- Pre-auth ---
|
||||
|
||||
message Hello {
|
||||
string device_name = 1;
|
||||
string client_name = 2;
|
||||
string client_version = 3;
|
||||
}
|
||||
|
||||
// --- Header ---
|
||||
|
||||
message Header {
|
||||
MessageType type = 1;
|
||||
MessageCompression compression = 2;
|
||||
}
|
||||
|
||||
enum MessageType {
|
||||
CLUSTER_CONFIG = 0 [(gogoproto.enumvalue_customname) = "messageTypeClusterConfig"];
|
||||
INDEX = 1 [(gogoproto.enumvalue_customname) = "messageTypeIndex"];
|
||||
INDEX_UPDATE = 2 [(gogoproto.enumvalue_customname) = "messageTypeIndexUpdate"];
|
||||
REQUEST = 3 [(gogoproto.enumvalue_customname) = "messageTypeRequest"];
|
||||
RESPONSE = 4 [(gogoproto.enumvalue_customname) = "messageTypeResponse"];
|
||||
DOWNLOAD_PROGRESS = 5 [(gogoproto.enumvalue_customname) = "messageTypeDownloadProgress"];
|
||||
PING = 6 [(gogoproto.enumvalue_customname) = "messageTypePing"];
|
||||
CLOSE = 7 [(gogoproto.enumvalue_customname) = "messageTypeClose"];
|
||||
}
|
||||
|
||||
enum MessageCompression {
|
||||
NONE = 0 [(gogoproto.enumvalue_customname) = "MessageCompressionNone"];
|
||||
LZ4 = 1 [(gogoproto.enumvalue_customname) = "MessageCompressionLZ4"];
|
||||
}
|
||||
|
||||
// --- Actual messages ---
|
||||
|
||||
// Cluster Config
|
||||
|
||||
message ClusterConfig {
|
||||
repeated Folder folders = 1 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
message Folder {
|
||||
string id = 1 [(gogoproto.customname) = "ID"];
|
||||
string label = 2;
|
||||
bool read_only = 3;
|
||||
bool ignore_permissions = 4;
|
||||
bool ignore_delete = 5;
|
||||
bool disable_temp_indexes = 6;
|
||||
bool paused = 7;
|
||||
|
||||
repeated Device devices = 16 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
message Device {
|
||||
bytes id = 1 [(gogoproto.customname) = "ID", (gogoproto.customtype) = "DeviceID", (gogoproto.nullable) = false];
|
||||
string name = 2;
|
||||
repeated string addresses = 3;
|
||||
Compression compression = 4;
|
||||
string cert_name = 5;
|
||||
int64 max_sequence = 6;
|
||||
bool introducer = 7;
|
||||
uint64 index_id = 8 [(gogoproto.customname) = "IndexID", (gogoproto.customtype) = "IndexID", (gogoproto.nullable) = false];
|
||||
bool skip_introduction_removals = 9;
|
||||
}
|
||||
|
||||
enum Compression {
|
||||
METADATA = 0 [(gogoproto.enumvalue_customname) = "CompressMetadata"];
|
||||
NEVER = 1 [(gogoproto.enumvalue_customname) = "CompressNever"];
|
||||
ALWAYS = 2 [(gogoproto.enumvalue_customname) = "CompressAlways"];
|
||||
}
|
||||
|
||||
// Index and Index Update
|
||||
|
||||
message Index {
|
||||
string folder = 1;
|
||||
repeated FileInfo files = 2 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
message IndexUpdate {
|
||||
string folder = 1;
|
||||
repeated FileInfo files = 2 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
message FileInfo {
|
||||
option (gogoproto.goproto_stringer) = false;
|
||||
|
||||
// The field ordering here optimizes for struct size / alignment --
|
||||
// large types come before smaller ones.
|
||||
|
||||
string name = 1;
|
||||
int64 size = 3;
|
||||
int64 modified_s = 5;
|
||||
uint64 modified_by = 12 [(gogoproto.customtype) = "ShortID", (gogoproto.nullable) = false];
|
||||
Vector version = 9 [(gogoproto.nullable) = false];
|
||||
int64 sequence = 10;
|
||||
repeated BlockInfo blocks = 16 [(gogoproto.nullable) = false];
|
||||
string symlink_target = 17;
|
||||
bytes blocks_hash = 18;
|
||||
FileInfoType type = 2;
|
||||
uint32 permissions = 4;
|
||||
int32 modified_ns = 11;
|
||||
int32 block_size = 13 [(gogoproto.customname) = "RawBlockSize"];
|
||||
|
||||
// The local_flags fields stores flags that are relevant to the local
|
||||
// host only. It is not part of the protocol, doesn't get sent or
|
||||
// received (we make sure to zero it), nonetheless we need it on our
|
||||
// struct and to be able to serialize it to/from the database.
|
||||
uint32 local_flags = 1000;
|
||||
// The version_hash is an implementation detail and not part of the wire
|
||||
// format.
|
||||
bytes version_hash = 1001;
|
||||
|
||||
bool deleted = 6;
|
||||
bool invalid = 7 [(gogoproto.customname) = "RawInvalid"];
|
||||
bool no_permissions = 8;
|
||||
}
|
||||
|
||||
enum FileInfoType {
|
||||
FILE = 0 [(gogoproto.enumvalue_customname) = "FileInfoTypeFile"];
|
||||
DIRECTORY = 1 [(gogoproto.enumvalue_customname) = "FileInfoTypeDirectory"];
|
||||
SYMLINK_FILE = 2 [(gogoproto.enumvalue_customname) = "FileInfoTypeDeprecatedSymlinkFile", deprecated = true];
|
||||
SYMLINK_DIRECTORY = 3 [(gogoproto.enumvalue_customname) = "FileInfoTypeDeprecatedSymlinkDirectory", deprecated = true];
|
||||
SYMLINK = 4 [(gogoproto.enumvalue_customname) = "FileInfoTypeSymlink"];
|
||||
}
|
||||
|
||||
message BlockInfo {
|
||||
option (gogoproto.goproto_stringer) = false;
|
||||
bytes hash = 3;
|
||||
int64 offset = 1;
|
||||
int32 size = 2;
|
||||
uint32 weak_hash = 4;
|
||||
}
|
||||
|
||||
message Vector {
|
||||
repeated Counter counters = 1 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
message Counter {
|
||||
uint64 id = 1 [(gogoproto.customname) = "ID", (gogoproto.customtype) = "ShortID", (gogoproto.nullable) = false];
|
||||
uint64 value = 2;
|
||||
}
|
||||
|
||||
// Request
|
||||
|
||||
message Request {
|
||||
int32 id = 1 [(gogoproto.customname) = "ID"];
|
||||
string folder = 2;
|
||||
string name = 3;
|
||||
int64 offset = 4;
|
||||
int32 size = 5;
|
||||
bytes hash = 6;
|
||||
bool from_temporary = 7;
|
||||
uint32 weak_hash = 8;
|
||||
}
|
||||
|
||||
// Response
|
||||
|
||||
message Response {
|
||||
int32 id = 1 [(gogoproto.customname) = "ID"];
|
||||
bytes data = 2;
|
||||
ErrorCode code = 3;
|
||||
}
|
||||
|
||||
enum ErrorCode {
|
||||
NO_ERROR = 0 [(gogoproto.enumvalue_customname) = "ErrorCodeNoError"];
|
||||
GENERIC = 1 [(gogoproto.enumvalue_customname) = "ErrorCodeGeneric"];
|
||||
NO_SUCH_FILE = 2 [(gogoproto.enumvalue_customname) = "ErrorCodeNoSuchFile"];
|
||||
INVALID_FILE = 3 [(gogoproto.enumvalue_customname) = "ErrorCodeInvalidFile"];
|
||||
}
|
||||
|
||||
// DownloadProgress
|
||||
|
||||
message DownloadProgress {
|
||||
string folder = 1;
|
||||
repeated FileDownloadProgressUpdate updates = 2 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
message FileDownloadProgressUpdate {
|
||||
FileDownloadProgressUpdateType update_type = 1;
|
||||
string name = 2;
|
||||
Vector version = 3 [(gogoproto.nullable) = false];
|
||||
repeated int32 block_indexes = 4 [packed=false];
|
||||
int32 block_size = 5;
|
||||
}
|
||||
|
||||
enum FileDownloadProgressUpdateType {
|
||||
APPEND = 0 [(gogoproto.enumvalue_customname) = "UpdateTypeAppend"];
|
||||
FORGET = 1 [(gogoproto.enumvalue_customname) = "UpdateTypeForget"];
|
||||
}
|
||||
|
||||
// Ping
|
||||
|
||||
message Ping {
|
||||
}
|
||||
|
||||
// Close
|
||||
|
||||
message Close {
|
||||
string reason = 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// Copyright (C) 2020 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
//+build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
)
|
||||
|
||||
func main() {
|
||||
new, err := os.Create("tags.csv")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(filepath.Abs(new.Name()))
|
||||
w := csv.NewWriter(new)
|
||||
w.Write([]string{
|
||||
"path", "json", "xml", "default", "restart",
|
||||
})
|
||||
walk(w, "", &config.Configuration{})
|
||||
w.Flush()
|
||||
new.Close()
|
||||
}
|
||||
|
||||
func walk(w *csv.Writer, prefix string, data interface{}) {
|
||||
s := reflect.ValueOf(data).Elem()
|
||||
t := s.Type()
|
||||
for i := 0; i < s.NumField(); i++ {
|
||||
f := s.Field(i)
|
||||
ft := t.Field(i)
|
||||
|
||||
for f.Kind() == reflect.Ptr {
|
||||
f = f.Elem()
|
||||
}
|
||||
|
||||
pfx := prefix + "." + s.Type().Field(i).Name
|
||||
if f.Kind() == reflect.Slice {
|
||||
slc := reflect.MakeSlice(f.Type(), 1, 1)
|
||||
f = slc.Index(0)
|
||||
pfx = prefix + "." + s.Type().Field(i).Name + "[]"
|
||||
}
|
||||
|
||||
if f.Kind() == reflect.Struct && strings.HasPrefix(f.Type().PkgPath(), "github.com/syncthing/syncthing") {
|
||||
walk(w, pfx, f.Addr().Interface())
|
||||
} else {
|
||||
jsonTag := ft.Tag.Get("json")
|
||||
xmlTag := ft.Tag.Get("xml")
|
||||
defaultTag := ft.Tag.Get("default")
|
||||
restartTag := ft.Tag.Get("restart")
|
||||
w.Write([]string{
|
||||
strings.ToLower(pfx), jsonTag, xmlTag, defaultTag, restartTag,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
// Copyright (C) 2020 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
//+build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/syncthing/syncthing/proto/ext"
|
||||
|
||||
"github.com/gogo/protobuf/gogoproto"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
|
||||
"github.com/gogo/protobuf/vanity"
|
||||
"github.com/gogo/protobuf/vanity/command"
|
||||
)
|
||||
|
||||
func main() {
|
||||
req := command.Read()
|
||||
files := req.GetProtoFile()
|
||||
files = vanity.FilterFiles(files, vanity.NotGoogleProtobufDescriptorProto)
|
||||
|
||||
vanity.ForEachFile(files, vanity.TurnOffGoGettersAll)
|
||||
vanity.ForEachFile(files, TurnOnProtoSizerAll)
|
||||
vanity.ForEachFile(files, vanity.TurnOffGoEnumPrefixAll)
|
||||
vanity.ForEachFile(files, vanity.TurnOffGoUnrecognizedAll)
|
||||
vanity.ForEachFile(files, vanity.TurnOffGoUnkeyedAll)
|
||||
vanity.ForEachFile(files, vanity.TurnOffGoSizecacheAll)
|
||||
vanity.ForEachFile(files, vanity.TurnOffGoEnumStringerAll)
|
||||
vanity.ForEachEnumInFiles(files, HandleCustomEnumExtensions)
|
||||
vanity.ForEachFile(files, SetPackagePrefix("github.com/syncthing/syncthing"))
|
||||
|
||||
vanity.ForEachMessageInFiles(files, HandleCustomExtensions)
|
||||
vanity.ForEachFieldInFilesExcludingExtensions(files, TurnOffNullableForMessages)
|
||||
|
||||
resp := command.Generate(req)
|
||||
command.Write(resp)
|
||||
}
|
||||
|
||||
func TurnOnProtoSizerAll(file *descriptor.FileDescriptorProto) {
|
||||
vanity.SetBoolFileOption(gogoproto.E_ProtosizerAll, true)(file)
|
||||
}
|
||||
|
||||
func TurnOffNullableForMessages(field *descriptor.FieldDescriptorProto) {
|
||||
if !vanity.FieldHasBoolExtension(field, gogoproto.E_Nullable) {
|
||||
_, hasCustomType := GetFieldStringExtension(field, gogoproto.E_Customtype)
|
||||
if field.IsMessage() || hasCustomType {
|
||||
vanity.SetBoolFieldOption(gogoproto.E_Nullable, false)(field)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func HandleCustomEnumExtensions(enum *descriptor.EnumDescriptorProto) {
|
||||
for _, field := range enum.Value {
|
||||
if field == nil {
|
||||
continue
|
||||
}
|
||||
if field.Options == nil {
|
||||
field.Options = &descriptor.EnumValueOptions{}
|
||||
}
|
||||
customName := gogoproto.GetEnumValueCustomName(field)
|
||||
if customName != "" {
|
||||
continue
|
||||
}
|
||||
if v, ok := GetEnumValueStringExtension(field, ext.E_Enumgoname); ok {
|
||||
SetEnumValueStringFieldOption(field, gogoproto.E_EnumvalueCustomname, v)
|
||||
} else {
|
||||
SetEnumValueStringFieldOption(field, gogoproto.E_EnumvalueCustomname, toCamelCase(*field.Name, true))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func SetPackagePrefix(prefix string) func(file *descriptor.FileDescriptorProto) {
|
||||
return func(file *descriptor.FileDescriptorProto) {
|
||||
if file.Options.GoPackage == nil {
|
||||
pkg, _ := filepath.Split(file.GetName())
|
||||
fullPkg := prefix + "/" + strings.TrimSuffix(pkg, "/")
|
||||
file.Options.GoPackage = &fullPkg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func toCamelCase(input string, firstUpper bool) string {
|
||||
runes := []rune(strings.ToLower(input))
|
||||
outputRunes := make([]rune, 0, len(runes))
|
||||
|
||||
nextUpper := false
|
||||
for i, rune := range runes {
|
||||
if rune == '_' {
|
||||
nextUpper = true
|
||||
continue
|
||||
}
|
||||
if (firstUpper && i == 0) || nextUpper {
|
||||
rune = unicode.ToUpper(rune)
|
||||
nextUpper = false
|
||||
}
|
||||
outputRunes = append(outputRunes, rune)
|
||||
}
|
||||
return string(outputRunes)
|
||||
}
|
||||
|
||||
func SetStringFieldOption(field *descriptor.FieldDescriptorProto, extension *proto.ExtensionDesc, value string) {
|
||||
if _, ok := GetFieldStringExtension(field, extension); ok {
|
||||
return
|
||||
}
|
||||
if field.Options == nil {
|
||||
field.Options = &descriptor.FieldOptions{}
|
||||
}
|
||||
if err := proto.SetExtension(field.Options, extension, &value); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func SetEnumValueStringFieldOption(field *descriptor.EnumValueDescriptorProto, extension *proto.ExtensionDesc, value string) {
|
||||
if _, ok := GetEnumValueStringExtension(field, extension); ok {
|
||||
return
|
||||
}
|
||||
if field.Options == nil {
|
||||
field.Options = &descriptor.EnumValueOptions{}
|
||||
}
|
||||
if err := proto.SetExtension(field.Options, extension, &value); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func GetEnumValueStringExtension(enumValue *descriptor.EnumValueDescriptorProto, extension *proto.ExtensionDesc) (string, bool) {
|
||||
if enumValue.Options == nil {
|
||||
return "", false
|
||||
}
|
||||
value, err := proto.GetExtension(enumValue.Options, extension)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
if value == nil {
|
||||
return "", false
|
||||
}
|
||||
if v, ok := value.(*string); !ok || v == nil {
|
||||
return "", false
|
||||
} else {
|
||||
return *v, true
|
||||
}
|
||||
}
|
||||
|
||||
func GetFieldStringExtension(field *descriptor.FieldDescriptorProto, extension *proto.ExtensionDesc) (string, bool) {
|
||||
if field.Options == nil {
|
||||
return "", false
|
||||
}
|
||||
value, err := proto.GetExtension(field.Options, extension)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
if value == nil {
|
||||
return "", false
|
||||
}
|
||||
if v, ok := value.(*string); !ok || v == nil {
|
||||
return "", false
|
||||
} else {
|
||||
return *v, true
|
||||
}
|
||||
}
|
||||
|
||||
func GetFieldBooleanExtension(field *descriptor.FieldDescriptorProto, extension *proto.ExtensionDesc) (bool, bool) {
|
||||
if field.Options == nil {
|
||||
return false, false
|
||||
}
|
||||
value, err := proto.GetExtension(field.Options, extension)
|
||||
if err != nil {
|
||||
return false, false
|
||||
}
|
||||
if value == nil {
|
||||
return false, false
|
||||
}
|
||||
if v, ok := value.(*bool); !ok || v == nil {
|
||||
return false, false
|
||||
} else {
|
||||
return *v, true
|
||||
}
|
||||
}
|
||||
|
||||
func GetMessageBoolExtension(msg *descriptor.DescriptorProto, extension *proto.ExtensionDesc) (bool, bool) {
|
||||
if msg.Options == nil {
|
||||
return false, false
|
||||
}
|
||||
value, err := proto.GetExtension(msg.Options, extension)
|
||||
if err != nil {
|
||||
return false, false
|
||||
}
|
||||
if value == nil {
|
||||
return false, false
|
||||
}
|
||||
val, ok := value.(*bool)
|
||||
if !ok || val == nil {
|
||||
return false, false
|
||||
}
|
||||
return *val, true
|
||||
}
|
||||
|
||||
func HandleCustomExtensions(msg *descriptor.DescriptorProto) {
|
||||
generateXmlTags := true
|
||||
if generate, ok := GetMessageBoolExtension(msg, ext.E_XmlTags); ok {
|
||||
generateXmlTags = generate
|
||||
}
|
||||
|
||||
vanity.ForEachField([]*descriptor.DescriptorProto{msg}, func(field *descriptor.FieldDescriptorProto) {
|
||||
if field.Options == nil {
|
||||
field.Options = &descriptor.FieldOptions{}
|
||||
}
|
||||
deprecated := field.Options.Deprecated != nil && *field.Options.Deprecated == true
|
||||
|
||||
if field.Type != nil && *field.Type == descriptor.FieldDescriptorProto_TYPE_INT32 {
|
||||
SetStringFieldOption(field, gogoproto.E_Casttype, "int")
|
||||
}
|
||||
|
||||
if field.TypeName != nil && *field.TypeName == ".google.protobuf.Timestamp" {
|
||||
vanity.SetBoolFieldOption(gogoproto.E_Stdtime, true)(field)
|
||||
}
|
||||
|
||||
if goName, ok := GetFieldStringExtension(field, ext.E_Goname); ok {
|
||||
SetStringFieldOption(field, gogoproto.E_Customname, goName)
|
||||
} else if deprecated {
|
||||
SetStringFieldOption(field, gogoproto.E_Customname, "Deprecated"+toCamelCase(*field.Name, true))
|
||||
}
|
||||
|
||||
if val, ok := GetFieldBooleanExtension(field, ext.E_DeviceId); ok && val {
|
||||
SetStringFieldOption(field, gogoproto.E_Customtype, "github.com/syncthing/syncthing/lib/protocol.DeviceID")
|
||||
}
|
||||
|
||||
if jsonValue, ok := GetFieldStringExtension(field, ext.E_Json); ok {
|
||||
SetStringFieldOption(field, gogoproto.E_Jsontag, jsonValue)
|
||||
} else if deprecated {
|
||||
SetStringFieldOption(field, gogoproto.E_Jsontag, "-")
|
||||
} else {
|
||||
SetStringFieldOption(field, gogoproto.E_Jsontag, toCamelCase(*field.Name, false))
|
||||
}
|
||||
|
||||
current := ""
|
||||
if v, ok := GetFieldStringExtension(field, gogoproto.E_Moretags); ok {
|
||||
current = v
|
||||
}
|
||||
|
||||
if generateXmlTags {
|
||||
if len(current) > 0 {
|
||||
current += " "
|
||||
}
|
||||
if xmlValue, ok := GetFieldStringExtension(field, ext.E_Xml); ok {
|
||||
current += fmt.Sprintf(`xml:"%s"`, xmlValue)
|
||||
} else {
|
||||
xmlValue = toCamelCase(*field.Name, false)
|
||||
// XML dictates element name within the collection, not collection name, so trim plural suffix.
|
||||
if field.IsRepeated() {
|
||||
if strings.HasSuffix(xmlValue, "ses") {
|
||||
// addresses -> address
|
||||
xmlValue = strings.TrimSuffix(xmlValue, "es")
|
||||
} else {
|
||||
// devices -> device
|
||||
xmlValue = strings.TrimSuffix(xmlValue, "s")
|
||||
}
|
||||
}
|
||||
if deprecated {
|
||||
xmlValue += ",omitempty"
|
||||
}
|
||||
current += fmt.Sprintf(`xml:"%s"`, xmlValue)
|
||||
}
|
||||
}
|
||||
|
||||
if defaultValue, ok := GetFieldStringExtension(field, ext.E_Default); ok {
|
||||
if len(current) > 0 {
|
||||
current += " "
|
||||
}
|
||||
current += fmt.Sprintf(`default:"%s"`, defaultValue)
|
||||
}
|
||||
|
||||
if restartValue, ok := GetFieldBooleanExtension(field, ext.E_Restart); ok {
|
||||
if len(current) > 0 {
|
||||
current += " "
|
||||
}
|
||||
current += fmt.Sprintf(`restart:"%t"`, restartValue)
|
||||
}
|
||||
|
||||
SetStringFieldOption(field, gogoproto.E_Moretags, current)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
// Copyright (C) 2016 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
for _, arg := range flag.Args() {
|
||||
matches, err := filepath.Glob(arg)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
for _, file := range matches {
|
||||
if stat, err := os.Stat(file); err != nil {
|
||||
log.Fatal(err)
|
||||
} else if stat.IsDir() {
|
||||
err := filepath.Walk(file, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if filepath.Ext(path) == ".proto" {
|
||||
return formatProtoFile(path)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
if err := formatProtoFile(file); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func formatProtoFile(file string) error {
|
||||
log.Println("Formatting", file)
|
||||
in, err := os.Open(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer in.Close()
|
||||
out, err := os.Create(file + ".tmp")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
if err := formatProto(in, out); err != nil {
|
||||
return err
|
||||
}
|
||||
in.Close()
|
||||
out.Close()
|
||||
return os.Rename(file+".tmp", file)
|
||||
}
|
||||
|
||||
func formatProto(in io.Reader, out io.Writer) error {
|
||||
sc := bufio.NewScanner(in)
|
||||
lineExp := regexp.MustCompile(`([^=]+)\s+([^=\s]+?)\s*=(.+)`)
|
||||
var tw *tabwriter.Writer
|
||||
for sc.Scan() {
|
||||
line := sc.Text()
|
||||
if strings.HasPrefix(line, "//") {
|
||||
if _, err := fmt.Fprintln(out, line); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
ms := lineExp.FindStringSubmatch(line)
|
||||
for i := range ms {
|
||||
ms[i] = strings.TrimSpace(ms[i])
|
||||
}
|
||||
if len(ms) == 4 && ms[1] != "option" {
|
||||
typ := strings.Join(strings.Fields(ms[1]), " ")
|
||||
name := ms[2]
|
||||
id := ms[3]
|
||||
if tw == nil {
|
||||
tw = tabwriter.NewWriter(out, 4, 4, 1, ' ', 0)
|
||||
}
|
||||
if typ == "" {
|
||||
// We're in an enum
|
||||
fmt.Fprintf(tw, "\t%s\t= %s\n", name, id)
|
||||
} else {
|
||||
// Message
|
||||
fmt.Fprintf(tw, "\t%s\t%s\t= %s\n", typ, name, id)
|
||||
}
|
||||
} else {
|
||||
if tw != nil {
|
||||
if err := tw.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
tw = nil
|
||||
}
|
||||
if _, err := fmt.Fprintln(out, line); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user