mirror of
https://github.com/syncthing/syncthing.git
synced 2026-01-10 14:59:11 -05:00
Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b16cc72fc7 | ||
|
|
dcddd9c1e4 | ||
|
|
35c813f56f | ||
|
|
846b265430 | ||
|
|
31559e908b | ||
|
|
4db5ea5893 | ||
|
|
54643e86b5 | ||
|
|
326111d10f | ||
|
|
0fb7cc186c | ||
|
|
1f1729ba43 | ||
|
|
d4ce0dfd84 | ||
|
|
cc9ea9db89 | ||
|
|
a08a1b6998 | ||
|
|
33185fdeb5 | ||
|
|
d0ccea0404 | ||
|
|
c206fbdc58 | ||
|
|
2b9cef3ae5 | ||
|
|
a38b370c8d | ||
|
|
942b8ebb27 | ||
|
|
7892547873 | ||
|
|
5b9280c50f | ||
|
|
4d1bcd718c | ||
|
|
7dc0c6ab43 | ||
|
|
9d1ee2f7e0 | ||
|
|
4a616f3cb2 | ||
|
|
deafe4ca53 | ||
|
|
bc012d750d | ||
|
|
c7d40ccbae | ||
|
|
0d90ae26ac | ||
|
|
9189c79d74 | ||
|
|
a20d85d451 | ||
|
|
f0f60ba2e7 | ||
|
|
1c2be84e4e | ||
|
|
2ba3be5e4d | ||
|
|
5c91723ef2 | ||
|
|
a17a8cd48b | ||
|
|
27c91c57d5 | ||
|
|
86b040f595 | ||
|
|
1a8c10a8d0 | ||
|
|
01a7ef3b0f | ||
|
|
23c935b05a | ||
|
|
8e8e30dc7b | ||
|
|
d828adb648 | ||
|
|
9d09fd6af3 | ||
|
|
b1db328931 | ||
|
|
14ae330eff | ||
|
|
977ee4f06b | ||
|
|
42de53c6c9 | ||
|
|
48da6f0f22 | ||
|
|
a20c6ca868 | ||
|
|
e027175446 | ||
|
|
7774932302 | ||
|
|
3fe331c2d0 | ||
|
|
1b1d38183d | ||
|
|
fb3281b647 | ||
|
|
e6b1f67ecf | ||
|
|
9e0b924d57 | ||
|
|
df99237a7f | ||
|
|
8452fd2ab4 | ||
|
|
c390565eef | ||
|
|
02744cd73f | ||
|
|
bd622b8edd | ||
|
|
67761d8795 | ||
|
|
9f8b01b1b9 | ||
|
|
d2e3295767 |
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,6 +1,6 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Ask a question
|
||||
- name: I need help / I have a question
|
||||
url: https://forum.syncthing.net/
|
||||
about: Ask questions, get support, and discuss with other community members.
|
||||
- name: Android issues
|
||||
|
||||
2
AUTHORS
2
AUTHORS
@@ -91,6 +91,7 @@ Erik Meitner (WSGCSysadmin) <e.meitner@willystreet.coop>
|
||||
Evgeny Kuznetsov <evgeny@kuznetsov.md>
|
||||
Federico Castagnini (facastagnini) <federico.castagnini@gmail.com>
|
||||
Felix Ableitner (Nutomic) <me@nutomic.com>
|
||||
Felix Lampe <mail@flampe.de>
|
||||
Felix Unterpaintner (bigbear2nd) <bigbear2nd@gmail.com>
|
||||
Francois-Xavier Gsell (zukoo) <fxgsell@gmail.com>
|
||||
Frank Isemann (fti7) <frank@isemann.name>
|
||||
@@ -232,6 +233,7 @@ Taylor Khan (nelsonkhan) <nelsonkhan@gmail.com>
|
||||
Thomas Hipp <thomashipp@gmail.com>
|
||||
Tim Abell (timabell) <tim@timwise.co.uk>
|
||||
Tim Howes (timhowes) <timhowes@berkeley.edu>
|
||||
Tobias Klauser <tobias.klauser@gmail.com>
|
||||
Tobias Nygren (tnn2) <tnn@nygren.pp.se>
|
||||
Tobias Tom (tobiastom) <t.tom@succont.de>
|
||||
Tom Jakubowski <tom@crystae.net>
|
||||
|
||||
115
cmd/stcrashreceiver/main.go
Normal file
115
cmd/stcrashreceiver/main.go
Normal file
@@ -0,0 +1,115 @@
|
||||
// Copyright (C) 2019 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/.
|
||||
|
||||
// Command stcrashreceiver is a trivial HTTP server that allows two things:
|
||||
//
|
||||
// - uploading files (crash reports) named like a SHA256 hash using a PUT request
|
||||
// - checking whether such file exists using a HEAD request
|
||||
//
|
||||
// Typically this should be deployed behind something that manages HTTPS.
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/sha256"
|
||||
"github.com/syncthing/syncthing/lib/ur"
|
||||
|
||||
raven "github.com/getsentry/raven-go"
|
||||
)
|
||||
|
||||
const maxRequestSize = 1 << 20 // 1 MiB
|
||||
|
||||
func main() {
|
||||
dir := flag.String("dir", ".", "Directory to store reports in")
|
||||
dsn := flag.String("dsn", "", "Sentry DSN")
|
||||
listen := flag.String("listen", ":22039", "HTTP listen address")
|
||||
flag.Parse()
|
||||
|
||||
mux := http.NewServeMux()
|
||||
|
||||
cr := &crashReceiver{
|
||||
dir: *dir,
|
||||
dsn: *dsn,
|
||||
}
|
||||
mux.Handle("/", cr)
|
||||
|
||||
if *dsn != "" {
|
||||
mux.HandleFunc("/failure", handleFailureFn(*dsn))
|
||||
}
|
||||
|
||||
log.SetOutput(os.Stdout)
|
||||
if err := http.ListenAndServe(*listen, mux); err != nil {
|
||||
log.Fatalln("HTTP serve:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func handleFailureFn(dsn string) func(w http.ResponseWriter, req *http.Request) {
|
||||
return func(w http.ResponseWriter, req *http.Request) {
|
||||
lr := io.LimitReader(req.Body, maxRequestSize)
|
||||
bs, err := ioutil.ReadAll(lr)
|
||||
req.Body.Close()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
|
||||
var reports []ur.FailureReport
|
||||
err = json.Unmarshal(bs, &reports)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 400)
|
||||
return
|
||||
}
|
||||
if len(reports) == 0 {
|
||||
// Shouldn't happen
|
||||
return
|
||||
}
|
||||
|
||||
version, err := parseVersion(reports[0].Version)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 400)
|
||||
return
|
||||
}
|
||||
for _, r := range reports {
|
||||
pkt := packet(version)
|
||||
pkt.Message = r.Description
|
||||
pkt.Extra = raven.Extra{
|
||||
"count": r.Count,
|
||||
}
|
||||
pkt.Fingerprint = []string{r.Description}
|
||||
|
||||
if err := sendReport(dsn, pkt, userIDFor(req)); err != nil {
|
||||
log.Println("Failed to send crash report:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// userIDFor returns a string we can use as the user ID for the purpose of
|
||||
// counting affected users. It's the truncated hash of a salt, the user
|
||||
// remote IP, and the current month.
|
||||
func userIDFor(req *http.Request) string {
|
||||
addr := req.RemoteAddr
|
||||
if fwd := req.Header.Get("x-forwarded-for"); fwd != "" {
|
||||
addr = fwd
|
||||
}
|
||||
if host, _, err := net.SplitHostPort(addr); err == nil {
|
||||
addr = host
|
||||
}
|
||||
now := time.Now().Format("200601")
|
||||
salt := "stcrashreporter"
|
||||
hash := sha256.Sum256([]byte(salt + addr + now))
|
||||
return fmt.Sprintf("%x", hash[:8])
|
||||
}
|
||||
@@ -31,12 +31,7 @@ var (
|
||||
clientsMut sync.Mutex
|
||||
)
|
||||
|
||||
func sendReport(dsn, path string, report []byte, userID string) error {
|
||||
pkt, err := parseReport(path, report)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func sendReport(dsn string, pkt *raven.Packet, userID string) error {
|
||||
pkt.Interfaces = append(pkt.Interfaces, &raven.User{ID: userID})
|
||||
|
||||
clientsMut.Lock()
|
||||
@@ -44,6 +39,7 @@ func sendReport(dsn, path string, report []byte, userID string) error {
|
||||
|
||||
cli, ok := clients[dsn]
|
||||
if !ok {
|
||||
var err error
|
||||
cli, err = raven.New(dsn)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -62,7 +58,7 @@ func sendReport(dsn, path string, report []byte, userID string) error {
|
||||
return <-errC
|
||||
}
|
||||
|
||||
func parseReport(path string, report []byte) (*raven.Packet, error) {
|
||||
func parseCrashReport(path string, report []byte) (*raven.Packet, error) {
|
||||
parts := bytes.SplitN(report, []byte("\n"), 2)
|
||||
if len(parts) != 2 {
|
||||
return nil, errors.New("no first line")
|
||||
@@ -126,35 +122,50 @@ func parseReport(path string, report []byte) (*raven.Packet, error) {
|
||||
}
|
||||
}
|
||||
|
||||
pkt := &raven.Packet{
|
||||
Message: string(subjectLine),
|
||||
Platform: "go",
|
||||
Release: version.tag,
|
||||
Environment: version.environment(),
|
||||
Tags: raven.Tags{
|
||||
raven.Tag{Key: "version", Value: version.version},
|
||||
raven.Tag{Key: "tag", Value: version.tag},
|
||||
raven.Tag{Key: "codename", Value: version.codename},
|
||||
raven.Tag{Key: "runtime", Value: version.runtime},
|
||||
raven.Tag{Key: "goos", Value: version.goos},
|
||||
raven.Tag{Key: "goarch", Value: version.goarch},
|
||||
raven.Tag{Key: "builder", Value: version.builder},
|
||||
},
|
||||
Extra: raven.Extra{
|
||||
"url": reportServer + path,
|
||||
},
|
||||
Interfaces: []raven.Interface{&trace},
|
||||
}
|
||||
if version.commit != "" {
|
||||
pkt.Tags = append(pkt.Tags, raven.Tag{Key: "commit", Value: version.commit})
|
||||
}
|
||||
for _, tag := range version.extra {
|
||||
pkt.Tags = append(pkt.Tags, raven.Tag{Key: tag, Value: "1"})
|
||||
pkt := packet(version)
|
||||
pkt.Message = string(subjectLine)
|
||||
pkt.Extra = raven.Extra{
|
||||
"url": reportServer + path,
|
||||
}
|
||||
pkt.Interfaces = []raven.Interface{&trace}
|
||||
pkt.Fingerprint = crashReportFingerprint(pkt.Message)
|
||||
|
||||
return pkt, nil
|
||||
}
|
||||
|
||||
var (
|
||||
indexRe = regexp.MustCompile(`\[[-:0-9]+\]`)
|
||||
sizeRe = regexp.MustCompile(`(length|capacity) [0-9]+`)
|
||||
ldbPosRe = regexp.MustCompile(`(\(pos=)([0-9]+)\)`)
|
||||
ldbChecksumRe = regexp.MustCompile(`(want=0x)([a-z0-9]+)( got=0x)([a-z0-9]+)`)
|
||||
ldbFileRe = regexp.MustCompile(`(\[file=)([0-9]+)(\.ldb\])`)
|
||||
ldbInternalKeyRe = regexp.MustCompile(`(internal key ")[^"]+(", len=)[0-9]+`)
|
||||
ldbPathRe = regexp.MustCompile(`(open|write|read) .+[\\/].+[\\/]index[^\\/]+[\\/][^\\/]+: `)
|
||||
)
|
||||
|
||||
func crashReportFingerprint(message string) []string {
|
||||
// Do not fingerprint on the stack in case of db corruption or fatal
|
||||
// db io error - where it occurs doesn't matter.
|
||||
orig := message
|
||||
message = ldbPosRe.ReplaceAllString(message, "${1}x)")
|
||||
message = ldbFileRe.ReplaceAllString(message, "${1}x${3}")
|
||||
message = ldbChecksumRe.ReplaceAllString(message, "${1}X${3}X")
|
||||
message = ldbInternalKeyRe.ReplaceAllString(message, "${1}x${2}x")
|
||||
message = ldbPathRe.ReplaceAllString(message, "$1 x: ")
|
||||
if message != orig {
|
||||
return []string{message}
|
||||
}
|
||||
|
||||
message = indexRe.ReplaceAllString(message, "[x]")
|
||||
message = sizeRe.ReplaceAllString(message, "$1 x")
|
||||
|
||||
// {{ default }} is what sentry uses as a fingerprint by default. While
|
||||
// never specified, the docs point at this being some hash derived from the
|
||||
// stack trace. Here we include the filtered panic message on top of that.
|
||||
// https://docs.sentry.io/platforms/go/data-management/event-grouping/sdk-fingerprinting/#basic-example
|
||||
return []string{"{{ default }}", message}
|
||||
}
|
||||
|
||||
// syncthing v1.1.4-rc.1+30-g6aaae618-dirty-crashrep "Erbium Earthworm" (go1.12.5 darwin-amd64) jb@kvin.kastelo.net 2019-05-23 16:08:14 UTC [foo, bar]
|
||||
var longVersionRE = regexp.MustCompile(`syncthing\s+(v[^\s]+)\s+"([^"]+)"\s\(([^\s]+)\s+([^-]+)-([^)]+)\)\s+([^\s]+)[^\[]*(?:\[(.+)\])?$`)
|
||||
|
||||
@@ -217,3 +228,27 @@ func parseVersion(line string) (version, error) {
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func packet(version version) *raven.Packet {
|
||||
pkt := &raven.Packet{
|
||||
Platform: "go",
|
||||
Release: version.tag,
|
||||
Environment: version.environment(),
|
||||
Tags: raven.Tags{
|
||||
raven.Tag{Key: "version", Value: version.version},
|
||||
raven.Tag{Key: "tag", Value: version.tag},
|
||||
raven.Tag{Key: "codename", Value: version.codename},
|
||||
raven.Tag{Key: "runtime", Value: version.runtime},
|
||||
raven.Tag{Key: "goos", Value: version.goos},
|
||||
raven.Tag{Key: "goarch", Value: version.goarch},
|
||||
raven.Tag{Key: "builder", Value: version.builder},
|
||||
},
|
||||
}
|
||||
if version.commit != "" {
|
||||
pkt.Tags = append(pkt.Tags, raven.Tag{Key: "commit", Value: version.commit})
|
||||
}
|
||||
for _, tag := range version.extra {
|
||||
pkt.Tags = append(pkt.Tags, raven.Tag{Key: tag, Value: "1"})
|
||||
}
|
||||
return pkt
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ func TestParseReport(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
pkt, err := parseReport("1/2/345", bs)
|
||||
pkt, err := parseCrashReport("1/2/345", bs)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -76,3 +76,66 @@ func TestParseReport(t *testing.T) {
|
||||
|
||||
fmt.Printf("%s\n", bs)
|
||||
}
|
||||
|
||||
func TestCrashReportFingerprint(t *testing.T) {
|
||||
cases := []struct {
|
||||
message, exp string
|
||||
ldb bool
|
||||
}{
|
||||
{
|
||||
message: "panic: leveldb/table: corruption on data-block (pos=51308946): checksum mismatch, want=0xa89f9aa0 got=0xd27cc4c7 [file=004003.ldb]",
|
||||
exp: "panic: leveldb/table: corruption on data-block (pos=x): checksum mismatch, want=0xX got=0xX [file=x.ldb]",
|
||||
ldb: true,
|
||||
},
|
||||
{
|
||||
message: "panic: leveldb/table: corruption on table-footer (pos=248): bad magic number [file=001370.ldb]",
|
||||
exp: "panic: leveldb/table: corruption on table-footer (pos=x): bad magic number [file=x.ldb]",
|
||||
ldb: true,
|
||||
},
|
||||
{
|
||||
message: "panic: runtime error: slice bounds out of range [4294967283:4194304]",
|
||||
exp: "panic: runtime error: slice bounds out of range [x]",
|
||||
},
|
||||
{
|
||||
message: "panic: runtime error: slice bounds out of range [-2:]",
|
||||
exp: "panic: runtime error: slice bounds out of range [x]",
|
||||
},
|
||||
{
|
||||
message: "panic: runtime error: slice bounds out of range [:4294967283] with capacity 32768",
|
||||
exp: "panic: runtime error: slice bounds out of range [x] with capacity x",
|
||||
},
|
||||
{
|
||||
message: "panic: runtime error: index out of range [0] with length 0",
|
||||
exp: "panic: runtime error: index out of range [x] with length x",
|
||||
},
|
||||
{
|
||||
message: `panic: leveldb: internal key "\x01", len=1: invalid length`,
|
||||
exp: `panic: leveldb: internal key "x", len=x: invalid length`,
|
||||
ldb: true,
|
||||
},
|
||||
{
|
||||
message: `panic: write /var/syncthing/config/index-v0.14.0.db/2732813.log: cannot allocate memory`,
|
||||
exp: `panic: write x: cannot allocate memory`,
|
||||
ldb: true,
|
||||
},
|
||||
{
|
||||
message: `panic: filling Blocks: read C:\Users\Serv-Resp-Tizayuca\AppData\Local\Syncthing\index-v0.14.0.db\006561.ldb: Error de datos (comprobación de redundancia cíclica).`,
|
||||
exp: `panic: filling Blocks: read x: Error de datos (comprobación de redundancia cíclica).`,
|
||||
ldb: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
fingerprint := crashReportFingerprint(tc.message)
|
||||
|
||||
expLen := 2
|
||||
if tc.ldb {
|
||||
expLen = 1
|
||||
}
|
||||
if l := len(fingerprint); l != expLen {
|
||||
t.Errorf("tc %v: Unexpected fingerprint length: %v != %v", i, l, expLen)
|
||||
} else if msg := fingerprint[expLen-1]; msg != tc.exp {
|
||||
t.Errorf("tc %v:\n\"%v\" !=\n\"%v\"", i, msg, tc.exp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,52 +4,21 @@
|
||||
// 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/.
|
||||
|
||||
// Command stcrashreceiver is a trivial HTTP server that allows two things:
|
||||
//
|
||||
// - uploading files (crash reports) named like a SHA256 hash using a PUT request
|
||||
// - checking whether such file exists using a HEAD request
|
||||
//
|
||||
// Typically this should be deployed behind something that manages HTTPS.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/sha256"
|
||||
)
|
||||
|
||||
const maxRequestSize = 1 << 20 // 1 MiB
|
||||
|
||||
func main() {
|
||||
dir := flag.String("dir", ".", "Directory to store reports in")
|
||||
dsn := flag.String("dsn", "", "Sentry DSN")
|
||||
listen := flag.String("listen", ":22039", "HTTP listen address")
|
||||
flag.Parse()
|
||||
|
||||
cr := &crashReceiver{
|
||||
dir: *dir,
|
||||
dsn: *dsn,
|
||||
}
|
||||
|
||||
log.SetOutput(os.Stdout)
|
||||
if err := http.ListenAndServe(*listen, cr); err != nil {
|
||||
log.Fatalln("HTTP serve:", err)
|
||||
}
|
||||
}
|
||||
|
||||
type crashReceiver struct {
|
||||
dir string
|
||||
dsn string
|
||||
@@ -155,8 +124,13 @@ func (r *crashReceiver) servePut(reportID, fullPath string, w http.ResponseWrite
|
||||
|
||||
go func() {
|
||||
// There's no need for the client to have to wait for this part.
|
||||
if err := sendReport(r.dsn, reportID, bs, user); err != nil {
|
||||
log.Println("Failed to send report:", err)
|
||||
pkt, err := parseCrashReport(reportID, bs)
|
||||
if err != nil {
|
||||
log.Println("Failed to parse crash report:", err)
|
||||
return
|
||||
}
|
||||
if err := sendReport(r.dsn, pkt, user); err != nil {
|
||||
log.Println("Failed to send crash report:", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -166,20 +140,3 @@ func (r *crashReceiver) servePut(reportID, fullPath string, w http.ResponseWrite
|
||||
func (r *crashReceiver) dirFor(base string) string {
|
||||
return filepath.Join(base[0:2], base[2:4])
|
||||
}
|
||||
|
||||
// userIDFor returns a string we can use as the user ID for the purpose of
|
||||
// counting affected users. It's the truncated hash of a salt, the user
|
||||
// remote IP, and the current month.
|
||||
func userIDFor(req *http.Request) string {
|
||||
addr := req.RemoteAddr
|
||||
if fwd := req.Header.Get("x-forwarded-for"); fwd != "" {
|
||||
addr = fwd
|
||||
}
|
||||
if host, _, err := net.SplitHostPort(addr); err == nil {
|
||||
addr = host
|
||||
}
|
||||
now := time.Now().Format("200601")
|
||||
salt := "stcrashreporter"
|
||||
hash := sha256.Sum256([]byte(salt + addr + now))
|
||||
return fmt.Sprintf("%x", hash[:8])
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
|
||||
"github.com/oschwald/geoip2-golang"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/upgrade"
|
||||
"github.com/syncthing/syncthing/lib/ur/contract"
|
||||
)
|
||||
|
||||
@@ -753,6 +754,8 @@ func getReport(db *sql.DB) map[string]interface{} {
|
||||
add(featureGroups["Folder"]["v3"], "Pull Order", prettyCase(key), value)
|
||||
}
|
||||
|
||||
inc(features["Device"]["v3"], "Untrusted", rep.DeviceUsesV3.Untrusted)
|
||||
|
||||
totals["GUI"] += rep.GUIStats.Enabled
|
||||
|
||||
inc(features["GUI"]["v3"], "Auth Enabled", rep.GUIStats.UseAuth)
|
||||
@@ -919,7 +922,7 @@ func getReport(db *sql.DB) map[string]interface{} {
|
||||
}
|
||||
|
||||
var (
|
||||
plusRe = regexp.MustCompile(`\+.*$`)
|
||||
plusRe = regexp.MustCompile(`(\+.*|\.dev\..*)$`)
|
||||
plusStr = "(+dev)"
|
||||
)
|
||||
|
||||
@@ -978,7 +981,9 @@ func (s *summary) MarshalJSON() ([]byte, error) {
|
||||
for v := range s.versions {
|
||||
versions = append(versions, v)
|
||||
}
|
||||
sort.Strings(versions)
|
||||
sort.Slice(versions, func(a, b int) bool {
|
||||
return upgrade.CompareVersions(versions[a], versions[b]) < 0
|
||||
})
|
||||
|
||||
var filtered []string
|
||||
for _, v := range versions {
|
||||
|
||||
45
go.mod
45
go.mod
@@ -3,52 +3,51 @@ module github.com/syncthing/syncthing
|
||||
require (
|
||||
github.com/AudriusButkevicius/pfilter v0.0.0-20190627213056-c55ef6137fc6
|
||||
github.com/AudriusButkevicius/recli v0.0.5
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
|
||||
github.com/bkaradzic/go-lz4 v0.0.0-20160924222819-7224d8d8f27e
|
||||
github.com/calmh/xdr v1.1.0
|
||||
github.com/ccding/go-stun v0.0.0-20180726100737-be486d185f3d
|
||||
github.com/certifi/gocertifi v0.0.0-20190905060710-a5e0173ced67 // indirect
|
||||
github.com/ccding/go-stun v0.1.2
|
||||
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 // indirect
|
||||
github.com/chmduquesne/rollinghash v0.0.0-20180912150627-a60f8e7142b5
|
||||
github.com/d4l3k/messagediff v1.2.1
|
||||
github.com/dchest/siphash v1.2.1
|
||||
github.com/dchest/siphash v1.2.2
|
||||
github.com/dgraph-io/badger/v2 v2.0.3
|
||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568
|
||||
github.com/getsentry/raven-go v0.2.0
|
||||
github.com/go-ldap/ldap/v3 v3.2.0
|
||||
github.com/go-ldap/ldap/v3 v3.2.4
|
||||
github.com/go-ole/go-ole v1.2.4 // indirect
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/gogo/protobuf v1.3.1
|
||||
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9
|
||||
github.com/golang/protobuf v1.4.2
|
||||
github.com/greatroar/blobloom v0.3.0
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e
|
||||
github.com/golang/protobuf v1.4.3
|
||||
github.com/greatroar/blobloom v0.5.0
|
||||
github.com/jackpal/gateway v1.0.6
|
||||
github.com/jackpal/go-nat-pmp v1.0.2
|
||||
github.com/julienschmidt/httprouter v1.3.0
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||
github.com/kr/pretty v0.2.0 // indirect
|
||||
github.com/lib/pq v1.2.0
|
||||
github.com/lucas-clemente/quic-go v0.18.0
|
||||
github.com/lib/pq v1.8.0
|
||||
github.com/lucas-clemente/quic-go v0.18.1
|
||||
github.com/maruel/panicparse v1.5.1
|
||||
github.com/mattn/go-isatty v0.0.12
|
||||
github.com/minio/sha256-simd v0.1.1
|
||||
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75
|
||||
github.com/oschwald/geoip2-golang v1.4.0
|
||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.2.1
|
||||
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563
|
||||
github.com/prometheus/client_golang v1.8.0
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0
|
||||
github.com/sasha-s/go-deadlock v0.2.0
|
||||
github.com/shirou/gopsutil v2.20.7+incompatible
|
||||
github.com/syncthing/notify v0.0.0-20190709140112-69c7a957d3e2
|
||||
github.com/shirou/gopsutil v3.20.10+incompatible
|
||||
github.com/syncthing/notify v0.0.0-20201109091751-9a0e44181151
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20200815071216-d9e9293bd0f7
|
||||
github.com/thejerf/suture v3.0.2+incompatible
|
||||
github.com/urfave/cli v1.22.2
|
||||
github.com/thejerf/suture v4.0.0+incompatible
|
||||
github.com/urfave/cli v1.22.4
|
||||
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0
|
||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de
|
||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc
|
||||
golang.org/x/sys v0.0.0-20200819171115-d785dc25833f
|
||||
golang.org/x/text v0.3.3
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
|
||||
google.golang.org/protobuf v1.25.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102
|
||||
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1
|
||||
golang.org/x/text v0.3.4
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e
|
||||
)
|
||||
|
||||
go 1.14
|
||||
|
||||
400
go.sum
400
go.sum
@@ -16,76 +16,103 @@ github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzS
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM=
|
||||
github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
|
||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bkaradzic/go-lz4 v0.0.0-20160924222819-7224d8d8f27e h1:2augTYh6E+XoNrrivZJBadpThP/dsvYKj0nzqfQ8tM4=
|
||||
github.com/bkaradzic/go-lz4 v0.0.0-20160924222819-7224d8d8f27e/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
|
||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625 h1:ckJgFhFWywOx+YLEMIJsTb+NV6NexWICk5+AMSuz3ss=
|
||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/calmh/xdr v1.1.0 h1:U/Dd4CXNLoo8EiQ4ulJUXkgO1/EyQLgDKLgpY1SOoJE=
|
||||
github.com/calmh/xdr v1.1.0/go.mod h1:E8sz2ByAdXC8MbANf1LCRYzedSnnc+/sXXJs/PVqoeg=
|
||||
github.com/ccding/go-stun v0.0.0-20180726100737-be486d185f3d h1:As4937T5NVbJ/DmZT9z33pyLEprMd6CUSfhbmMY57Io=
|
||||
github.com/ccding/go-stun v0.0.0-20180726100737-be486d185f3d/go.mod h1:3FK1bMar37f7jqVY7q/63k3OMX1c47pGCufzt3X0sYE=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/ccding/go-stun v0.1.2 h1:1CZhjVwfyO/jGxk06a+0OSOGBWZu588kuZQQO4nihsw=
|
||||
github.com/ccding/go-stun v0.1.2/go.mod h1:3FK1bMar37f7jqVY7q/63k3OMX1c47pGCufzt3X0sYE=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/certifi/gocertifi v0.0.0-20190905060710-a5e0173ced67 h1:8k9FLYBLKT+9v2HQJ/a95ZemmTx+/ltJcAiRhVushG8=
|
||||
github.com/certifi/gocertifi v0.0.0-20190905060710-a5e0173ced67/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4=
|
||||
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI=
|
||||
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.0 h1:yTUvW7Vhb89inJ+8irsUqiWjh8iT6sQPZiQzI6ReGkA=
|
||||
github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
|
||||
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||
github.com/chmduquesne/rollinghash v0.0.0-20180912150627-a60f8e7142b5 h1:Wg96Dh0MLTanEaPO0OkGtUIaa2jOnShAIOVUIzRHUxo=
|
||||
github.com/chmduquesne/rollinghash v0.0.0-20180912150627-a60f8e7142b5/go.mod h1:Uc2I36RRfTAf7Dge82bi3RU0OQUmXT9iweIcPqvr8A0=
|
||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/d4l3k/messagediff v1.2.1 h1:ZcAIMYsUg0EAp9X+tt8/enBE/Q8Yd5kzPynLyKptt9U=
|
||||
github.com/d4l3k/messagediff v1.2.1/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dchest/siphash v1.2.1 h1:4cLinnzVJDKxTCl9B01807Yiy+W7ZzVHj/KIroQRvT4=
|
||||
github.com/dchest/siphash v1.2.1/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4=
|
||||
github.com/dchest/siphash v1.2.2 h1:9DFz8tQwl9pTVt5iok/9zKyzA1Q6bRGiF3HPiEEVr9I=
|
||||
github.com/dchest/siphash v1.2.2/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4=
|
||||
github.com/dgraph-io/badger/v2 v2.0.3 h1:inzdf6VF/NZ+tJ8RwwYMjJMvsOALTHYdozn0qSl6XJI=
|
||||
github.com/dgraph-io/badger/v2 v2.0.3/go.mod h1:3KY8+bsP8wI0OEnQJAKpd4wIJW/Mm32yw2j/9FUVnIM=
|
||||
github.com/dgraph-io/ristretto v0.0.2-0.20200115201040-8f368f2f2ab3 h1:MQLRM35Pp0yAyBYksjbj1nZI/w6eyRY/mWoM1sFf4kU=
|
||||
github.com/dgraph-io/ristretto v0.0.2-0.20200115201040-8f368f2f2ab3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWTLOJKlh+lOBt6nUQgXAfB7oVIQt5cNreqSLI=
|
||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
|
||||
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
@@ -93,105 +120,147 @@ github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JY
|
||||
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.0 h1:/S4hO/AO6tLMlPX0oftGSOcdGJJN/MuYzfgWRMn199E=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.0/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-ldap/ldap/v3 v3.2.0 h1:fkS0nXg43MZvU0UNTOGyQv60WdwHRXa1eX0CSzuKLvY=
|
||||
github.com/go-ldap/ldap/v3 v3.2.0/go.mod h1:dtLsnBXnSLIsMRbCBuRpHflCGaYzZ5jn+x1q7XqMTKU=
|
||||
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
|
||||
github.com/go-ldap/ldap/v3 v3.2.4 h1:PFavAq2xTgzo/loE8qNXcQaofAaqIpI4WgaLdv+1l3E=
|
||||
github.com/go-ldap/ldap/v3 v3.2.4/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
|
||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9 h1:uHTyIjqVhYRhLbJ8nIiOJHkEZZ+5YoOsAbD3sk82NiE=
|
||||
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.4.0 h1:Rd1kQnQu0Hq3qvJppYSG0HtP+f5LPPUiDswTLiEegLg=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/greatroar/blobloom v0.3.0 h1:TSf9vu9lZ840bnMXNFpFKe61AISBZL5a9uRL62KixCY=
|
||||
github.com/greatroar/blobloom v0.3.0/go.mod h1:we9vO6GNYMmsNvCWINtZnQbcGEHUT6hGBAznNHd6RlE=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/greatroar/blobloom v0.5.0 h1:jNbCsgDpZ23AI6jgZsXm7oFatkFaLCxr+ZWzlYasONU=
|
||||
github.com/greatroar/blobloom v0.5.0/go.mod h1:M+yFtr/P96aNZYDYowvNWL3WdDluSMK2PPPHN49LMw8=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/jackpal/gateway v1.0.6 h1:/MJORKvJEwNVldtGVJC2p2cwCnsSoLn3hl3zxmZT7tk=
|
||||
github.com/jackpal/gateway v1.0.6/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lucas-clemente/quic-go v0.18.0 h1:JhQDdqxdwdmGdKsKgXi1+coHRoGhvU6z0rNzOJqZ/4o=
|
||||
github.com/lucas-clemente/quic-go v0.18.0/go.mod h1:yXttHsSNxQi8AWijC/vLP+OJczXqzHSOcJrM5ITUlCg=
|
||||
github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg=
|
||||
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||
github.com/lucas-clemente/quic-go v0.18.1 h1:DMR7guC0NtVS8zNZR3IO7NARZvZygkSC56GGtC6cyys=
|
||||
github.com/lucas-clemente/quic-go v0.18.1/go.mod h1:yXttHsSNxQi8AWijC/vLP+OJczXqzHSOcJrM5ITUlCg=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/marten-seemann/qpack v0.2.0/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
|
||||
@@ -199,94 +268,139 @@ github.com/marten-seemann/qtls v0.10.0 h1:ECsuYUKalRL240rRD4Ri33ISb7kAQ3qGDlrrl5
|
||||
github.com/marten-seemann/qtls v0.10.0/go.mod h1:UvMd1oaYDACI99/oZUYLzMCkBXQVT0aGm99sJhbT8hs=
|
||||
github.com/marten-seemann/qtls-go1-15 v0.1.0 h1:i/YPXVxz8q9umso/5y474CNcHmTpA+5DH+mFPjx6PZg=
|
||||
github.com/marten-seemann/qtls-go1-15 v0.1.0/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I=
|
||||
github.com/maruel/panicparse v1.3.0 h1:1Ep/RaYoSL1r5rTILHQQbyzHG8T4UP5ZbQTYTo4bdDc=
|
||||
github.com/maruel/panicparse v1.3.0/go.mod h1:vszMjr5QQ4F5FSRfraldcIA/BCw5xrdLL+zEcU2nRBs=
|
||||
github.com/maruel/panicparse v1.5.1 h1:hUPcXI7ubtEqj/k+P34KsHQqb86zuVk7zBfkP6tBBPc=
|
||||
github.com/maruel/panicparse v1.5.1/go.mod h1:aOutY/MUjdj80R0AEVI9qE2zHqig+67t2ffUDDiLzAM=
|
||||
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
|
||||
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75 h1:cUVxyR+UfmdEAZGJ8IiKld1O0dbGotEnkMolG5hfMSY=
|
||||
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75/go.mod h1:pBbZyGwC5i16IBkjVKoy/sznA8jPD/K9iedwe1ESE6w=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
|
||||
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
|
||||
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
|
||||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
|
||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
|
||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/oschwald/geoip2-golang v1.4.0 h1:5RlrjCgRyIGDz/mBmPfnAF4h8k0IAcRv9PvrpOfz+Ug=
|
||||
github.com/oschwald/geoip2-golang v1.4.0/go.mod h1:8QwxJvRImBH+Zl6Aa6MaIcs5YdlZSTKtzmPGzQqi9ng=
|
||||
github.com/oschwald/maxminddb-golang v1.6.0 h1:KAJSjdHQ8Kv45nFIbtoLGrGWqHFajOIm7skTyz/+Dls=
|
||||
github.com/oschwald/maxminddb-golang v1.6.0/go.mod h1:DUJFucBg2cvqx42YmDa/+xHvb0elJtOm3o4aFQ/nb/w=
|
||||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ=
|
||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI=
|
||||
github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
|
||||
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.8.0 h1:zvJNkoCFAnYFNC24FV8nW4JdRJ3GIFcLbg65lL/JDcw=
|
||||
github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
|
||||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.14.0 h1:RHRyE8UocrbjU+6UvRzwi6HjiDfxrrBU91TtbKzkGp4=
|
||||
github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
|
||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
|
||||
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563 h1:dY6ETXrvDG7Sa4vE8ZQG4yqWg6UnOcbqTAahkV813vQ=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
|
||||
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/sasha-s/go-deadlock v0.2.0 h1:lMqc+fUb7RrFS3gQLtoQsJ7/6TV/pAIFvBsqX73DK8Y=
|
||||
github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shirou/gopsutil v2.20.7+incompatible h1:Ymv4OD12d6zm+2yONe39VSmp2XooJe8za7ngOLW/o/w=
|
||||
github.com/shirou/gopsutil v2.20.7+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shirou/gopsutil v3.20.10+incompatible h1:kQuRhh6h6y4luXvnmtu/lJEGtdJ3q8lbu9NQY99GP+o=
|
||||
github.com/shirou/gopsutil v3.20.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
|
||||
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
|
||||
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
|
||||
@@ -312,8 +426,12 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
|
||||
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
|
||||
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
||||
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
|
||||
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
@@ -321,133 +439,166 @@ github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0b
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/syncthing/notify v0.0.0-20190709140112-69c7a957d3e2 h1:6tuEEEpg+mxM82E0YingzoXzXXISYR/o/7I9n573LWI=
|
||||
github.com/syncthing/notify v0.0.0-20190709140112-69c7a957d3e2/go.mod h1:Sn4ChoS7e4FxjCN1XHPVBT43AgnRLbuaB8pEc1Zcdjg=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/syncthing/notify v0.0.0-20201101120444-a28a0bd0f5ee h1:Q2dajND8VmNqXOi+N3IQQP77VkuXMA7tvPzXosDS1vA=
|
||||
github.com/syncthing/notify v0.0.0-20201101120444-a28a0bd0f5ee/go.mod h1:Sn4ChoS7e4FxjCN1XHPVBT43AgnRLbuaB8pEc1Zcdjg=
|
||||
github.com/syncthing/notify v0.0.0-20201109091751-9a0e44181151 h1:aKnLuEFWn/7u42UR82PxsPOMkoBAhq+06oRtUnK3Z1o=
|
||||
github.com/syncthing/notify v0.0.0-20201109091751-9a0e44181151/go.mod h1:Sn4ChoS7e4FxjCN1XHPVBT43AgnRLbuaB8pEc1Zcdjg=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20200815071216-d9e9293bd0f7 h1:udtnv1cokhJYqnUfCMCppJ71bFN9VKfG1BQ6UsYZnx8=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20200815071216-d9e9293bd0f7/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
github.com/thejerf/suture v3.0.2+incompatible h1:GtMydYcnK4zBJ0KL6Lx9vLzl6Oozb65wh252FTBxrvM=
|
||||
github.com/thejerf/suture v3.0.2+incompatible/go.mod h1:ibKwrVj+Uzf3XZdAiNWUouPaAbSoemxOHLmJmwheEMc=
|
||||
github.com/thejerf/suture v4.0.0+incompatible h1:luAwgEo87y1X30wEYa64N4SKMrsAm9qXRwNxnLVuuwg=
|
||||
github.com/thejerf/suture v4.0.0+incompatible/go.mod h1:ibKwrVj+Uzf3XZdAiNWUouPaAbSoemxOHLmJmwheEMc=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=
|
||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA=
|
||||
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0 h1:okhMind4q9H1OxF44gNegWkiP4H/gsTFLalHFa4OOUI=
|
||||
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0/go.mod h1:TTbGUfE+cXXceWtbTHq6lqcTvYPBKLNejBEbnUsQJtU=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig=
|
||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc h1:zK/HqS5bZxDptfPJNq8v7vJfXtkU7r9TLIoSr1bXaP4=
|
||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102 h1:42cLlJJdEh+ySyeUUbEQ5bsTiq8voBeTuweGVkY6Puw=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY=
|
||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191224085550-c709ea063b76 h1:Dho5nD6R3PcW2SH1or8vS0dszDaXRxIw55lBX7XiE5g=
|
||||
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191224085550-c709ea063b76/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200819171115-d785dc25833f h1:KJuwZVtZBVzDmEDtB2zro9CXkD9O0dpCv4o2LHbQIAw=
|
||||
golang.org/x/sys v0.0.0-20200819171115-d785dc25833f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 h1:a/mKvvZr9Jcc8oKfcmgzyp7OwF73JPWsQLvH1z2Kxck=
|
||||
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s=
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -455,15 +606,23 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
@@ -473,53 +632,60 @@ google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoA
|
||||
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
||||
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
|
||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
|
||||
|
||||
@@ -21,7 +21,7 @@ ul+h5 {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
#content {
|
||||
.content {
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
@@ -421,3 +421,11 @@ ul.three-columns li, ul.two-columns li {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.form-horizontal .form-group {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.form-horizontal {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
@@ -27,27 +27,27 @@
|
||||
"Are you sure you want to remove device {%name%}?": "Er du sikker på, at du vil fjerne enheden {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Er du sikker på, at du vil fjerne mappen {{label}}?",
|
||||
"Are you sure you want to restore {%count%} files?": "Er du sikker på, at du vil genskabe {{count}} filer?",
|
||||
"Are you sure you want to upgrade?": "Are you sure you want to upgrade?",
|
||||
"Are you sure you want to upgrade?": "Opgradere?",
|
||||
"Auto Accept": "Autoacceptér",
|
||||
"Automatic Crash Reporting": "Automatic Crash Reporting",
|
||||
"Automatic Crash Reporting": "Automatisk nedbrud rapportering",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Den automatiske opdatering tilbyder nu valget mellem stabile udgivelser og udgivelseskandidater.",
|
||||
"Automatic upgrades": "Automatisk opdatering",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "Automatic upgrades are always enabled for candidate releases.",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "Automatisk opgradering er altid aktiveret for kandidat udgivelser",
|
||||
"Automatically create or share folders that this device advertises at the default path.": "Opret eller del automatisk mapper på standardstien, som denne enhed tilbyder.",
|
||||
"Available debug logging facilities:": "Tilgængelige faciliteter for fejlretningslogning:",
|
||||
"Be careful!": "Vær forsigtig!",
|
||||
"Bugs": "Fejl",
|
||||
"Changelog": "Udgivelsesnoter",
|
||||
"Clean out after": "Rens efter",
|
||||
"Cleaning Versions": "Cleaning Versions",
|
||||
"Cleanup Interval": "Cleanup Interval",
|
||||
"Cleaning Versions": "Rydder op i versioner",
|
||||
"Cleanup Interval": "Ryd op interval",
|
||||
"Click to see discovery failures": "Klik for at se opdagelsesfejl",
|
||||
"Close": "Luk",
|
||||
"Command": "Kommando",
|
||||
"Comment, when used at the start of a line": "Kommentar, når den bruges i starten af en linje",
|
||||
"Compression": "Anvend komprimering",
|
||||
"Configured": "Konfigureret",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connected (Unused)": "Tilsluttet (ubrugt)",
|
||||
"Connection Error": "Tilslutnings fejl",
|
||||
"Connection Type": "Tilslutningstype",
|
||||
"Connections": "Forbindelser",
|
||||
@@ -56,13 +56,13 @@
|
||||
"Copied from original": "Kopieret fra originalen",
|
||||
"Copyright © 2014-2019 the following Contributors:": "Copyright © 2014-2019 de følgende bidragsydere:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Opretter ignoreringsmønstre; overskriver en eksisterende fil på {{path}}.",
|
||||
"Currently Shared With Devices": "Currently Shared With Devices",
|
||||
"Currently Shared With Devices": "i øjeblikket delt med enheder",
|
||||
"Danger!": "Fare!",
|
||||
"Debugging Facilities": "Faciliteter til fejlretning",
|
||||
"Default Folder Path": "Standardmappesti",
|
||||
"Deleted": "Slettet",
|
||||
"Deselect All": "Fravælg alle",
|
||||
"Deselect devices to stop sharing this folder with.": "Deselect devices to stop sharing this folder with.",
|
||||
"Deselect devices to stop sharing this folder with.": "Fravælg enheder for at stoppe mappe deling.",
|
||||
"Device": "Enhed",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Enheden “{{name}}” ({{device}} på {{address}}) vil gerne forbinde. Tilføj denne enhed?",
|
||||
"Device ID": "Enheds-ID",
|
||||
@@ -71,7 +71,7 @@
|
||||
"Device rate limits": "Enhedens hastighedsbegrænsning",
|
||||
"Device that last modified the item": "Enhed, som sidst ændrede filen",
|
||||
"Devices": "Enheder",
|
||||
"Disable Crash Reporting": "Disable Crash Reporting",
|
||||
"Disable Crash Reporting": "Deaktivere nedbrud rapportering",
|
||||
"Disabled": "Deaktiveret",
|
||||
"Disabled periodic scanning and disabled watching for changes": "Deaktiverede periodisk skanning og deaktiverede overvågning af ændringer",
|
||||
"Disabled periodic scanning and enabled watching for changes": "Deaktiverede periodisk skanning og aktiverede overvågning af ændringer",
|
||||
@@ -79,7 +79,7 @@
|
||||
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).",
|
||||
"Discard": "Behold ikke",
|
||||
"Disconnected": "Ikke tilsluttet",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Disconnected (Unused)": "Ikke tilsluttet (ubrugt)",
|
||||
"Discovered": "Opdaget",
|
||||
"Discovery": "Opslag",
|
||||
"Discovery Failures": "Fejl ved opdagelse",
|
||||
@@ -91,10 +91,10 @@
|
||||
"Downloaded": "Downloadet",
|
||||
"Downloading": "Downloader",
|
||||
"Edit": "Redigér",
|
||||
"Edit Device": "Edit Device",
|
||||
"Edit Folder": "Edit Folder",
|
||||
"Edit Device": "Redigere enhed",
|
||||
"Edit Folder": "Redigere mappe",
|
||||
"Editing {%path%}.": "Redigerer {{path}}.",
|
||||
"Enable Crash Reporting": "Enable Crash Reporting",
|
||||
"Enable Crash Reporting": "Aktivere nedbrud rapportering",
|
||||
"Enable NAT traversal": "Aktivér NAT-traversering",
|
||||
"Enable Relaying": "Aktivér videresending",
|
||||
"Enabled": "Aktiveret",
|
||||
@@ -102,7 +102,7 @@
|
||||
"Enter a non-privileged port number (1024 - 65535).": "Indtast et ikke-priviligeret portnummer (1024–65535).",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Angiv en kommaadskilt adresseliste (\"tcp://ip:port\", \"tcp://host:port\") eller \"dynamic\" for automatisk at opdage adressen.",
|
||||
"Enter ignore patterns, one per line.": "Indtast ignoreringsmønstre, ét per linje.",
|
||||
"Enter up to three octal digits.": "Enter up to three octal digits.",
|
||||
"Enter up to three octal digits.": "Indtast op til tre oktale cifre.",
|
||||
"Error": "Fejl",
|
||||
"External File Versioning": "Ekstern filversionering",
|
||||
"Failed Items": "Mislykkede filer",
|
||||
@@ -128,10 +128,10 @@
|
||||
"GUI": "GUI",
|
||||
"GUI Authentication Password": "GUI-adgangskode",
|
||||
"GUI Authentication User": "GUI-brugernavn",
|
||||
"GUI Authentication: Set User and Password": "GUI Authentication: Set User and Password",
|
||||
"GUI Authentication: Set User and Password": "GUI godkendelse: Angiv bruger og adgangskode",
|
||||
"GUI Listen Address": "GUI-lytteadresse",
|
||||
"GUI Theme": "GUI-tema",
|
||||
"General": "Generalt",
|
||||
"General": "Generelt",
|
||||
"Generate": "Opret",
|
||||
"Global Discovery": "Globalt opslag",
|
||||
"Global Discovery Servers": "Globale opslagsservere",
|
||||
@@ -162,13 +162,13 @@
|
||||
"Listeners": "Lyttere",
|
||||
"Loading data...": "Indlæser data ...",
|
||||
"Loading...": "Indlæser ...",
|
||||
"Local Additions": "Local Additions",
|
||||
"Local Additions": "Lokale tilføjelser",
|
||||
"Local Discovery": "Lokal opslag",
|
||||
"Local State": "Lokal tilstand",
|
||||
"Local State (Total)": "Lokal tilstand (total)",
|
||||
"Locally Changed Items": "Lokalt ændrede filer",
|
||||
"Log": "Logbog",
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "Log tailing paused. Scroll to the bottom to continue.",
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "Log sammenkædning er i pause. Rul til bunden for at fortsætte.",
|
||||
"Logs": "Logbog",
|
||||
"Major Upgrade": "Opgradering til ny hovedversion",
|
||||
"Mass actions": "Massehandlinger",
|
||||
@@ -204,7 +204,7 @@
|
||||
"Pause": "Pause",
|
||||
"Pause All": "Sæt alt på pause",
|
||||
"Paused": "På pause",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Paused (Unused)": "Pauset (ubrugt)",
|
||||
"Pending changes": "Ventende ændringer",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodisk skanning med et givent interval og deaktiveret overvågning af ændringer",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodisk skanning med et givent interval og aktiveret overvågning af ændringer",
|
||||
@@ -215,7 +215,7 @@
|
||||
"Please wait": "Vent venligst",
|
||||
"Prefix indicating that the file can be deleted if preventing directory removal": "Forstavelse, der indikerer, at filen kan slettes, hvis fjernelse at mappe undgåes",
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "Forstavelse, der indikerer det mønster, der skal sammenlignes uden versalfølsomhed",
|
||||
"Preparing to Sync": "Preparing to Sync",
|
||||
"Preparing to Sync": "Forbereder synkronisering",
|
||||
"Preview": "Forhåndsvisning",
|
||||
"Preview Usage Report": "Forhåndsvisning af forbrugsrapport",
|
||||
"Quick guide to supported patterns": "Kvikguide til understøttede mønstre",
|
||||
@@ -287,7 +287,7 @@
|
||||
"Syncing": "Synkroniserer",
|
||||
"Syncthing has been shut down.": "Syncthing er lukket ned.",
|
||||
"Syncthing includes the following software or portions thereof:": "Syncthing indeholder følgende software eller dele heraf:",
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing is Free and Open Source Software licensed as MPL v2.0.",
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing er fri og åben kildekode software licenseret som MPL v2.0.",
|
||||
"Syncthing is restarting.": "Syncthing genstarter.",
|
||||
"Syncthing is upgrading.": "Syncthing opgraderer.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.",
|
||||
@@ -295,10 +295,10 @@
|
||||
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Det ser ud til, at Syncthing har problemer med at udføre opgaven. Prøv at genindlæse siden eller genstarte Synching, hvis problemet vedbliver.",
|
||||
"Take me back": "Tag mig tilbage",
|
||||
"The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.": "The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.",
|
||||
"The Syncthing Authors": "The Syncthing Authors",
|
||||
"The Syncthing Authors": "Syncthing udviklere",
|
||||
"The Syncthing admin interface is configured to allow remote access without a password.": "Syncthing-administationsfladen er sat op til at kunne fjernstyres uden adgangskode.",
|
||||
"The aggregated statistics are publicly available at the URL below.": "Den indsamlede statistik er offentligt tilgængelig på den nedenstående URL.",
|
||||
"The cleanup interval cannot be blank.": "The cleanup interval cannot be blank.",
|
||||
"The cleanup interval cannot be blank.": "Ryd op interval kan ikke være tom.",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Konfigurationen er gemt, men ikke aktiveret. Syncthing skal genstarte for at aktivere den nye konfiguration.",
|
||||
"The device ID cannot be blank.": "Enhedens ID må ikke være tom.",
|
||||
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "Det enheds-ID, som skal indtastes her, kan findes under menuen “Handlinger > Vis ID” på den anden enhed. Mellemrum og bindestreger er valgfri (ignoreres).",
|
||||
@@ -310,7 +310,7 @@
|
||||
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "De følgende intervaller er brugt: Inden for den første time bliver en version gemt hvert 30. sekund, inden for den første dag bliver en version gemt hver time, inden for de første 30 dage bliver en version gemt hver dag, og indtil den maksimale alder bliver en version gemt hver uge.",
|
||||
"The following items could not be synchronized.": "Følgende filer kunne ikke synkroniseres.",
|
||||
"The following items were changed locally.": "De følgende filer er ændret lokalt.",
|
||||
"The interval must be a positive number of seconds.": "The interval must be a positive number of seconds.",
|
||||
"The interval must be a positive number of seconds.": "Intervallet skal være et positivt antal sekunder.",
|
||||
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.",
|
||||
"The maximum age must be a number and cannot be blank.": "Maksimal alder skal være et tal og feltet må ikke være tomt.",
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Den maksimale tid, en version skal gemmes (i dage; sæt lig med 0 for at beholde gamle versioner for altid).",
|
||||
@@ -321,7 +321,7 @@
|
||||
"The path cannot be blank.": "Stien må ikke være tom.",
|
||||
"The rate limit must be a non-negative number (0: no limit)": "Hastighedsbegrænsningen skal være et ikke-negativt tal (0: ingen begrænsning)",
|
||||
"The rescan interval must be a non-negative number of seconds.": "Genskanningsintervallet skal være et ikke-negativt antal sekunder.",
|
||||
"There are no devices to share this folder with.": "There are no devices to share this folder with.",
|
||||
"There are no devices to share this folder with.": "Der er ingen enheder at dele denne mappe med.",
|
||||
"They are retried automatically and will be synced when the error is resolved.": "De prøves igen automatisk og vil blive synkroniseret, når fejlen er løst.",
|
||||
"This Device": "Denne enhed",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "Dette gør det nemt for hackere at få adgang til at læse og ændre filer på din computer.",
|
||||
@@ -331,14 +331,14 @@
|
||||
"Time the item was last modified": "Tidspunkt for seneste ændring af filen",
|
||||
"Trash Can File Versioning": "Versionering med papirkurv",
|
||||
"Type": "Type",
|
||||
"UNIX Permissions": "UNIX Permissions",
|
||||
"UNIX Permissions": "UNIX rettigheder",
|
||||
"Unavailable": "Ikke tilgængelig",
|
||||
"Unavailable/Disabled by administrator or maintainer": "Ikke tilgængelig / deaktiveret af administrator eller vedligeholder",
|
||||
"Undecided (will prompt)": "Ubestemt (du bliver spurgt)",
|
||||
"Unignore": "Fjern ignorering",
|
||||
"Unknown": "Ukendt",
|
||||
"Unshared": "Ikke delt",
|
||||
"Unshared Devices": "Unshared Devices",
|
||||
"Unshared Devices": "Ikke delte enheder",
|
||||
"Up to Date": "Fuldt opdateret",
|
||||
"Updated": "Opdateret",
|
||||
"Upgrade": "Opgradér",
|
||||
@@ -353,9 +353,9 @@
|
||||
"Versions": "Versioner",
|
||||
"Versions Path": "Versionssti",
|
||||
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Versioner slettes automatisk, hvis de er ældre end den givne maksimum alder eller overstiger det tilladte antal filer i et interval.",
|
||||
"Waiting to Clean": "Waiting to Clean",
|
||||
"Waiting to Scan": "Waiting to Scan",
|
||||
"Waiting to Sync": "Waiting to Sync",
|
||||
"Waiting to Clean": "Venter på oprydning",
|
||||
"Waiting to Scan": "Venter på skanning",
|
||||
"Waiting to Sync": "Venter på synkronisering",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Advarsel: Denne sti er en forældermappe til den eksisterende mappe “{{otherFolder}}”.",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Advarsel: Denne sti er en forældermappe til den eksisterende mappe “{{otherFolderLabel}}” ({{otherFolder}}).",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Advarsel: Denne sti er en undermappe til den eksisterende mappe “{{otherFolder}}”.",
|
||||
@@ -375,11 +375,11 @@
|
||||
"You have unsaved changes. Do you really want to discard them?": "Du har ændringer, som ikke er gemt. Er du sikker på, at du ikke vil beholde dem?",
|
||||
"You must keep at least one version.": "Du skal beholde mindst én version.",
|
||||
"days": "dage",
|
||||
"directories": "directories",
|
||||
"directories": "kataloger",
|
||||
"files": "filer",
|
||||
"full documentation": "fuld dokumentation",
|
||||
"items": "filer",
|
||||
"seconds": "seconds",
|
||||
"seconds": "sekunder",
|
||||
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} ønsker at dele mappen “{{folder}}”.",
|
||||
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} ønsker at dele mappen “{{folderlabel}}” ({{folder}})."
|
||||
}
|
||||
@@ -311,7 +311,7 @@
|
||||
"The following items could not be synchronized.": "Die folgenden Elemente konnten nicht synchronisiert werden.",
|
||||
"The following items were changed locally.": "Die folgenden Elemente wurden lokal geändert.",
|
||||
"The interval must be a positive number of seconds.": "Das Intervall muss eine positive Zahl von Sekunden sein.",
|
||||
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "Das Interval, in Sekunden, zwischen den Bereinigungen im Versionen Verzeichnis. 0 um das regelmäßige Bereinigen zu deaktivieren.",
|
||||
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "Das Intervall, in Sekunden, zwischen den Bereinigungen im Versionsverzeichnis. 0 um das regelmäßige Bereinigen zu deaktivieren.",
|
||||
"The maximum age must be a number and cannot be blank.": "Das Höchstalter muss angegeben werden und eine Zahl sein.",
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Die längste Zeit, die alte Versionen vorgehalten werden (in Tagen) (0 um alte Versionen für immer zu behalten).",
|
||||
"The number of days must be a number and cannot be blank.": "Die Anzahl von Versionen muss eine Ganzzahl und darf nicht leer sein.",
|
||||
|
||||
385
gui/default/assets/lang/lang-en-AU.json
Normal file
385
gui/default/assets/lang/lang-en-AU.json
Normal file
@@ -0,0 +1,385 @@
|
||||
{
|
||||
"A device with that ID is already added.": "A device with that ID is already added.",
|
||||
"A negative number of days doesn't make sense.": "A negative number of days doesn't make sense.",
|
||||
"A new major version may not be compatible with previous versions.": "A new major version may not be compatible with previous versions.",
|
||||
"API Key": "API Key",
|
||||
"About": "About",
|
||||
"Action": "Action",
|
||||
"Actions": "Actions",
|
||||
"Add": "Add",
|
||||
"Add Device": "Add Device",
|
||||
"Add Folder": "Add Folder",
|
||||
"Add Remote Device": "Add Remote Device",
|
||||
"Add devices from the introducer to our device list, for mutually shared folders.": "Add devices from the introducer to our device list, for mutually shared folders.",
|
||||
"Add new folder?": "Add new folder?",
|
||||
"Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.",
|
||||
"Address": "Address",
|
||||
"Addresses": "Addresses",
|
||||
"Advanced": "Advanced",
|
||||
"Advanced Configuration": "Advanced Configuration",
|
||||
"All Data": "All Data",
|
||||
"Allow Anonymous Usage Reporting?": "Allow Anonymous Usage Reporting?",
|
||||
"Allowed Networks": "Allowed Networks",
|
||||
"Alphabetic": "Alphabetic",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.",
|
||||
"Anonymous Usage Reporting": "Anonymous Usage Reporting",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonymous usage report format has changed. Would you like to move to the new format?",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Are you sure you want to restore {%count%} files?": "Are you sure you want to restore {{count}} files?",
|
||||
"Are you sure you want to upgrade?": "Are you sure you want to upgrade?",
|
||||
"Auto Accept": "Auto Accept",
|
||||
"Automatic Crash Reporting": "Automatic Crash Reporting",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatic upgrade now offers the choice between stable releases and release candidates.",
|
||||
"Automatic upgrades": "Automatic upgrades",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "Automatic upgrades are always enabled for candidate releases.",
|
||||
"Automatically create or share folders that this device advertises at the default path.": "Automatically create or share folders that this device advertises at the default path.",
|
||||
"Available debug logging facilities:": "Available debug logging facilities:",
|
||||
"Be careful!": "Be careful!",
|
||||
"Bugs": "Bugs",
|
||||
"Changelog": "Changelog",
|
||||
"Clean out after": "Clean out after",
|
||||
"Cleaning Versions": "Cleaning Versions",
|
||||
"Cleanup Interval": "Cleanup Interval",
|
||||
"Click to see discovery failures": "Click to see discovery failures",
|
||||
"Close": "Close",
|
||||
"Command": "Command",
|
||||
"Comment, when used at the start of a line": "Comment, when used at the start of a line",
|
||||
"Compression": "Compression",
|
||||
"Configured": "Configured",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "Connection Error",
|
||||
"Connection Type": "Connection Type",
|
||||
"Connections": "Connections",
|
||||
"Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.": "Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.",
|
||||
"Copied from elsewhere": "Copied from elsewhere",
|
||||
"Copied from original": "Copied from original",
|
||||
"Copyright © 2014-2019 the following Contributors:": "Copyright © 2014-2019 the following Contributors:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Creating ignore patterns, overwriting an existing file at {{path}}.",
|
||||
"Currently Shared With Devices": "Currently Shared With Devices",
|
||||
"Danger!": "Danger!",
|
||||
"Debugging Facilities": "Debugging Facilities",
|
||||
"Default Folder Path": "Default Folder Path",
|
||||
"Deleted": "Deleted",
|
||||
"Deselect All": "Deselect All",
|
||||
"Deselect devices to stop sharing this folder with.": "Deselect devices to stop sharing this folder with.",
|
||||
"Device": "Device",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Device \"{{name}}\" ({{device}} at {{address}}) wants to connect. Add new device?",
|
||||
"Device ID": "Device ID",
|
||||
"Device Identification": "Device Identification",
|
||||
"Device Name": "Device Name",
|
||||
"Device rate limits": "Device rate limits",
|
||||
"Device that last modified the item": "Device that last modified the item",
|
||||
"Devices": "Devices",
|
||||
"Disable Crash Reporting": "Disable Crash Reporting",
|
||||
"Disabled": "Disabled",
|
||||
"Disabled periodic scanning and disabled watching for changes": "Disabled periodic scanning and disabled watching for changes",
|
||||
"Disabled periodic scanning and enabled watching for changes": "Disabled periodic scanning and enabled watching for changes",
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:",
|
||||
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).",
|
||||
"Discard": "Discard",
|
||||
"Disconnected": "Disconnected",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "Discovered",
|
||||
"Discovery": "Discovery",
|
||||
"Discovery Failures": "Discovery Failures",
|
||||
"Do not restore": "Do not restore",
|
||||
"Do not restore all": "Do not restore all",
|
||||
"Do you want to enable watching for changes for all your folders?": "Do you want to enable watching for changes for all your folders?",
|
||||
"Documentation": "Documentation",
|
||||
"Download Rate": "Download Rate",
|
||||
"Downloaded": "Downloaded",
|
||||
"Downloading": "Downloading",
|
||||
"Edit": "Edit",
|
||||
"Edit Device": "Edit Device",
|
||||
"Edit Folder": "Edit Folder",
|
||||
"Editing {%path%}.": "Editing {{path}}.",
|
||||
"Enable Crash Reporting": "Enable Crash Reporting",
|
||||
"Enable NAT traversal": "Enable NAT traversal",
|
||||
"Enable Relaying": "Enable Relaying",
|
||||
"Enabled": "Enabled",
|
||||
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
|
||||
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.",
|
||||
"Enter ignore patterns, one per line.": "Enter ignore patterns, one per line.",
|
||||
"Enter up to three octal digits.": "Enter up to three octal digits.",
|
||||
"Error": "Error",
|
||||
"External File Versioning": "External File Versioning",
|
||||
"Failed Items": "Failed Items",
|
||||
"Failed to setup, retrying": "Failed to setup, retrying",
|
||||
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.",
|
||||
"File Pull Order": "File Pull Order",
|
||||
"File Versioning": "File Versioning",
|
||||
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Files are moved to .stversions directory when replaced or deleted by Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.",
|
||||
"Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.": "Files are synchronised from the cluster, but any changes made locally will not be sent to other devices.",
|
||||
"Filesystem Watcher Errors": "Filesystem Watcher Errors",
|
||||
"Filter by date": "Filter by date",
|
||||
"Filter by name": "Filter by name",
|
||||
"Folder": "Folder",
|
||||
"Folder ID": "Folder ID",
|
||||
"Folder Label": "Folder Label",
|
||||
"Folder Path": "Folder Path",
|
||||
"Folder Type": "Folder Type",
|
||||
"Folders": "Folders",
|
||||
"For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.": "For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.",
|
||||
"Full Rescan Interval (s)": "Full Rescan Interval (s)",
|
||||
"GUI": "GUI",
|
||||
"GUI Authentication Password": "GUI Authentication Password",
|
||||
"GUI Authentication User": "GUI Authentication User",
|
||||
"GUI Authentication: Set User and Password": "GUI Authentication: Set User and Password",
|
||||
"GUI Listen Address": "GUI Listen Address",
|
||||
"GUI Theme": "GUI Theme",
|
||||
"General": "General",
|
||||
"Generate": "Generate",
|
||||
"Global Discovery": "Global Discovery",
|
||||
"Global Discovery Servers": "Global Discovery Servers",
|
||||
"Global State": "Global State",
|
||||
"Help": "Help",
|
||||
"Home page": "Home page",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.",
|
||||
"Ignore": "Ignore",
|
||||
"Ignore Patterns": "Ignore Patterns",
|
||||
"Ignore Permissions": "Ignore Permissions",
|
||||
"Ignored Devices": "Ignored Devices",
|
||||
"Ignored Folders": "Ignored Folders",
|
||||
"Ignored at": "Ignored at",
|
||||
"Incoming Rate Limit (KiB/s)": "Incoming Rate Limit (KiB/s)",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Incorrect configuration may damage your folder contents and render Syncthing inoperable.",
|
||||
"Introduced By": "Introduced By",
|
||||
"Introducer": "Introducer",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Inversion of the given condition (i.e. do not exclude)",
|
||||
"Keep Versions": "Keep Versions",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Largest First",
|
||||
"Last Scan": "Last Scan",
|
||||
"Last seen": "Last seen",
|
||||
"Latest Change": "Latest Change",
|
||||
"Learn more": "Learn more",
|
||||
"Limit": "Limit",
|
||||
"Listeners": "Listeners",
|
||||
"Loading data...": "Loading data...",
|
||||
"Loading...": "Loading...",
|
||||
"Local Additions": "Local Additions",
|
||||
"Local Discovery": "Local Discovery",
|
||||
"Local State": "Local State",
|
||||
"Local State (Total)": "Local State (Total)",
|
||||
"Locally Changed Items": "Locally Changed Items",
|
||||
"Log": "Log",
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "Log tailing paused. Scroll to the bottom to continue.",
|
||||
"Logs": "Logs",
|
||||
"Major Upgrade": "Major Upgrade",
|
||||
"Mass actions": "Mass actions",
|
||||
"Maximum Age": "Maximum Age",
|
||||
"Metadata Only": "Metadata Only",
|
||||
"Minimum Free Disk Space": "Minimum Free Disk Space",
|
||||
"Mod. Device": "Mod. Device",
|
||||
"Mod. Time": "Mod. Time",
|
||||
"Move to top of queue": "Move to top of queue",
|
||||
"Multi level wildcard (matches multiple directory levels)": "Multi level wildcard (matches multiple directory levels)",
|
||||
"Never": "Never",
|
||||
"New Device": "New Device",
|
||||
"New Folder": "New Folder",
|
||||
"Newest First": "Newest First",
|
||||
"No": "No",
|
||||
"No File Versioning": "No File Versioning",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "No upgrades",
|
||||
"Notice": "Notice",
|
||||
"OK": "OK",
|
||||
"Off": "Off",
|
||||
"Oldest First": "Oldest First",
|
||||
"Optional descriptive label for the folder. Can be different on each device.": "Optional descriptive label for the folder. Can be different on each device.",
|
||||
"Options": "Options",
|
||||
"Out of Sync": "Out of Sync",
|
||||
"Out of Sync Items": "Out of Sync Items",
|
||||
"Outgoing Rate Limit (KiB/s)": "Outgoing Rate Limit (KiB/s)",
|
||||
"Override Changes": "Override Changes",
|
||||
"Path": "Path",
|
||||
"Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for",
|
||||
"Path where new auto accepted folders will be created, as well as the default suggested path when adding new folders via the UI. Tilde character (~) expands to {%tilde%}.": "Path where new auto accepted folders will be created, as well as the default suggested path when adding new folders via the UI. Tilde character (~) expands to {{tilde}}.",
|
||||
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).",
|
||||
"Pause": "Pause",
|
||||
"Pause All": "Pause All",
|
||||
"Paused": "Paused",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "Pending changes",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodic scanning at given interval and disabled watching for changes",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodic scanning at given interval and enabled watching for changes",
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:",
|
||||
"Permissions": "Permissions",
|
||||
"Please consult the release notes before performing a major upgrade.": "Please consult the release notes before performing a major upgrade.",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "Please set a GUI Authentication User and Password in the Settings dialog.",
|
||||
"Please wait": "Please wait",
|
||||
"Prefix indicating that the file can be deleted if preventing directory removal": "Prefix indicating that the file can be deleted if preventing directory removal",
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "Prefix indicating that the pattern should be matched without case sensitivity",
|
||||
"Preparing to Sync": "Preparing to Sync",
|
||||
"Preview": "Preview",
|
||||
"Preview Usage Report": "Preview Usage Report",
|
||||
"Quick guide to supported patterns": "Quick guide to supported patterns",
|
||||
"Random": "Random",
|
||||
"Receive Only": "Receive Only",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "Reduced by ignore patterns",
|
||||
"Release Notes": "Release Notes",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.",
|
||||
"Remote Devices": "Remote Devices",
|
||||
"Remove": "Remove",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Required identifier for the folder. Must be the same on all cluster devices.",
|
||||
"Rescan": "Rescan",
|
||||
"Rescan All": "Rescan All",
|
||||
"Rescans": "Rescans",
|
||||
"Restart": "Restart",
|
||||
"Restart Needed": "Restart Needed",
|
||||
"Restarting": "Restarting",
|
||||
"Restore": "Restore",
|
||||
"Restore Versions": "Restore Versions",
|
||||
"Resume": "Resume",
|
||||
"Resume All": "Resume All",
|
||||
"Reused": "Reused",
|
||||
"Revert Local Changes": "Revert Local Changes",
|
||||
"Save": "Save",
|
||||
"Scan Time Remaining": "Scan Time Remaining",
|
||||
"Scanning": "Scanning",
|
||||
"See external versioning help for supported templated command line parameters.": "See external versioning help for supported templated command line parameters.",
|
||||
"Select All": "Select All",
|
||||
"Select a version": "Select a version",
|
||||
"Select additional devices to share this folder with.": "Select additional devices to share this folder with.",
|
||||
"Select latest version": "Select latest version",
|
||||
"Select oldest version": "Select oldest version",
|
||||
"Select the folders to share with this device.": "Select the folders to share with this device.",
|
||||
"Send & Receive": "Send & Receive",
|
||||
"Send Only": "Send Only",
|
||||
"Settings": "Settings",
|
||||
"Share": "Share",
|
||||
"Share Folder": "Share Folder",
|
||||
"Share Folders With Device": "Share Folders With Device",
|
||||
"Share this folder?": "Share this folder?",
|
||||
"Shared With": "Shared With",
|
||||
"Sharing": "Sharing",
|
||||
"Show ID": "Show ID",
|
||||
"Show QR": "Show QR",
|
||||
"Show diff with previous version": "Show diff with previous version",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.",
|
||||
"Shutdown": "Shutdown",
|
||||
"Shutdown Complete": "Shutdown Complete",
|
||||
"Simple File Versioning": "Simple File Versioning",
|
||||
"Single level wildcard (matches within a directory only)": "Single level wildcard (matches within a directory only)",
|
||||
"Size": "Size",
|
||||
"Smallest First": "Smallest First",
|
||||
"Some items could not be restored:": "Some items could not be restored:",
|
||||
"Source Code": "Source Code",
|
||||
"Stable releases and release candidates": "Stable releases and release candidates",
|
||||
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.",
|
||||
"Stable releases only": "Stable releases only",
|
||||
"Staggered File Versioning": "Staggered File Versioning",
|
||||
"Start Browser": "Start Browser",
|
||||
"Statistics": "Statistics",
|
||||
"Stopped": "Stopped",
|
||||
"Support": "Support",
|
||||
"Support Bundle": "Support Bundle",
|
||||
"Sync Protocol Listen Addresses": "Sync Protocol Listen Addresses",
|
||||
"Syncing": "Syncing",
|
||||
"Syncthing has been shut down.": "Syncthing has been shut down.",
|
||||
"Syncthing includes the following software or portions thereof:": "Syncthing includes the following software or portions thereof:",
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing is Free and Open Source Software licensed as MPL v2.0.",
|
||||
"Syncthing is restarting.": "Syncthing is restarting.",
|
||||
"Syncthing is upgrading.": "Syncthing is upgrading.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…",
|
||||
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.",
|
||||
"Take me back": "Take me back",
|
||||
"The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.": "The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.",
|
||||
"The Syncthing Authors": "The Syncthing Authors",
|
||||
"The Syncthing admin interface is configured to allow remote access without a password.": "The Syncthing admin interface is configured to allow remote access without a password.",
|
||||
"The aggregated statistics are publicly available at the URL below.": "The aggregated statistics are publicly available at the URL below.",
|
||||
"The cleanup interval cannot be blank.": "The cleanup interval cannot be blank.",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.",
|
||||
"The device ID cannot be blank.": "The device ID cannot be blank.",
|
||||
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).",
|
||||
"The encrypted usage report is sent daily. It is used to track common platforms, folder sizes and app versions. If the reported data set is changed you will be prompted with this dialog again.": "The encrypted usage report is sent daily. It is used to track common platforms, folder sizes and app versions. If the reported data set is changed you will be prompted with this dialog again.",
|
||||
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.",
|
||||
"The folder ID cannot be blank.": "The folder ID cannot be blank.",
|
||||
"The folder ID must be unique.": "The folder ID must be unique.",
|
||||
"The folder path cannot be blank.": "The folder path cannot be blank.",
|
||||
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.",
|
||||
"The following items could not be synchronized.": "The following items could not be synchronised.",
|
||||
"The following items were changed locally.": "The following items were changed locally.",
|
||||
"The interval must be a positive number of seconds.": "The interval must be a positive number of seconds.",
|
||||
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.",
|
||||
"The maximum age must be a number and cannot be blank.": "The maximum age must be a number and cannot be blank.",
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "The maximum time to keep a version (in days, set to 0 to keep versions forever).",
|
||||
"The number of days must be a number and cannot be blank.": "The number of days must be a number and cannot be blank.",
|
||||
"The number of days to keep files in the trash can. Zero means forever.": "The number of days to keep files in the bin. Zero means forever.",
|
||||
"The number of old versions to keep, per file.": "The number of old versions to keep, per file.",
|
||||
"The number of versions must be a number and cannot be blank.": "The number of versions must be a number and cannot be blank.",
|
||||
"The path cannot be blank.": "The path cannot be blank.",
|
||||
"The rate limit must be a non-negative number (0: no limit)": "The rate limit must be a non-negative number (0: no limit)",
|
||||
"The rescan interval must be a non-negative number of seconds.": "The rescan interval must be a non-negative number of seconds.",
|
||||
"There are no devices to share this folder with.": "There are no devices to share this folder with.",
|
||||
"They are retried automatically and will be synced when the error is resolved.": "They are retried automatically and will be synced when the error is resolved.",
|
||||
"This Device": "This Device",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "This can easily give hackers access to read and change any files on your computer.",
|
||||
"This is a major version upgrade.": "This is a major version upgrade.",
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
|
||||
"Time": "Time",
|
||||
"Time the item was last modified": "Time the item was last modified",
|
||||
"Trash Can File Versioning": "Bin File Versioning",
|
||||
"Type": "Type",
|
||||
"UNIX Permissions": "UNIX Permissions",
|
||||
"Unavailable": "Unavailable",
|
||||
"Unavailable/Disabled by administrator or maintainer": "Unavailable/Disabled by administrator or maintainer",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unignore": "Unignore",
|
||||
"Unknown": "Unknown",
|
||||
"Unshared": "Unshared",
|
||||
"Unshared Devices": "Unshared Devices",
|
||||
"Up to Date": "Up to Date",
|
||||
"Updated": "Updated",
|
||||
"Upgrade": "Upgrade",
|
||||
"Upgrade To {%version%}": "Upgrade To {{version}}",
|
||||
"Upgrading": "Upgrading",
|
||||
"Upload Rate": "Upload Rate",
|
||||
"Uptime": "Uptime",
|
||||
"Usage reporting is always enabled for candidate releases.": "Usage reporting is always enabled for candidate releases.",
|
||||
"Use HTTPS for GUI": "Use HTTPS for GUI",
|
||||
"Username/Password has not been set for the GUI authentication. Please consider setting it up.": "Username/Password has not been set for the GUI authentication. Please consider setting it up.",
|
||||
"Version": "Version",
|
||||
"Versions": "Versions",
|
||||
"Versions Path": "Versions Path",
|
||||
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.",
|
||||
"Waiting to Clean": "Waiting to Clean",
|
||||
"Waiting to Scan": "Waiting to Scan",
|
||||
"Waiting to Sync": "Waiting to Sync",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Warning, this path is a parent directory of an existing folder \"{{otherFolder}}\".",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warning, this path is a parent directory of an existing folder \"{{otherFolderLabel}}\" ({{otherFolder}}).",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Warning, this path is a subdirectory of an existing folder \"{{otherFolder}}\".",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warning, this path is a subdirectory of an existing folder \"{{otherFolderLabel}}\" ({{otherFolder}}).",
|
||||
"Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.": "Warning: If you are using an external watcher like {{syncthingInotify}}, you should make sure it is deactivated.",
|
||||
"Watch for Changes": "Watch for Changes",
|
||||
"Watching for Changes": "Watching for Changes",
|
||||
"Watching for changes discovers most changes without periodic scanning.": "Watching for changes discovers most changes without periodic scanning.",
|
||||
"When adding a new device, keep in mind that this device must be added on the other side too.": "When adding a new device, keep in mind that this device must be added on the other side too.",
|
||||
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.",
|
||||
"Yes": "Yes",
|
||||
"You can also select one of these nearby devices:": "You can also select one of these nearby devices:",
|
||||
"You can change your choice at any time in the Settings dialog.": "You can change your choice at any time in the Settings dialog.",
|
||||
"You can read more about the two release channels at the link below.": "You can read more about the two release channels at the link below.",
|
||||
"You have no ignored devices.": "You have no ignored devices.",
|
||||
"You have no ignored folders.": "You have no ignored folders.",
|
||||
"You have unsaved changes. Do you really want to discard them?": "You have unsaved changes. Do you really want to discard them?",
|
||||
"You must keep at least one version.": "You must keep at least one version.",
|
||||
"days": "days",
|
||||
"directories": "directories",
|
||||
"files": "files",
|
||||
"full documentation": "full documentation",
|
||||
"items": "items",
|
||||
"seconds": "seconds",
|
||||
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} wants to share folder \"{{folder}}\".",
|
||||
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} wants to share folder \"{{folderlabel}}\" ({{folder}})."
|
||||
}
|
||||
@@ -18,12 +18,14 @@
|
||||
"Advanced": "Advanced",
|
||||
"Advanced Configuration": "Advanced Configuration",
|
||||
"All Data": "All Data",
|
||||
"All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.": "All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.",
|
||||
"Allow Anonymous Usage Reporting?": "Allow Anonymous Usage Reporting?",
|
||||
"Allowed Networks": "Allowed Networks",
|
||||
"Alphabetic": "Alphabetic",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.",
|
||||
"Anonymous Usage Reporting": "Anonymous Usage Reporting",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonymous usage report format has changed. Would you like to move to the new format?",
|
||||
"Are you sure you want to permanently delete all these files?": "Are you sure you want to permanently delete all these files?",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Are you sure you want to restore {%count%} files?": "Are you sure you want to restore {{count}} files?",
|
||||
@@ -60,6 +62,7 @@
|
||||
"Danger!": "Danger!",
|
||||
"Debugging Facilities": "Debugging Facilities",
|
||||
"Default Folder Path": "Default Folder Path",
|
||||
"Delete Unexpected Items": "Delete Unexpected Items",
|
||||
"Deleted": "Deleted",
|
||||
"Deselect All": "Deselect All",
|
||||
"Deselect devices to stop sharing this folder with.": "Deselect devices to stop sharing this folder with.",
|
||||
@@ -122,6 +125,7 @@
|
||||
"Folder Label": "Folder Label",
|
||||
"Folder Path": "Folder Path",
|
||||
"Folder Type": "Folder Type",
|
||||
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "Folder type \"{{receiveEncrypted}}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.",
|
||||
"Folders": "Folders",
|
||||
"For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.": "For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.",
|
||||
"Full Rescan Interval (s)": "Full Rescan Interval (s)",
|
||||
@@ -139,6 +143,7 @@
|
||||
"Help": "Help",
|
||||
"Home page": "Home page",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.",
|
||||
"If untrusted, enter encryption password": "If untrusted, enter encryption password",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.",
|
||||
"Ignore": "Ignore",
|
||||
"Ignore Patterns": "Ignore Patterns",
|
||||
@@ -187,6 +192,7 @@
|
||||
"No File Versioning": "No File Versioning",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "No upgrades",
|
||||
"Not shared": "Not shared",
|
||||
"Notice": "Notice",
|
||||
"OK": "OK",
|
||||
"Off": "Off",
|
||||
@@ -220,7 +226,9 @@
|
||||
"Preview Usage Report": "Preview Usage Report",
|
||||
"Quick guide to supported patterns": "Quick guide to supported patterns",
|
||||
"Random": "Random",
|
||||
"Receive Encrypted": "Receive Encrypted",
|
||||
"Receive Only": "Receive Only",
|
||||
"Received data is already encrypted": "Received data is already encrypted",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "Reduced by ignore patterns",
|
||||
"Release Notes": "Release Notes",
|
||||
@@ -249,6 +257,7 @@
|
||||
"Select All": "Select All",
|
||||
"Select a version": "Select a version",
|
||||
"Select additional devices to share this folder with.": "Select additional devices to share this folder with.",
|
||||
"Select additional folders to share with this device.": "Select additional folders to share with this device.",
|
||||
"Select latest version": "Select latest version",
|
||||
"Select oldest version": "Select oldest version",
|
||||
"Select the folders to share with this device.": "Select the folders to share with this device.",
|
||||
@@ -259,6 +268,7 @@
|
||||
"Share Folder": "Share Folder",
|
||||
"Share Folders With Device": "Share Folders With Device",
|
||||
"Share this folder?": "Share this folder?",
|
||||
"Shared Folders": "Shared Folders",
|
||||
"Shared With": "Shared With",
|
||||
"Sharing": "Sharing",
|
||||
"Show ID": "Show ID",
|
||||
@@ -281,6 +291,7 @@
|
||||
"Start Browser": "Start Browser",
|
||||
"Statistics": "Statistics",
|
||||
"Stopped": "Stopped",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{{receiveEncrypted}}\" too.",
|
||||
"Support": "Support",
|
||||
"Support Bundle": "Support Bundle",
|
||||
"Sync Protocol Listen Addresses": "Sync Protocol Listen Addresses",
|
||||
@@ -310,6 +321,7 @@
|
||||
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.",
|
||||
"The following items could not be synchronized.": "The following items could not be synchronized.",
|
||||
"The following items were changed locally.": "The following items were changed locally.",
|
||||
"The following unexpected items were found.": "The following unexpected items were found.",
|
||||
"The interval must be a positive number of seconds.": "The interval must be a positive number of seconds.",
|
||||
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.",
|
||||
"The maximum age must be a number and cannot be blank.": "The maximum age must be a number and cannot be blank.",
|
||||
@@ -335,10 +347,14 @@
|
||||
"Unavailable": "Unavailable",
|
||||
"Unavailable/Disabled by administrator or maintainer": "Unavailable/Disabled by administrator or maintainer",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unexpected Items": "Unexpected Items",
|
||||
"Unexpected items have been found in this folder.": "Unexpected items have been found in this folder.",
|
||||
"Unignore": "Unignore",
|
||||
"Unknown": "Unknown",
|
||||
"Unshared": "Unshared",
|
||||
"Unshared Devices": "Unshared Devices",
|
||||
"Unshared Folders": "Unshared Folders",
|
||||
"Untrusted": "Untrusted",
|
||||
"Up to Date": "Up to Date",
|
||||
"Updated": "Updated",
|
||||
"Upgrade": "Upgrade",
|
||||
@@ -374,6 +390,7 @@
|
||||
"You have no ignored folders.": "You have no ignored folders.",
|
||||
"You have unsaved changes. Do you really want to discard them?": "You have unsaved changes. Do you really want to discard them?",
|
||||
"You must keep at least one version.": "You must keep at least one version.",
|
||||
"You should never add or change anything locally in a \"{%receiveEncrypted%}\" folder.": "You should never add or change anything locally in a \"{{receiveEncrypted}}\" folder.",
|
||||
"days": "days",
|
||||
"directories": "directories",
|
||||
"files": "files",
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Le système de mise à jour automatique propose le choix entre versions stables et versions préliminaires.",
|
||||
"Automatic upgrades": "Mises à jour automatiques",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "Les mises à jour automatiques sont toujours activées pour les versions préliminaires (-rc.N).",
|
||||
"Automatically create or share folders that this device advertises at the default path.": "ATTENTION !!! Créer ou partager automatiquement dans le chemin par défaut les partages que cet appareil annonce.",
|
||||
"Automatically create or share folders that this device advertises at the default path.": "ATTENTION, risque de sécurité/confidentialité !!! Créer ou partager automatiquement dans le chemin par défaut les partages auxquels cet appareil m'invite à participer. N'accordez ce privilège, éventuellement temporaire le temps de l'établissement, qu'à vos propres appareils.",
|
||||
"Available debug logging facilities:": "Outils de débogage disponibles :",
|
||||
"Be careful!": "Faites attention !",
|
||||
"Bugs": "Bugs",
|
||||
@@ -301,9 +301,9 @@
|
||||
"The cleanup interval cannot be blank.": "L'intervalle de purge ne peut pas être vide.",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "La configuration a été enregistrée mais pas activée. Syncthing doit redémarrer afin d'activer la nouvelle configuration.",
|
||||
"The device ID cannot be blank.": "L'ID de l'appareil ne peut être vide.",
|
||||
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "L'ID d'appareil à saisir ici se trouve dans le menu \"Actions > Afficher mon ID\" de l'appareil distant. Espaces et tirets sont optionnels (ignorés).",
|
||||
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "L'ID d'appareil à saisir ici se trouve dans le menu \"Actions > Afficher mon ID\" de l'appareil distant. Espaces et tirets sont optionnels (ignorés, comme la casse).",
|
||||
"The encrypted usage report is sent daily. It is used to track common platforms, folder sizes and app versions. If the reported data set is changed you will be prompted with this dialog again.": "Le rapport d'utilisation chiffré est envoyé quotidiennement. Il sert à répertorier les plates-formes utilisées, la taille des partages et les versions de l'application. Si le jeu de données rapportées devait être changé, il vous serait demandé de valider de nouveau son envoi via ce message. Vous pouvez revenir sur votre décision via Actions/Configuration, et agir sur la fréquence d'envoi via Actions/Avancé/Options (Ur Initial Delay (seconds)).",
|
||||
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "L'ID de l'appareil inséré ne semble pas valide. Il devrait ressembler à une chaîne de 52 ou 56 caractères comprenant des lettres, des chiffres et potentiellement des espaces et des traits d'union.",
|
||||
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "L'ID de l'appareil inséré ne semble pas valide. Il devrait ressembler à une chaîne de 52 ou 56 caractères comprenant des lettres (casse ignorée), des chiffres et potentiellement des espaces et des traits d'union.",
|
||||
"The folder ID cannot be blank.": "L'ID du partage ne peut être vide.",
|
||||
"The folder ID must be unique.": "L'ID du partage doit être unique.",
|
||||
"The folder path cannot be blank.": "Le chemin vers le répertoire ne peut pas être vide.",
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
"Copied from original": "원본에서 복사됨",
|
||||
"Copyright © 2014-2019 the following Contributors:": "Copyright © 2014-2019 the following Contributors:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "무시 패턴 만들기, {{path}}에 존재하는 파일을 덮어쓰기 합니다",
|
||||
"Currently Shared With Devices": "Currently Shared With Devices",
|
||||
"Currently Shared With Devices": "현재 공유된 기기들",
|
||||
"Danger!": "경고!",
|
||||
"Debugging Facilities": "디버깅 기능",
|
||||
"Default Folder Path": "기본 폴더 경로",
|
||||
@@ -71,7 +71,7 @@
|
||||
"Device rate limits": "Device rate limits",
|
||||
"Device that last modified the item": "항목을 마지막으로 수정 한 기기",
|
||||
"Devices": "기기",
|
||||
"Disable Crash Reporting": "Disable Crash Reporting",
|
||||
"Disable Crash Reporting": "충돌 보고 해제",
|
||||
"Disabled": "비활성화",
|
||||
"Disabled periodic scanning and disabled watching for changes": "주기적 스캔을 사용 중지하고 변경 사항을 감시하지 않음",
|
||||
"Disabled periodic scanning and enabled watching for changes": "주기적 스캔을 사용 중지하고 변경 사항 감시 하기",
|
||||
@@ -91,8 +91,8 @@
|
||||
"Downloaded": "다운로드됨",
|
||||
"Downloading": "다운로드 중",
|
||||
"Edit": "편집",
|
||||
"Edit Device": "Edit Device",
|
||||
"Edit Folder": "Edit Folder",
|
||||
"Edit Device": "기기 수정",
|
||||
"Edit Folder": "폴더 수정",
|
||||
"Editing {%path%}.": "{{path}} 수정하기.",
|
||||
"Enable Crash Reporting": "충돌 보고 활성화",
|
||||
"Enable NAT traversal": "NAT traversal 활성화",
|
||||
@@ -102,7 +102,7 @@
|
||||
"Enter a non-privileged port number (1024 - 65535).": "비 특권 포트 번호를 입력하세요 (1024 - 65535).",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.",
|
||||
"Enter ignore patterns, one per line.": "무시할 패턴을 한 줄에 하나씩 입력하세요.",
|
||||
"Enter up to three octal digits.": "Enter up to three octal digits.",
|
||||
"Enter up to three octal digits.": "최대 3자리의 8진수를 입력하세요.",
|
||||
"Error": "오류",
|
||||
"External File Versioning": "외부 파일 버전 관리",
|
||||
"Failed Items": "실패한 항목",
|
||||
@@ -220,7 +220,7 @@
|
||||
"Preview Usage Report": "사용 보고서 미리보기",
|
||||
"Quick guide to supported patterns": "지원하는 패턴에 대한 빠른 도움말",
|
||||
"Random": "무작위",
|
||||
"Receive Only": "Receive Only",
|
||||
"Receive Only": "수신 전용",
|
||||
"Recent Changes": "최근 변경",
|
||||
"Reduced by ignore patterns": "무시 패턴으로 축소",
|
||||
"Release Notes": "릴리즈 노트",
|
||||
@@ -310,7 +310,7 @@
|
||||
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "다음과 같은 간격이 사용됩니다: 첫 한 시간 동안은 버전이 매 30초마다 유지되며, 첫 하루 동안은 매 시간, 첫 한 달 동안은 매 일마다 유지됩니다. 그리고 최대 날짜까지는 버전이 매 주마다 유지됩니다.",
|
||||
"The following items could not be synchronized.": "이 항목들은 동기화 할 수 없습니다.",
|
||||
"The following items were changed locally.": "The following items were changed locally.",
|
||||
"The interval must be a positive number of seconds.": "The interval must be a positive number of seconds.",
|
||||
"The interval must be a positive number of seconds.": "간격은 초 단위의 자연수여야 합니다.",
|
||||
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.",
|
||||
"The maximum age must be a number and cannot be blank.": "최대 보존 기간은 숫자여야 하며 비워 둘 수 없습니다.",
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "버전을 유지할 최대 시간을 지정합니다. 일단위이며 버전을 계속 유지하려면 0을 입력하세요,",
|
||||
@@ -338,7 +338,7 @@
|
||||
"Unignore": "Unignore",
|
||||
"Unknown": "알 수 없음",
|
||||
"Unshared": "공유되지 않음",
|
||||
"Unshared Devices": "Unshared Devices",
|
||||
"Unshared Devices": "공유되지 않은 기기들",
|
||||
"Up to Date": "최신 데이터",
|
||||
"Updated": "업데이트 완료",
|
||||
"Upgrade": "업데이트",
|
||||
|
||||
@@ -241,7 +241,7 @@
|
||||
"Resume": "Wznów",
|
||||
"Resume All": "Wznów wszystkie",
|
||||
"Reused": "Ponownie użyte",
|
||||
"Revert Local Changes": "Przywróć zmiany lokalne",
|
||||
"Revert Local Changes": "Odrzuć zmiany lokalne",
|
||||
"Save": "Zapisz",
|
||||
"Scan Time Remaining": "Pozostały czas skanowania",
|
||||
"Scanning": "Skanowanie",
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
"Bugs": "Erros",
|
||||
"Changelog": "Registo de alterações",
|
||||
"Clean out after": "Esvaziar ao fim de",
|
||||
"Cleaning Versions": "Limpar versões",
|
||||
"Cleaning Versions": "Limpando versões",
|
||||
"Cleanup Interval": "Intervalo entre limpezas",
|
||||
"Click to see discovery failures": "Clique para ver as falhas da pesquisa",
|
||||
"Close": "Fechar",
|
||||
|
||||
@@ -126,11 +126,11 @@
|
||||
"For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.": "För följande mappar uppstod ett fel när du började bevaka ändringar. Det kommer att omförsökas varje minut, så felen kan försvinna snart. Om de fortsätter, försök att åtgärda det underliggande problemet och fråga om hjälp om du inte kan.",
|
||||
"Full Rescan Interval (s)": "Fullständig återkommande skanningsintervall (s)",
|
||||
"GUI": "Grafiskt gränssnitt",
|
||||
"GUI Authentication Password": "Gränssnittets autentiseringslösenord",
|
||||
"GUI Authentication User": "Gränssnittets autentiseringsanvändare",
|
||||
"GUI Authentication: Set User and Password": "Gränssnittets autentisering: Ställ in användare och lösenord",
|
||||
"GUI Listen Address": "Gränssnittets lyssnaradress",
|
||||
"GUI Theme": "Gränssnittets tema",
|
||||
"GUI Authentication Password": "Autentiseringslösenord för gränssnittet",
|
||||
"GUI Authentication User": "Autentiseringsanvändare för gränssnittet",
|
||||
"GUI Authentication: Set User and Password": "Autentisering för gränssnittets: Ställ in användare och lösenord",
|
||||
"GUI Listen Address": "Lyssnaradress för gränssnittet",
|
||||
"GUI Theme": "Tema för gränssnittet",
|
||||
"General": "Allmänt",
|
||||
"Generate": "Generera",
|
||||
"Global Discovery": "Global annonsering",
|
||||
@@ -211,7 +211,7 @@
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Periodisk skanning vid givna intervall och misslyckades med att ställa in bevakning av ändringar, försöker igen varje 1m:",
|
||||
"Permissions": "Behörigheter",
|
||||
"Please consult the release notes before performing a major upgrade.": "Vänligen läs igenom versionsnyheterna innan du utför en större uppgradering.",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "Vänligen ange en användare och lösenord för gränssnittets autentisering i inställningsdialogrutan.",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "Vänligen ange en användare och lösenord för autentisering för gränssnittet i inställningsdialogrutan.",
|
||||
"Please wait": "Vänligen vänta",
|
||||
"Prefix indicating that the file can be deleted if preventing directory removal": "Prefix som indikerar att filen kan tas bort om det förhindrar mappborttagning",
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "Prefix som indikerar att mönstret ska matchas utan skiftlägeskänslighet",
|
||||
@@ -278,12 +278,12 @@
|
||||
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Stabila utgåvor är försenade med cirka två veckor. Under denna tid går de igenom tester som utgåvskandidater.",
|
||||
"Stable releases only": "Endast stabila utgåvor",
|
||||
"Staggered File Versioning": "Filversionshantering i intervall",
|
||||
"Start Browser": "Starta webbläsare",
|
||||
"Start Browser": "Starta webbläsaren",
|
||||
"Statistics": "Statistik",
|
||||
"Stopped": "Stoppad",
|
||||
"Support": "Support",
|
||||
"Support Bundle": "Support Bundle",
|
||||
"Sync Protocol Listen Addresses": "Synkroniseringsprotokollets lyssnaradresser",
|
||||
"Sync Protocol Listen Addresses": "Lyssnaradresser för synkroniseringsprotokollets",
|
||||
"Syncing": "Synkroniserar",
|
||||
"Syncthing has been shut down.": "Syncthing har stängts.",
|
||||
"Syncthing includes the following software or portions thereof:": "Syncthing innehåller följande mjukvarupaket eller delar av dem:",
|
||||
@@ -291,10 +291,10 @@
|
||||
"Syncthing is restarting.": "Syncthing startar om.",
|
||||
"Syncthing is upgrading.": "Syncthing uppgraderas.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing stöder nu automatiskt kraschrapportering till utvecklarna. Den här funktionen är aktiverad som standard.",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing verkar avstängd eller så är det problem med din Internetanslutning. Försöker igen...",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing verkar vara avstängd eller så är det problem med din internetanslutning. Försöker igen...",
|
||||
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing verkar ha drabbats av ett problem med behandlingen av din förfrågan. Vänligen uppdatera sidan eller starta om Syncthing om problemet kvarstår.",
|
||||
"Take me back": "Ta mig tillbaka",
|
||||
"The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.": "Det grafiska gränssnittets adressen åsidosätts av startalternativ. Ändringar här träder inte i kraft så länge åsidosättandet är på plats.",
|
||||
"The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.": "Adressen för det grafiska gränssnittets åsidosätts av startalternativ. Ändringar här träder inte i kraft så länge åsidosättandet är på plats.",
|
||||
"The Syncthing Authors": "Syncthing-upphovsmän",
|
||||
"The Syncthing admin interface is configured to allow remote access without a password.": "Syncthing administratör gränssnittet är konfigurerat för att tillåta fjärrtillträde utan ett lösenord.",
|
||||
"The aggregated statistics are publicly available at the URL below.": "Den aggregerade statistiken är offentligt tillgänglig på webbadressen nedan.",
|
||||
@@ -348,7 +348,7 @@
|
||||
"Uptime": "Drifttid",
|
||||
"Usage reporting is always enabled for candidate releases.": "Användningsrapportering är alltid aktiverad för kandidatutgåvor.",
|
||||
"Use HTTPS for GUI": "Använd HTTPS för gränssnittet",
|
||||
"Username/Password has not been set for the GUI authentication. Please consider setting it up.": "Användarnamn/lösenord har inte ställts in för gränssnittets autentisering. Överväg att ställa in det.",
|
||||
"Username/Password has not been set for the GUI authentication. Please consider setting it up.": "Användarnamn/lösenord har inte ställts in för autentisering för gränssnittet. Överväg att ställa in det.",
|
||||
"Version": "Version",
|
||||
"Versions": "Versioner",
|
||||
"Versions Path": "Sökväg för versioner",
|
||||
|
||||
@@ -56,11 +56,11 @@
|
||||
"Copied from original": "Orijinalinden kopyalandı",
|
||||
"Copyright © 2014-2019 the following Contributors:": "Telif hakkı © 2014-2020 Katkıda Bulunanlar:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Yoksayma şekilleri oluşturuluyor, {{path}} yolunda varolan bir dosyanın üzerine yazılıyor.",
|
||||
"Currently Shared With Devices": "Şu Anda Cihazlarla Paylaşılan",
|
||||
"Currently Shared With Devices": "Şu Anda Paylaşıldığı Cihazlar",
|
||||
"Danger!": "Tehlike!",
|
||||
"Debugging Facilities": "Hata Ayıklama Olanakları",
|
||||
"Default Folder Path": "Varsayılan Klasör Yolu",
|
||||
"Deleted": "Silindi",
|
||||
"Deleted": "Silinen",
|
||||
"Deselect All": "Tüm Seçimi Kaldır",
|
||||
"Deselect devices to stop sharing this folder with.": "Bu klasörün paylaşımının durdurulacağı cihazların seçimini kaldırın.",
|
||||
"Device": "Cihaz",
|
||||
@@ -100,7 +100,7 @@
|
||||
"Enabled": "Etkinleştirildi",
|
||||
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Negatif olmayan bir sayı girin (örn., \"2.35\") ve bir birim seçin. Yüzdeler, toplam disk boyutunun bir parçasıdır.",
|
||||
"Enter a non-privileged port number (1024 - 65535).": "Yetkisiz bir bağlantı noktası numarası girin (1024 - 65535).",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Virgülle ayrılmış (\"tcp://ip:b.noktası\", \"tcp://host:b.noktası\") adresler veya otomatik adres keşfi yapmak için \"dynamic\" girin",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Virgülle ayrılmış (\"tcp://ip:b.noktası\", \"tcp://anamakine:b.noktası\") adresler veya otomatik adres keşfi yapmak için \"dynamic\" girin.",
|
||||
"Enter ignore patterns, one per line.": "Yoksayma şekillerini girin, her satıra bir tane.",
|
||||
"Enter up to three octal digits.": "En fazla üç sekizlik rakam girin.",
|
||||
"Error": "Hata",
|
||||
@@ -243,7 +243,7 @@
|
||||
"Reused": "Yeniden Kullanılan",
|
||||
"Revert Local Changes": "Yerel Değişiklikleri Geri Döndür",
|
||||
"Save": "Kaydet",
|
||||
"Scan Time Remaining": "Kalan Tarama Zamanı",
|
||||
"Scan Time Remaining": "Kalan Tarama Süresi",
|
||||
"Scanning": "Tarama",
|
||||
"See external versioning help for supported templated command line parameters.": "Desteklenen şablonlu komut satırı parametreleri için harici sürümlendirme yardımına bakın.",
|
||||
"Select All": "Tümünü Seç",
|
||||
@@ -345,7 +345,7 @@
|
||||
"Upgrade To {%version%}": "{{version}} Sürümüne Yükselt",
|
||||
"Upgrading": "Yükseltiliyor",
|
||||
"Upload Rate": "Gönderme Hızı",
|
||||
"Uptime": "Çalışma Zamanı",
|
||||
"Uptime": "Çalışma Süresi",
|
||||
"Usage reporting is always enabled for candidate releases.": "Kullanım bildirme aday yayımlar için her zaman etkinleştirilmiştir.",
|
||||
"Use HTTPS for GUI": "GKA için HTTPS kullan",
|
||||
"Username/Password has not been set for the GUI authentication. Please consider setting it up.": "Kullanıcı adı/Parola, GKA kimlik doğrulaması için ayarlanmadı. Lütfen ayarlamayı düşünün.",
|
||||
|
||||
@@ -91,8 +91,8 @@
|
||||
"Downloaded": "Завантажено",
|
||||
"Downloading": "Завантаження",
|
||||
"Edit": "Редагувати",
|
||||
"Edit Device": "Edit Device",
|
||||
"Edit Folder": "Edit Folder",
|
||||
"Edit Device": "Налаштування пристрою",
|
||||
"Edit Folder": "Налаштування директорії",
|
||||
"Editing {%path%}.": "Редагування {{path}}.",
|
||||
"Enable Crash Reporting": "Увімкнути звітування про збої",
|
||||
"Enable NAT traversal": "Увімкнути NAT traversal",
|
||||
@@ -375,7 +375,7 @@
|
||||
"You have unsaved changes. Do you really want to discard them?": "Внесені зміни не збережено, чи дійсно відмовитись від змін?",
|
||||
"You must keep at least one version.": "Ви повинні зберігати щонайменше одну версію.",
|
||||
"days": "днів",
|
||||
"directories": "directories",
|
||||
"directories": "директорії",
|
||||
"files": "файли",
|
||||
"full documentation": "повна документація",
|
||||
"items": "елементи",
|
||||
|
||||
@@ -91,8 +91,8 @@
|
||||
"Downloaded": "已下载",
|
||||
"Downloading": "下载中",
|
||||
"Edit": "选项",
|
||||
"Edit Device": "Edit Device",
|
||||
"Edit Folder": "Edit Folder",
|
||||
"Edit Device": "编辑设备",
|
||||
"Edit Folder": "编辑文件夹",
|
||||
"Editing {%path%}.": "正在编辑 {{path}}。",
|
||||
"Enable Crash Reporting": "启用自动发送崩溃报告",
|
||||
"Enable NAT traversal": "启用 NAT 遍历",
|
||||
@@ -375,7 +375,7 @@
|
||||
"You have unsaved changes. Do you really want to discard them?": "你有未保存的更改。你真的要丢弃它们吗?",
|
||||
"You must keep at least one version.": "您必须保留至少一个版本。",
|
||||
"days": "天",
|
||||
"directories": "directories",
|
||||
"directories": "目录",
|
||||
"files": "文件",
|
||||
"full documentation": "完整文档",
|
||||
"items": "条目",
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
"Comment, when used at the start of a line": "註解,當輸入在一行的開頭時",
|
||||
"Compression": "壓縮",
|
||||
"Configured": "已設定",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connected (Unused)": "已連線(未使用)",
|
||||
"Connection Error": "連線錯誤",
|
||||
"Connection Type": "連線類型",
|
||||
"Connections": "連線",
|
||||
@@ -79,7 +79,7 @@
|
||||
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).",
|
||||
"Discard": "忽略",
|
||||
"Disconnected": "斷線",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Disconnected (Unused)": "斷線(未使用)",
|
||||
"Discovered": "已發現",
|
||||
"Discovery": "探索",
|
||||
"Discovery Failures": "探索失敗",
|
||||
@@ -204,7 +204,7 @@
|
||||
"Pause": "暫停",
|
||||
"Pause All": "全部暫停",
|
||||
"Paused": "暫停",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Paused (Unused)": "暫停(未使用)",
|
||||
"Pending changes": "等待中的變動",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "在一定的時間間隔,定期掃描及關閉觀察變動",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "在一定的時間間隔,定期掃描及啟用觀察變動",
|
||||
|
||||
@@ -1 +1 @@
|
||||
var langPrettyprint = {"bg":"Bulgarian","ca@valencia":"Catalan (Valencian)","cs":"Czech","da":"Danish","de":"German","el":"Greek","en":"English","en-GB":"English (United Kingdom)","eo":"Esperanto","es":"Spanish","es-ES":"Spanish (Spain)","eu":"Basque","fi":"Finnish","fr":"French","fy":"Western Frisian","hu":"Hungarian","it":"Italian","ja":"Japanese","ko-KR":"Korean (Korea)","lt":"Lithuanian","nb":"Norwegian Bokmål","nl":"Dutch","pl":"Polish","pt-BR":"Portuguese (Brazil)","pt-PT":"Portuguese (Portugal)","ru":"Russian","sk":"Slovak","sv":"Swedish","tr":"Turkish","uk":"Ukrainian","zh-CN":"Chinese (China)","zh-TW":"Chinese (Taiwan)"}
|
||||
var langPrettyprint = {"bg":"Bulgarian","ca@valencia":"Catalan (Valencian)","cs":"Czech","da":"Danish","de":"German","el":"Greek","en":"English","en-AU":"English (Australia)","en-GB":"English (United Kingdom)","eo":"Esperanto","es":"Spanish","es-ES":"Spanish (Spain)","eu":"Basque","fi":"Finnish","fr":"French","fy":"Western Frisian","hu":"Hungarian","it":"Italian","ja":"Japanese","ko-KR":"Korean (Korea)","lt":"Lithuanian","nb":"Norwegian Bokmål","nl":"Dutch","pl":"Polish","pt-BR":"Portuguese (Brazil)","pt-PT":"Portuguese (Portugal)","ru":"Russian","sk":"Slovak","sv":"Swedish","tr":"Turkish","uk":"Ukrainian","zh-CN":"Chinese (China)","zh-TW":"Chinese (Taiwan)"}
|
||||
|
||||
@@ -1 +1 @@
|
||||
var validLangs = ["bg","ca@valencia","cs","da","de","el","en","en-GB","eo","es","es-ES","eu","fi","fr","fy","hu","it","ja","ko-KR","lt","nb","nl","pl","pt-BR","pt-PT","ru","sk","sv","tr","uk","zh-CN","zh-TW"]
|
||||
var validLangs = ["bg","ca@valencia","cs","da","de","el","en","en-AU","en-GB","eo","es","es-ES","eu","fi","fr","fy","hu","it","ja","ko-KR","lt","nb","nl","pl","pt-BR","pt-PT","ru","sk","sv","tr","uk","zh-CN","zh-TW"]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -74,6 +74,15 @@ function deviceMap(l) {
|
||||
return m;
|
||||
}
|
||||
|
||||
function deviceList(m) {
|
||||
var l = [];
|
||||
for (var id in m) {
|
||||
l.push(m[id]);
|
||||
}
|
||||
l.sort(deviceCompare);
|
||||
return l;
|
||||
}
|
||||
|
||||
function folderMap(l) {
|
||||
var m = {};
|
||||
l.forEach(function (r) {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<h4 class="text-center" translate>The Syncthing Authors</h4>
|
||||
<div class="row">
|
||||
<div class="col-md-12" id="contributor-list">
|
||||
Jakob Borg, Audrius Butkevicius, Simon Frei, Alexander Graf, Alexandre Viau, Anderson Mesquita, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Evgeny Kuznetsov, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ryan Sullivan, Sergey Mishin, Stefan Tatschner, Wulf Weich, dependabot-preview[bot], greatroar, Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alberto Donato, Alessandro G., Alex Lindeman, Alex Xu, Aman Gupta, Andrew Dunham, Andrew Rabert, Andrey D, André Colomb, Anjan Momi, Antoine Lamielle, Aranjedeath, Arkadiusz Tymiński, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benno Fünfstück, Benny Ng, Boqin Qin, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Cathryne Linenweaver, Cedric Staniewski, Chris Howie, Chris Joel, Chris Tonkinson, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Bergmann, Daniel Martí, Darshil Chanpura, David Rimmer, Denis A., Dennis Wilson, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Erik Meitner, Federico Castagnini, Felix Ableitner, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gilli Sigurdsson, Gleb Sinyavskiy, Graham Miln, Han Boetes, HansK-p, Harrison Jones, Heiko Zuerker, Hugo Locurcio, Iain Barnett, Ian Johnson, Ilya Brin, Iskander Sharipov, Jaakko Hannikainen, Jacek Szafarkiewicz, Jack Croft, Jacob, Jake Peterson, James Patterson, Jaroslav Lichtblau, Jaroslav Malec, Jaya Chithra, Jens Diemer, Jerry Jacobs, Jochen Voss, Johan Andersson, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan, Jonathan Cross, Jose Manuel Delicado, Jörg Thalheim, Jędrzej Kula, Kalle Laine, Karol Różycki, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin Bushiri, Kevin White, Jr., Kurt Fitzner, Laurent Arnoud, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Lukas Lihotzki, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Marcus Legendre, Mario Majila, Mark Pulford, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max Schulze, MaximAL, Maxime Thirouin, Michael Jephcote, Michael Rienstra, Michael Tilli, Mike Boone, MikeLund, MikolajTwarog, Mingxuan Lin, Nicholas Rishel, Nico Stapelbroek, Nicolas Braud-Santoni, Nicolas Perraut, Niels Peter Roest, Nils Jakobi, NinoM4ster, Nitroretro, NoLooseEnds, Oliver Freyermuth, Otiel, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Pawel Palenica, Paweł Rozlach, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phil Davis, Phill Luby, Pier Paolo Ramon, Piotr Bejda, Pramodh KP, Rahmi Pruitt, Richard Hartmann, Robert Carosi, Robin Schoonover, Roman Zaynetdinov, Ross Smith II, Ruslan Yevdokymov, Sacheendra Talluri, Scott Klupfel, Shaarad Dalvi, Simon Mwepu, Sly_tom_cat, Stefan Kuntz, Suhas Gundimeda, Taylor Khan, Thomas Hipp, Tim Abell, Tim Howes, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tomasz Wilczyński, Tommy Thorn, Tully Robinson, Tyler Brazier, Tyler Kropp, Unrud, Veeti Paananen, Victor Buinsky, Vil Brekin, Vladimir Rusinov, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, chenrui, chucic, dependabot[bot], derekriemer, desbma, georgespatton, ghjklw, janost, jaseg, jelle van der Waa, klemens, marco-m, mv1005, otbutz, perewa, rubenbe, wangguoliang, xarx00, xjtdy888, 佛跳墙
|
||||
Jakob Borg, Audrius Butkevicius, Simon Frei, Alexander Graf, Alexandre Viau, Anderson Mesquita, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Evgeny Kuznetsov, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ryan Sullivan, Sergey Mishin, Stefan Tatschner, Wulf Weich, dependabot-preview[bot], greatroar, Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alberto Donato, Alessandro G., Alex Lindeman, Alex Xu, Aman Gupta, Andrew Dunham, Andrew Rabert, Andrey D, André Colomb, Anjan Momi, Antoine Lamielle, Aranjedeath, Arkadiusz Tymiński, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benno Fünfstück, Benny Ng, Boqin Qin, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Cathryne Linenweaver, Cedric Staniewski, Chris Howie, Chris Joel, Chris Tonkinson, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Bergmann, Daniel Martí, Darshil Chanpura, David Rimmer, Denis A., Dennis Wilson, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Erik Meitner, Federico Castagnini, Felix Ableitner, Felix Lampe, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gilli Sigurdsson, Gleb Sinyavskiy, Graham Miln, Han Boetes, HansK-p, Harrison Jones, Heiko Zuerker, Hugo Locurcio, Iain Barnett, Ian Johnson, Ilya Brin, Iskander Sharipov, Jaakko Hannikainen, Jacek Szafarkiewicz, Jack Croft, Jacob, Jake Peterson, James Patterson, Jaroslav Lichtblau, Jaroslav Malec, Jaya Chithra, Jens Diemer, Jerry Jacobs, Jochen Voss, Johan Andersson, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan, Jonathan Cross, Jose Manuel Delicado, Jörg Thalheim, Jędrzej Kula, Kalle Laine, Karol Różycki, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin Bushiri, Kevin White, Jr., Kurt Fitzner, Laurent Arnoud, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Lukas Lihotzki, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Marcus Legendre, Mario Majila, Mark Pulford, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max Schulze, MaximAL, Maxime Thirouin, Michael Jephcote, Michael Rienstra, Michael Tilli, Mike Boone, MikeLund, MikolajTwarog, Mingxuan Lin, Nicholas Rishel, Nico Stapelbroek, Nicolas Braud-Santoni, Nicolas Perraut, Niels Peter Roest, Nils Jakobi, NinoM4ster, Nitroretro, NoLooseEnds, Oliver Freyermuth, Otiel, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Pawel Palenica, Paweł Rozlach, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phil Davis, Phill Luby, Pier Paolo Ramon, Piotr Bejda, Pramodh KP, Rahmi Pruitt, Richard Hartmann, Robert Carosi, Robin Schoonover, Roman Zaynetdinov, Ross Smith II, Ruslan Yevdokymov, Sacheendra Talluri, Scott Klupfel, Shaarad Dalvi, Simon Mwepu, Sly_tom_cat, Stefan Kuntz, Suhas Gundimeda, Taylor Khan, Thomas Hipp, Tim Abell, Tim Howes, Tobias Klauser, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tomasz Wilczyński, Tommy Thorn, Tully Robinson, Tyler Brazier, Tyler Kropp, Unrud, Veeti Paananen, Victor Buinsky, Vil Brekin, Vladimir Rusinov, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, chenrui, chucic, dependabot[bot], derekriemer, desbma, georgespatton, ghjklw, janost, jaseg, jelle van der Waa, klemens, marco-m, mv1005, otbutz, perewa, rubenbe, wangguoliang, xarx00, xjtdy888, 佛跳墙
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
@@ -27,7 +27,7 @@ angular.module('syncthing.core')
|
||||
$scope.errors = [];
|
||||
$scope.model = {};
|
||||
$scope.myID = '';
|
||||
$scope.devices = [];
|
||||
$scope.devices = {};
|
||||
$scope.discoveryCache = {};
|
||||
$scope.protocolChanged = false;
|
||||
$scope.reportData = {};
|
||||
@@ -63,9 +63,6 @@ angular.module('syncthing.core')
|
||||
|
||||
$scope.folderDefaults = {
|
||||
devices: [],
|
||||
sharedDevices: {},
|
||||
selectedDevices: {},
|
||||
unrelatedDevices: {},
|
||||
type: "sendreceive",
|
||||
rescanIntervalS: 3600,
|
||||
fsWatcherDelayS: 10,
|
||||
@@ -268,7 +265,7 @@ angular.module('syncthing.core')
|
||||
$scope.$on(Events.CONFIG_SAVED, function (event, arg) {
|
||||
updateLocalConfig(arg.data);
|
||||
|
||||
$http.get(urlbase + '/system/config/insync').success(function (data) {
|
||||
$http.get(urlbase + '/config/insync').success(function (data) {
|
||||
$scope.configInSync = data.configInSync;
|
||||
}).error($scope.emitHTTPError);
|
||||
});
|
||||
@@ -378,15 +375,14 @@ angular.module('syncthing.core')
|
||||
$scope.config.options._globalAnnounceServersStr = $scope.config.options.globalAnnounceServers.join(', ');
|
||||
$scope.config.options._urAcceptedStr = "" + $scope.config.options.urAccepted;
|
||||
|
||||
$scope.devices = $scope.config.devices;
|
||||
$scope.devices.forEach(function (deviceCfg) {
|
||||
$scope.completion[deviceCfg.deviceID] = {
|
||||
$scope.devices = deviceMap($scope.config.devices);
|
||||
for (var id in $scope.devices) {
|
||||
$scope.completion[id] = {
|
||||
_total: 100,
|
||||
_needBytes: 0,
|
||||
_needItems: 0
|
||||
};
|
||||
});
|
||||
$scope.devices.sort(deviceCompare);
|
||||
};
|
||||
$scope.folders = folderMap($scope.config.folders);
|
||||
Object.keys($scope.folders).forEach(function (folder) {
|
||||
refreshFolder(folder);
|
||||
@@ -578,12 +574,12 @@ angular.module('syncthing.core')
|
||||
}
|
||||
|
||||
function refreshConfig() {
|
||||
$http.get(urlbase + '/system/config').success(function (data) {
|
||||
$http.get(urlbase + '/config').success(function (data) {
|
||||
updateLocalConfig(data);
|
||||
console.log("refreshConfig", data);
|
||||
}).error($scope.emitHTTPError);
|
||||
|
||||
$http.get(urlbase + '/system/config/insync').success(function (data) {
|
||||
$http.get(urlbase + '/config/insync').success(function (data) {
|
||||
$scope.configInSync = data.configInSync;
|
||||
}).error($scope.emitHTTPError);
|
||||
}
|
||||
@@ -689,6 +685,14 @@ angular.module('syncthing.core')
|
||||
});
|
||||
};
|
||||
|
||||
function initShareEditing(editing) {
|
||||
$scope.currentSharing = {};
|
||||
$scope.currentSharing.editing = editing;
|
||||
$scope.currentSharing.shared = [];
|
||||
$scope.currentSharing.unrelated = [];
|
||||
$scope.currentSharing.selected = {};
|
||||
};
|
||||
|
||||
$scope.refreshFailed = function (page, perpage) {
|
||||
if (!$scope.failed || !$scope.failed.folder) {
|
||||
return;
|
||||
@@ -848,10 +852,11 @@ angular.module('syncthing.core')
|
||||
if ($scope.model[folder].needTotalItems === 0) {
|
||||
return 100;
|
||||
}
|
||||
if ($scope.model[folder].needBytes == 0 && $scope.model[folder].needDeletes > 0) {
|
||||
if (($scope.model[folder].needBytes == 0 && $scope.model[folder].needDeletes > 0) || $scope.model[folder].globalBytes == 0) {
|
||||
// We don't need any data, but we have deletes that we need
|
||||
// to do. Drop down the completion percentage to indicate
|
||||
// that we have stuff to do.
|
||||
// Do the same thing in case we only have zero byte files to sync.
|
||||
return 95;
|
||||
}
|
||||
var pct = 100 * $scope.model[folder].inSyncBytes / $scope.model[folder].globalBytes;
|
||||
@@ -1006,11 +1011,11 @@ angular.module('syncthing.core')
|
||||
}
|
||||
|
||||
// loop through all devices
|
||||
var deviceCount = $scope.devices.length;
|
||||
var deviceCount = 0;
|
||||
var pendingFolders = 0;
|
||||
for (var i = 0; i < $scope.devices.length; i++) {
|
||||
for (var id in $scope.devices) {
|
||||
var status = $scope.deviceStatus({
|
||||
deviceID: $scope.devices[i].deviceID
|
||||
deviceID: id
|
||||
});
|
||||
switch (status) {
|
||||
case 'unknown':
|
||||
@@ -1023,7 +1028,8 @@ angular.module('syncthing.core')
|
||||
deviceCount--;
|
||||
break;
|
||||
}
|
||||
pendingFolders += $scope.devices[i].pendingFolders.length;
|
||||
pendingFolders += $scope.devices[id].pendingFolders.length;
|
||||
deviceCount++;
|
||||
}
|
||||
|
||||
// enumerate notifications
|
||||
@@ -1060,8 +1066,8 @@ angular.module('syncthing.core')
|
||||
};
|
||||
|
||||
$scope.friendlyNameFromShort = function (shortID) {
|
||||
var matches = $scope.devices.filter(function (n) {
|
||||
return n.deviceID.substr(0, 7) === shortID;
|
||||
var matches = Object.keys($scope.devices).filter(function (id) {
|
||||
return id.substr(0, 7) === shortID;
|
||||
});
|
||||
if (matches.length !== 1) {
|
||||
return shortID;
|
||||
@@ -1070,23 +1076,13 @@ angular.module('syncthing.core')
|
||||
};
|
||||
|
||||
$scope.friendlyNameFromID = function (deviceID) {
|
||||
var match = $scope.findDevice(deviceID);
|
||||
var match = $scope.devices[deviceID];
|
||||
if (match) {
|
||||
return $scope.deviceName(match);
|
||||
}
|
||||
return deviceID.substr(0, 6);
|
||||
};
|
||||
|
||||
$scope.findDevice = function (deviceID) {
|
||||
var matches = $scope.devices.filter(function (n) {
|
||||
return n.deviceID === deviceID;
|
||||
});
|
||||
if (matches.length !== 1) {
|
||||
return undefined;
|
||||
}
|
||||
return matches[0];
|
||||
};
|
||||
|
||||
$scope.deviceName = function (deviceCfg) {
|
||||
if (typeof deviceCfg === 'undefined' || typeof deviceCfg.deviceID === 'undefined') {
|
||||
return "";
|
||||
@@ -1109,12 +1105,8 @@ angular.module('syncthing.core')
|
||||
};
|
||||
|
||||
$scope.setDevicePause = function (device, pause) {
|
||||
$scope.devices.forEach(function (cfg) {
|
||||
if (cfg.deviceID == device) {
|
||||
cfg.paused = pause;
|
||||
}
|
||||
});
|
||||
$scope.config.devices = $scope.devices;
|
||||
$scope.devices[device].paused = pause;
|
||||
$scope.config.devices = $scope.deviceList();
|
||||
$scope.saveConfig();
|
||||
};
|
||||
|
||||
@@ -1256,7 +1248,7 @@ angular.module('syncthing.core')
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
$http.post(urlbase + '/system/config', cfg, opts).success(function () {
|
||||
$http.put(urlbase + '/config', cfg, opts).success(function () {
|
||||
refreshConfig();
|
||||
|
||||
if (callback) {
|
||||
@@ -1343,7 +1335,7 @@ angular.module('syncthing.core')
|
||||
// at it before that and conclude that the settings are
|
||||
// modified (even though we just saved) unless we update
|
||||
// here as well...
|
||||
$scope.devices = $scope.config.devices;
|
||||
$scope.devices = deviceMap($scope.config.devices);
|
||||
|
||||
$scope.saveConfig(function () {
|
||||
if (themeChanged) {
|
||||
@@ -1409,45 +1401,52 @@ angular.module('syncthing.core')
|
||||
$scope.editingExisting = true;
|
||||
$scope.willBeReintroducedBy = undefined;
|
||||
if (deviceCfg.introducedBy) {
|
||||
var introducerDevice = $scope.findDevice(deviceCfg.introducedBy);
|
||||
var introducerDevice = $scope.devices[deviceCfg.introducedBy];
|
||||
if (introducerDevice && introducerDevice.introducer) {
|
||||
$scope.willBeReintroducedBy = $scope.deviceName(introducerDevice);
|
||||
}
|
||||
}
|
||||
$scope.currentDevice._addressesStr = deviceCfg.addresses.join(', ');
|
||||
$scope.currentDevice.selectedFolders = {};
|
||||
initShareEditing('device');
|
||||
$scope.currentSharing.selected = {};
|
||||
$scope.deviceFolders($scope.currentDevice).forEach(function (folder) {
|
||||
$scope.currentDevice.selectedFolders[folder] = true;
|
||||
$scope.currentSharing.selected[folder] = true;
|
||||
});
|
||||
$scope.deviceEditor.$setPristine();
|
||||
$('#editDevice').modal();
|
||||
};
|
||||
|
||||
$scope.selectAllFolders = function () {
|
||||
angular.forEach($scope.folders, function (_, id) {
|
||||
$scope.currentDevice.selectedFolders[id] = true;
|
||||
});
|
||||
$scope.selectAllFolders = function (state) {
|
||||
var folders = $scope.folders;
|
||||
for (var id in folders) {
|
||||
$scope.currentSharing.selected[id] = !!state;
|
||||
};
|
||||
};
|
||||
|
||||
$scope.deSelectAllFolders = function () {
|
||||
angular.forEach($scope.folders, function (_, id) {
|
||||
$scope.currentDevice.selectedFolders[id] = false;
|
||||
});
|
||||
$scope.selectAllSharedFolders = function (state) {
|
||||
var devices = $scope.currentSharing.shared;
|
||||
for (var i = 0; i < devices.length; i++) {
|
||||
$scope.currentSharing.selected[devices[i].deviceID] = !!state;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.selectAllUnrelatedFolders = function (state) {
|
||||
var devices = $scope.currentSharing.unrelated;
|
||||
for (var i = 0; i < devices.length; i++) {
|
||||
$scope.currentSharing.selected[devices[i].deviceID] = !!state;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.addDevice = function (deviceID, name) {
|
||||
return $http.get(urlbase + '/system/discovery')
|
||||
.success(function (registry) {
|
||||
$scope.discovery = [];
|
||||
outer:
|
||||
for (var id in registry) {
|
||||
if ($scope.discovery.length === 5) {
|
||||
break;
|
||||
}
|
||||
for (var i = 0; i < $scope.devices.length; i++) {
|
||||
if ($scope.devices[i].deviceID === id) {
|
||||
continue outer;
|
||||
}
|
||||
if (id in $scope.devices) {
|
||||
continue
|
||||
}
|
||||
$scope.discovery.push(id);
|
||||
}
|
||||
@@ -1459,11 +1458,11 @@ angular.module('syncthing.core')
|
||||
_addressesStr: 'dynamic',
|
||||
compression: 'metadata',
|
||||
introducer: false,
|
||||
selectedFolders: {},
|
||||
pendingFolders: [],
|
||||
ignoredFolders: []
|
||||
};
|
||||
$scope.editingExisting = false;
|
||||
initShareEditing('device');
|
||||
$scope.deviceEditor.$setPristine();
|
||||
$('#editDevice').modal();
|
||||
});
|
||||
@@ -1475,10 +1474,9 @@ angular.module('syncthing.core')
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.devices = $scope.devices.filter(function (n) {
|
||||
return n.deviceID !== $scope.currentDevice.deviceID;
|
||||
});
|
||||
$scope.config.devices = $scope.devices;
|
||||
var id = $scope.currentDevice.deviceID
|
||||
delete $scope.devices[id];
|
||||
$scope.config.devices = $scope.deviceList();
|
||||
|
||||
for (var id in $scope.folders) {
|
||||
$scope.folders[id].devices = $scope.folders[id].devices.filter(function (n) {
|
||||
@@ -1499,23 +1497,11 @@ angular.module('syncthing.core')
|
||||
return x.trim();
|
||||
});
|
||||
|
||||
var done = false;
|
||||
for (var i = 0; i < $scope.devices.length && !done; i++) {
|
||||
if ($scope.devices[i].deviceID === deviceCfg.deviceID) {
|
||||
$scope.devices[i] = deviceCfg;
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
$scope.devices[deviceCfg.deviceID] = deviceCfg;
|
||||
$scope.config.devices = deviceList($scope.devices);
|
||||
|
||||
if (!done) {
|
||||
$scope.devices.push(deviceCfg);
|
||||
}
|
||||
|
||||
$scope.devices.sort(deviceCompare);
|
||||
$scope.config.devices = $scope.devices;
|
||||
|
||||
for (var id in deviceCfg.selectedFolders) {
|
||||
if (deviceCfg.selectedFolders[id]) {
|
||||
for (var id in $scope.currentSharing.selected) {
|
||||
if ($scope.currentSharing.selected[id]) {
|
||||
var found = false;
|
||||
for (i = 0; i < $scope.folders[id].devices.length; i++) {
|
||||
if ($scope.folders[id].devices[i].deviceID === deviceCfg.deviceID) {
|
||||
@@ -1573,13 +1559,13 @@ angular.module('syncthing.core')
|
||||
};
|
||||
|
||||
$scope.otherDevices = function () {
|
||||
return $scope.devices.filter(function (n) {
|
||||
return $scope.deviceList().filter(function (n) {
|
||||
return n.deviceID !== $scope.myID;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.thisDevice = function () {
|
||||
return $scope.thisDeviceIn($scope.devices);
|
||||
return $scope.devices[$scope.myID];
|
||||
};
|
||||
|
||||
$scope.thisDeviceIn = function (l) {
|
||||
@@ -1598,16 +1584,16 @@ angular.module('syncthing.core')
|
||||
};
|
||||
|
||||
$scope.setAllDevicesPause = function (pause) {
|
||||
$scope.devices.forEach(function (cfg) {
|
||||
cfg.paused = pause;
|
||||
});
|
||||
$scope.config.devices = $scope.devices;
|
||||
for (var id in $scope.devices) {
|
||||
$scope.devices[id].paused = pause;
|
||||
};
|
||||
$scope.config.devices = deviceList($scope.devices);
|
||||
$scope.saveConfig();
|
||||
}
|
||||
|
||||
$scope.isAtleastOneDevicePausedStateSetTo = function (pause) {
|
||||
for (var i = 0; i < $scope.devices.length; i++) {
|
||||
if ($scope.devices[i].paused == pause) {
|
||||
for (var id in $scope.devices) {
|
||||
if ($scope.devices[id].paused == pause) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1640,9 +1626,8 @@ angular.module('syncthing.core')
|
||||
};
|
||||
|
||||
$scope.friendlyDevices = function (str) {
|
||||
for (var i = 0; i < $scope.devices.length; i++) {
|
||||
var cfg = $scope.devices[i];
|
||||
str = str.replace(cfg.deviceID, $scope.deviceName(cfg));
|
||||
for (var id in $scope.devices) {
|
||||
str = str.replace(id, $scope.deviceName($scope.devices[id]));
|
||||
}
|
||||
return str;
|
||||
};
|
||||
@@ -1651,6 +1636,10 @@ angular.module('syncthing.core')
|
||||
return folderList($scope.folders);
|
||||
};
|
||||
|
||||
$scope.deviceList = function () {
|
||||
return deviceList($scope.devices);
|
||||
};
|
||||
|
||||
$scope.directoryList = [];
|
||||
|
||||
$scope.$watch('currentFolder.path', function (newvalue) {
|
||||
@@ -1723,18 +1712,15 @@ angular.module('syncthing.core')
|
||||
$scope.currentFolder.path = $scope.currentFolder.path.slice(0, -1);
|
||||
}
|
||||
// Cache complete device objects indexed by ID for lookups
|
||||
var devMap = deviceMap($scope.devices)
|
||||
$scope.currentFolder.sharedDevices = [];
|
||||
$scope.currentFolder.selectedDevices = {};
|
||||
initShareEditing('folder');
|
||||
$scope.currentFolder.devices.forEach(function (n) {
|
||||
if (n.deviceID !== $scope.myID) {
|
||||
$scope.currentFolder.sharedDevices.push(devMap[n.deviceID]);
|
||||
$scope.currentSharing.shared.push($scope.devices[n.deviceID]);
|
||||
}
|
||||
$scope.currentFolder.selectedDevices[n.deviceID] = true;
|
||||
$scope.currentSharing.selected[n.deviceID] = true;
|
||||
});
|
||||
$scope.currentFolder.unrelatedDevices = $scope.devices.filter(function (n) {
|
||||
return n.deviceID !== $scope.myID
|
||||
&& !$scope.currentFolder.selectedDevices[n.deviceID]
|
||||
$scope.currentSharing.unrelated = $scope.deviceList().filter(function (n) {
|
||||
return n.deviceID !== $scope.myID && !$scope.currentSharing.selected[n.deviceID]
|
||||
});
|
||||
if ($scope.currentFolder.versioning && $scope.currentFolder.versioning.type === "trashcan") {
|
||||
$scope.currentFolder.trashcanFileVersioning = true;
|
||||
@@ -1794,16 +1780,16 @@ angular.module('syncthing.core')
|
||||
};
|
||||
|
||||
$scope.selectAllSharedDevices = function (state) {
|
||||
var devices = $scope.currentFolder.sharedDevices;
|
||||
var devices = $scope.currentSharing.shared;
|
||||
for (var i = 0; i < devices.length; i++) {
|
||||
$scope.currentFolder.selectedDevices[devices[i].deviceID] = !!state;
|
||||
$scope.currentSharing.selected[devices[i].deviceID] = !!state;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.selectAllUnrelatedDevices = function (state) {
|
||||
var devices = $scope.currentFolder.unrelatedDevices;
|
||||
var devices = $scope.currentSharing.unrelated;
|
||||
for (var i = 0; i < devices.length; i++) {
|
||||
$scope.currentFolder.selectedDevices[devices[i].deviceID] = !!state;
|
||||
$scope.currentSharing.selected[devices[i].deviceID] = !!state;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1811,8 +1797,9 @@ angular.module('syncthing.core')
|
||||
$http.get(urlbase + '/svc/random/string?length=10').success(function (data) {
|
||||
$scope.editingExisting = false;
|
||||
$scope.currentFolder = angular.copy($scope.folderDefaults);
|
||||
initShareEditing('folder');
|
||||
$scope.currentFolder.id = (data.random.substr(0, 5) + '-' + data.random.substr(5, 5)).toLowerCase();
|
||||
$scope.currentFolder.unrelatedDevices = $scope.otherDevices();
|
||||
$scope.currentSharing.unrelated = $scope.otherDevices();
|
||||
$scope.ignores.text = '';
|
||||
$scope.ignores.error = null;
|
||||
$scope.ignores.disabled = false;
|
||||
@@ -1828,8 +1815,11 @@ angular.module('syncthing.core')
|
||||
$scope.currentFolder.viewFlags = {
|
||||
importFromOtherDevice: true
|
||||
};
|
||||
$scope.currentFolder.selectedDevices[device] = true;
|
||||
$scope.currentFolder.unrelatedDevices = $scope.otherDevices();
|
||||
initShareEditing('folder');
|
||||
$scope.currentSharing.selected[device] = true;
|
||||
$scope.currentSharing.unrelated = $scope.deviceList().filter(function (n) {
|
||||
return n.deviceID !== $scope.myID && !$scope.currentSharing.selected[n.deviceID]
|
||||
});
|
||||
$scope.ignores.text = '';
|
||||
$scope.ignores.error = null;
|
||||
$scope.ignores.disabled = false;
|
||||
@@ -1847,25 +1837,23 @@ angular.module('syncthing.core')
|
||||
$scope.saveFolder = function () {
|
||||
$('#editFolder').modal('hide');
|
||||
var folderCfg = angular.copy($scope.currentFolder);
|
||||
folderCfg.selectedDevices[$scope.myID] = true;
|
||||
$scope.currentSharing.selected[$scope.myID] = true;
|
||||
var newDevices = [];
|
||||
folderCfg.devices.forEach(function (dev) {
|
||||
if (folderCfg.selectedDevices[dev.deviceID] === true) {
|
||||
if ($scope.currentSharing.selected[dev.deviceID] === true) {
|
||||
newDevices.push(dev);
|
||||
delete folderCfg.selectedDevices[dev.deviceID];
|
||||
delete $scope.currentSharing.selected[dev.deviceID];
|
||||
};
|
||||
});
|
||||
for (var deviceID in folderCfg.selectedDevices) {
|
||||
if (folderCfg.selectedDevices[deviceID] === true) {
|
||||
for (var deviceID in $scope.currentSharing.selected) {
|
||||
if ($scope.currentSharing.selected[deviceID] === true) {
|
||||
newDevices.push({
|
||||
deviceID: deviceID
|
||||
});
|
||||
}
|
||||
}
|
||||
folderCfg.devices = newDevices;
|
||||
delete folderCfg.sharedDevices;
|
||||
delete folderCfg.selectedDevices;
|
||||
delete folderCfg.unrelatedDevices;
|
||||
delete $scope.currentSharing;
|
||||
|
||||
if (folderCfg.fileVersioningSelector === "trashcan") {
|
||||
folderCfg.versioning = {
|
||||
@@ -1947,12 +1935,9 @@ angular.module('syncthing.core')
|
||||
// Bump time
|
||||
pendingFolder.time = (new Date()).toISOString();
|
||||
|
||||
for (var i = 0; i < $scope.devices.length; i++) {
|
||||
if ($scope.devices[i].deviceID == device) {
|
||||
$scope.devices[i].ignoredFolders.push(pendingFolder);
|
||||
$scope.saveConfig();
|
||||
return;
|
||||
}
|
||||
if (device in $scope.devices) {
|
||||
$scope.devices[device].ignoredFolders.push(pendingFolder);
|
||||
$scope.saveConfig();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1960,7 +1945,7 @@ angular.module('syncthing.core')
|
||||
var names = [];
|
||||
folderCfg.devices.forEach(function (device) {
|
||||
if (device.deviceID !== $scope.myID) {
|
||||
names.push($scope.deviceName($scope.findDevice(device.deviceID)));
|
||||
names.push($scope.deviceName($scope.devices[device.deviceID]));
|
||||
}
|
||||
});
|
||||
names.sort();
|
||||
@@ -2480,7 +2465,6 @@ angular.module('syncthing.core')
|
||||
$scope.modalLoaded = function () {
|
||||
// once all modal elements have been processed
|
||||
if ($('modal').length === 0) {
|
||||
|
||||
// pseudo main. called on all definitions assigned
|
||||
initController();
|
||||
}
|
||||
|
||||
@@ -16,10 +16,7 @@ angular.module('syncthing.core')
|
||||
}
|
||||
});
|
||||
//Prevents user from adding a duplicate ID
|
||||
var matches = scope.devices.filter(function (n) {
|
||||
return n.deviceID == viewValue;
|
||||
}).length;
|
||||
if (matches > 0) {
|
||||
if (scope.devices.hasOwnProperty(viewValue)) {
|
||||
ctrl.$setValidity('unique', false);
|
||||
} else {
|
||||
ctrl.$setValidity('unique', true);
|
||||
|
||||
@@ -69,17 +69,17 @@
|
||||
<label translate for="folders">Share Folders With Device</label>
|
||||
<p class="help-block">
|
||||
<span translate>Select the folders to share with this device.</span> 
|
||||
<small><a href="#" ng-click="selectAllFolders()" translate>Select All</a> 
|
||||
<a href="#" ng-click="deSelectAllFolders()" translate>Deselect All</a></small>
|
||||
<small><a href="#" ng-click="selectAllFolders(true)" translate>Select All</a> 
|
||||
<a href="#" ng-click="selectAllFolders(false)" translate>Deselect All</a></small>
|
||||
</p>
|
||||
<div class="row">
|
||||
<div class="col-md-4" ng-repeat="folder in folderList()">
|
||||
<div class="checkbox">
|
||||
<label ng-if="folder.label.length == 0">
|
||||
<input type="checkbox" ng-model="currentDevice.selectedFolders[folder.id]"> {{folder.id}}
|
||||
<input type="checkbox" ng-model="currentSharing.selected[folder.id]"> {{folder.id}}
|
||||
</label>
|
||||
<label ng-if="folder.label.length != 0">
|
||||
<input type="checkbox" ng-model="currentDevice.selectedFolders[folder.id]"> <span tooltip data-original-title="{{folder.id}}">{{folder.label}}</span>
|
||||
<input type="checkbox" ng-model="currentSharing.selected[folder.id]"> <span tooltip data-original-title="{{folder.id}}">{{folder.label}}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
</div>
|
||||
|
||||
<div id="folder-sharing" class="tab-pane">
|
||||
<div class="form-group" ng-if="currentFolder.sharedDevices.length">
|
||||
<div class="form-group" ng-if="currentSharing.shared.length">
|
||||
<label translate>Currently Shared With Devices</label>
|
||||
<p class="help-block">
|
||||
<span translate>Deselect devices to stop sharing this folder with.</span> 
|
||||
@@ -54,16 +54,16 @@
|
||||
<a href="#" ng-click="selectAllSharedDevices(false)" translate>Deselect All</a></small>
|
||||
</p>
|
||||
<div class="row">
|
||||
<div class="col-md-4" ng-repeat="device in currentFolder.sharedDevices">
|
||||
<div class="col-md-4" ng-repeat="device in currentSharing.shared">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="currentFolder.selectedDevices[device.deviceID]" /> {{deviceName(device)}}
|
||||
<input type="checkbox" ng-model="currentSharing.selected[device.deviceID]" /> {{deviceName(device)}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" ng-if="currentFolder.unrelatedDevices.length || otherDevices().length <= 0">
|
||||
<div class="form-group" ng-if="currentSharing.unrelated.length || otherDevices().length <= 0">
|
||||
<label translate>Unshared Devices</label>
|
||||
<p class="help-block" ng-if="otherDevices().length > 0">
|
||||
<span translate>Select additional devices to share this folder with.</span> 
|
||||
@@ -74,10 +74,10 @@
|
||||
<span translate>There are no devices to share this folder with.</span>
|
||||
</p>
|
||||
<div class="row">
|
||||
<div class="col-md-4" ng-repeat="device in currentFolder.unrelatedDevices">
|
||||
<div class="col-md-4" ng-repeat="device in currentSharing.unrelated">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="currentFolder.selectedDevices[device.deviceID]" /> {{deviceName(device)}}
|
||||
<input type="checkbox" ng-model="currentSharing.selected[device.deviceID]" /> {{deviceName(device)}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
950
gui/default/untrusted/index.html
Normal file
950
gui/default/untrusted/index.html
Normal file
@@ -0,0 +1,950 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
// Copyright (C) 2014 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/.
|
||||
|
||||
-->
|
||||
<html lang="en" ng-app="syncthing" ng-controller="SyncthingController">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<meta name="description" content=""/>
|
||||
<meta name="author" content=""/>
|
||||
<link rel="shortcut icon" href="assets/img/favicon-{{syncthingStatus()}}.png"/>
|
||||
<link rel="mask-icon" href="assets/img/safari-pinned-tab.svg" color="#0882c8"/>
|
||||
|
||||
<title ng-bind="thisDeviceName() + ' | Syncthing'"></title>
|
||||
<link href="vendor/bootstrap/css/bootstrap.css" rel="stylesheet"/>
|
||||
<link href="vendor/daterangepicker/daterangepicker.css" rel="stylesheet"/>
|
||||
<link href="assets/font/raleway.css" rel="stylesheet"/>
|
||||
<link href="vendor/fork-awesome/css/fork-awesome.css" rel="stylesheet"/>
|
||||
<link href="vendor/fork-awesome/css/v5-compat.css" rel="stylesheet"/>
|
||||
<link href="assets/css/overrides.css" rel="stylesheet"/>
|
||||
<link href="assets/css/theme.css" rel="stylesheet"/>
|
||||
<link href="vendor/fancytree/css/ui.fancytree.css" rel="stylesheet"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>
|
||||
<nav class="navbar navbar-top navbar-default" role="navigation">
|
||||
<div class="container">
|
||||
<span class="navbar-brand" aria-hidden="true">
|
||||
<img class="logo hidden-xs" src="assets/img/logo-horizontal.svg" height="32" width="117" alt=""/>
|
||||
<img class="logo hidden visible-xs" src="assets/img/favicon-default.png" height="32" alt=""/>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container content">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-danger">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
<div class="panel-icon">
|
||||
<span class="fas fa-exclamation-circle"></span>
|
||||
</div>
|
||||
Warning!
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
The Syncthing admin interface requires JavaScript. Please enable JavaScript in your web browser and try again.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</noscript>
|
||||
|
||||
<div class="ng-cloak">
|
||||
<script type="text/javascript" src="syncthing/development/logbar.js"></script>
|
||||
<div ng-if="version.isBeta" ng-include="'syncthing/development/logbar.html'"></div>
|
||||
<!-- Top bar -->
|
||||
|
||||
<nav class="navbar navbar-top navbar-default" role="navigation">
|
||||
<div class="container">
|
||||
<span class="navbar-brand" aria-hidden="true">
|
||||
<img class="logo hidden-xs" src="assets/img/logo-horizontal.svg" height="32" width="117" alt=""/>
|
||||
<img class="logo hidden visible-xs" src="assets/img/favicon-default.png" height="32" alt=""/>
|
||||
</span>
|
||||
<p class="navbar-text hidden-xs" ng-class="{'hidden-sm':upgradeInfo && upgradeInfo.newer}">{{thisDeviceName()}}</p>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li ng-if="upgradeInfo && upgradeInfo.newer" class="upgrade-newer">
|
||||
<button type="button" class="btn navbar-btn btn-primary btn-sm" data-toggle="modal" data-target="#upgrade">
|
||||
<span class="fas fa-arrow-circle-up"></span>
|
||||
<span class="hidden-xs" translate translate-value-version="{{upgradeInfo.latest}}">Upgrade To {%version%}</span>
|
||||
</button>
|
||||
</li>
|
||||
<li ng-if="upgradeInfo && upgradeInfo.majorNewer" class="upgrade-newer-major">
|
||||
<button type="button" class="btn navbar-btn btn-danger btn-sm" data-toggle="modal" data-target="#majorUpgrade">
|
||||
<span class="fas fa-arrow-circle-up"></span>
|
||||
<span class="hidden-xs" translate translate-value-version="{{upgradeInfo.latest}}">Upgrade To {%version%}</span>
|
||||
</button>
|
||||
</li>
|
||||
<li class="dropdown" language-select></li>
|
||||
<li>
|
||||
<a class="navbar-link" href="https://docs.syncthing.net/intro/gui.html" target="_blank">
|
||||
<span class="fas fa-question-circle"></span>
|
||||
<span class="hidden-xs" translate>Help</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="dropdown action-menu">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
|
||||
<span class="fas fa-cog"></span>
|
||||
<span class="hidden-xs" translate>Actions</span>
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="" ng-click="showSettings()"><span class="fas fa-fw fa-cog"></span> <span translate>Settings</span></a></li>
|
||||
<li><a href="" data-toggle="modal" data-target="#idqr" ng-click="currentDevice=thisDevice()"><span class="fas fa-fw fa-qrcode"></span> <span translate>Show ID</span></a></li>
|
||||
<li class="divider" aria-hidden="true"></li>
|
||||
<li><a href="" ng-click="shutdown()"><span class="fas fa-fw fa-power-off"></span> <span translate>Shutdown</span></a></li>
|
||||
<li><a href="" ng-click="restart()"><span class="fas fa-fw fa-refresh"></span> <span translate>Restart</span></a></li>
|
||||
<li class="divider" aria-hidden="true"></li>
|
||||
<li class="visible-xs">
|
||||
<a href="https://docs.syncthing.net/intro/gui.html" target="_blank">
|
||||
<span class="fas fa-fw fa-question-circle"></span> <span translate>Help</span>
|
||||
</a>
|
||||
</li>
|
||||
<li><a href="" data-toggle="modal" data-target="#about"><span class="far fa-fw fa-heart"></span> <span translate>About</span></a></li>
|
||||
<li class="divider" aria-hidden="true"></li>
|
||||
<li><a href="" ng-click="advanced()"><span class="fas fa-fw fa-cogs"></span> <span translate>Advanced</span></a></li>
|
||||
<li><a href="" ng-click="logging.show()"><span class="far fa-fw fa-file-alt"></span> <span translate>Logs</span></a></li>
|
||||
<li class="divider" aria-hidden="true" ng-if="config.gui.debugging"></li>
|
||||
<li><a href="/rest/debug/support" target="_blank" ng-if="config.gui.debugging"><span class="fa fa-user-md"></span> <span translate>Support Bundle</span></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container content">
|
||||
|
||||
<!-- Panel: Open, no auth -->
|
||||
|
||||
<div ng-if="openNoAuth" class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-danger">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
<div class="panel-icon">
|
||||
<span class="fas fa-exclamation-circle"></span>
|
||||
</div>
|
||||
<span translate>Danger!</span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
<span translate>The Syncthing admin interface is configured to allow remote access without a password.</span>
|
||||
<b><span translate>This can easily give hackers access to read and change any files on your computer.</span></b>
|
||||
<span translate>Please set a GUI Authentication User and Password in the Settings dialog.</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<button type="button" class="btn btn-sm btn-default pull-right" ng-click="showSettings()">
|
||||
<span class="fas fa-cog"></span> <span translate>Settings</span>
|
||||
</button>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Panel: Restart Needed -->
|
||||
|
||||
<div ng-if="!configInSync" class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-warning">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
<div class="panel-icon">
|
||||
<span class="fas fa-exclamation-circle"></span>
|
||||
</div>
|
||||
<span translate>Restart Needed</span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p translate>The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.</p>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<button type="button" class="btn btn-sm btn-default pull-right" ng-click="restart()">
|
||||
<span class="fas fa-refresh"></span> <span translate>Restart</span>
|
||||
</button>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="config">
|
||||
|
||||
<!-- Panel: Notifications -->
|
||||
|
||||
<div ng-if="config.options && config.options.unackedNotificationIDs" ng-include="'syncthing/core/notifications.html'"></div>
|
||||
|
||||
<!-- Panel: New Device -->
|
||||
|
||||
<div ng-repeat="pendingDevice in config.pendingDevices" class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-warning">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
<identicon class="panel-icon" data-value="device"></identicon>
|
||||
<span translate>New Device</span>
|
||||
<span class="pull-right">{{ pendingDevice.time | date:"yyyy-MM-dd HH:mm:ss" }}</span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
<span translate translate-value-device="{{ pendingDevice.deviceID }}" translate-value-address="{{ pendingDevice.address }}" translate-value-name="{{ pendingDevice.name }}">
|
||||
Device "{%name%}" ({%device%} at {%address%}) wants to connect. Add new device?
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="panel-footer clearfix">
|
||||
<div class="pull-right">
|
||||
<button type="button" class="btn btn-sm btn-success" ng-click="addDevice(pendingDevice.deviceID, pendingDevice.name)">
|
||||
<span class="fas fa-plus"></span> <span translate>Add Device</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-danger" ng-click="ignoreDevice(pendingDevice)">
|
||||
<span class="fas fa-times"></span> <span translate>Ignore</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Panel: New Folder -->
|
||||
<div ng-repeat="device in config.devices">
|
||||
<div ng-repeat="pendingFolder in device.pendingFolders" class="row reject">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-warning">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
<div class="panel-icon">
|
||||
<span class="fas fa-folder"></span>
|
||||
</div>
|
||||
<span translate ng-if="!folders[pendingFolder.id]">New Folder</span>
|
||||
<span translate ng-if="folders[pendingFolder.id]">Share Folder</span>
|
||||
<span class="pull-right">{{ pendingFolder.time | date:"yyyy-MM-dd HH:mm:ss" }}</span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
<span ng-if="pendingFolder.label.length == 0" translate translate-value-device="{{ deviceName(devices[device.deviceID]) }}" translate-value-folder="{{ pendingFolder.id }}">
|
||||
{%device%} wants to share folder "{%folder%}".
|
||||
</span>
|
||||
<span ng-if="pendingFolder.label.length != 0" translate translate-value-device="{{ deviceName(devices[device.deviceID]) }}" translate-value-folder="{{ pendingFolder.id }}" translate-value-folderlabel="{{ pendingFolder.label }}">
|
||||
{%device%} wants to share folder "{%folderlabel%}" ({%folder%}).
|
||||
</span>
|
||||
<span translate ng-if="folders[pendingFolder.id]">Share this folder?</span>
|
||||
<span translate ng-if="!folders[pendingFolder.id]">Add new folder?</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="panel-footer clearfix">
|
||||
<div class="pull-right">
|
||||
<button type="button" class="btn btn-sm btn-success" ng-click="addFolderAndShare(pendingFolder.id, pendingFolder.label, device.deviceID)" ng-if="!folders[pendingFolder.id]">
|
||||
<span class="fas fa-check"></span> <span translate>Add</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-success" ng-click="shareFolderWithDevice(pendingFolder.id, device.deviceID)" ng-if="folders[pendingFolder.id]">
|
||||
<span class="fas fa-check"></span> <span translate>Share</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-danger" ng-click="ignoreFolder(device.deviceID, pendingFolder)">
|
||||
<span class="fas fa-times"></span> <span translate>Ignore</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Panel: Notice -->
|
||||
|
||||
<div ng-if="errorList().length > 0" class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-warning">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
<div class="panel-icon">
|
||||
<span class="fas fa-exclamation-circle"></span>
|
||||
</div>
|
||||
<span translate>Notice</span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p ng-repeat="err in errorList()">
|
||||
<small>{{err.when | date:"yyyy-MM-dd HH:mm:ss"}}:</small>
|
||||
<span ng-bind-html="friendlyDevices(err.message) | linky: '_blank'"></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<button type="button" class="btn btn-sm btn-default pull-right" ng-click="clearErrors()">
|
||||
<span class="fas fa-check"></span> <span translate>OK</span>
|
||||
</button>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Panel: FS watcher errors -->
|
||||
|
||||
<div ng-if="sizeOf(fsWatcherErrorMap()) > 0" class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-warning">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
<div class="panel-icon">
|
||||
<span class="fas fa-exclamation-circle"></span>
|
||||
</div>
|
||||
<span translate>Filesystem Watcher Errors</span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
<span translate>For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.</span> <a href="https://forum.syncthing.net" target="_blank"><span class="fas fa-question-circle"></span> <span translate>Support</span></a>
|
||||
</p>
|
||||
<table>
|
||||
<tr ng-repeat="(id, err) in fsWatcherErrorMap()">
|
||||
<td>{{folderLabel(id)}}</td><td>{{err}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- First regular row -->
|
||||
|
||||
<div class="row">
|
||||
|
||||
<!-- Folder list (top left) -->
|
||||
|
||||
<div class="col-md-6" aria-labelledby="folder_list" role="region" >
|
||||
<h3 id="folder_list" translate>Folders</h3>
|
||||
<div class="panel-group" id="folders">
|
||||
<div class="panel panel-default" ng-repeat="folder in folderList()">
|
||||
<button class="btn panel-heading" data-toggle="collapse" data-parent="#folders" data-target="#folder-{{$index}}" aria-expanded="false">
|
||||
<div class="panel-progress" ng-show="folderStatus(folder) == 'syncing'" ng-attr-style="width: {{syncPercentage(folder.id) | percent}}"></div>
|
||||
<div class="panel-progress" ng-show="folderStatus(folder) == 'scanning' && scanProgress[folder.id] != undefined" ng-attr-style="width: {{scanPercentage(folder.id) | percent}}"></div>
|
||||
<h4 class="panel-title">
|
||||
<div class="panel-icon hidden-xs">
|
||||
<span ng-if="folder.type == 'sendreceive'" class="fas fa-fw fa-folder"></span>
|
||||
<span ng-if="folder.type == 'sendonly'" class="fas fa-fw fa-upload"></span>
|
||||
<span ng-if="folder.type == 'receiveonly'" class="fas fa-fw fa-download"></span>
|
||||
<span ng-if="folder.type == 'receiveencrypted'" class="fas fa-fw fa-lock"></span>
|
||||
</div>
|
||||
<div class="panel-status pull-right text-{{folderClass(folder)}}" ng-switch="folderStatus(folder)">
|
||||
<span ng-switch-when="paused"><span class="hidden-xs" translate>Paused</span><span class="visible-xs" aria-label="{{'Paused' | translate}}"><i class="fas fa-fw fa-pause"></i></span></span>
|
||||
<span ng-switch-when="unknown"><span class="hidden-xs" translate>Unknown</span><span class="visible-xs" aria-label="{{'Unknown' | translate}}"><i class="fas fa-fw fa-question-circle"></i></span></span>
|
||||
<span ng-switch-when="unshared"><span class="hidden-xs" translate>Unshared</span><span class="visible-xs" aria-label="{{'Unshared' | translate}}"><i class="fas fa-fw fa-unlink"></i></span></span>
|
||||
<span ng-switch-when="scan-waiting"><span class="hidden-xs" translate>Waiting to Scan</span><span class="visible-xs" aria-label="{{'Waiting to Scan' | translate}}"><i class="fas fa-fw fa-hourglass-half"></i></span></span>
|
||||
<span ng-switch-when="cleaning"><span class="hidden-xs" translate>Cleaning Versions</span><span class="visible-xs" aria-label="{{'Cleaning Versions' | translate}}"><i class="fas fa-fw fa-recycle"></i></span></span>
|
||||
<span ng-switch-when="clean-waiting"><span class="hidden-xs" translate>Waiting to Clean</span><span class="visible-xs" aria-label="{{'Waiting to Clean' | translate}}"><i class="fas fa-fw fa-hourglass-half"></i></span></span>
|
||||
<span ng-switch-when="stopped"><span class="hidden-xs" translate>Stopped</span><span class="visible-xs" aria-label="{{'Stopped' | translate}}"><i class="fas fa-fw fa-stop"></i></span></span>
|
||||
<span ng-switch-when="scanning">
|
||||
<span class="hidden-xs" translate>Scanning</span>
|
||||
<span class="hidden-xs" ng-if="scanPercentage(folder.id) != undefined">
|
||||
({{scanPercentage(folder.id) | percent}})
|
||||
</span>
|
||||
<span class="visible-xs" aria-label="{{'Scanning' | translate}}"><i class="fas fa-fw fa-search"></i></span>
|
||||
</span>
|
||||
<span ng-switch-when="idle"><span class="hidden-xs" translate>Up to Date</span><span class="visible-xs" aria-label="{{'Up to Date' | translate}}"><i class="fas fa-fw fa-check"></i></span></span>
|
||||
<span ng-switch-when="localadditions"><span class="hidden-xs" translate>Local Additions</span><span class="visible-xs" aria-label="{{'Local Additions' | translate}}"><i class="fas fa-fw fa-check"></i></span></span>
|
||||
<span ng-switch-when="sync-waiting">
|
||||
<span class="hidden-xs" translate>Waiting to Sync</span>
|
||||
<span class="visible-xs" aria-label="{{'Waiting to Sync' | translate}}"><i class="fas fa-fw fa-hourglass-half"></i></span>
|
||||
</span>
|
||||
<span ng-switch-when="sync-preparing">
|
||||
<span class="hidden-xs" translate>Preparing to Sync</span>
|
||||
<span class="visible-xs" aria-label="{{'Preparing to Sync' | translate}}"><i class="fas fa-fw fa-hourglass-half"></i></span>
|
||||
</span>
|
||||
<span ng-switch-when="syncing">
|
||||
<span class="hidden-xs" translate>Syncing</span>
|
||||
<span>({{syncPercentage(folder.id) | percent}}, {{model[folder.id].needBytes | binary}}B)</span>
|
||||
</span>
|
||||
<span ng-switch-when="outofsync"><span class="hidden-xs" translate>Out of Sync</span><span class="visible-xs" aria-label="{{'Out of Sync' | translate}}"><i class="fas fa-fw fa-exclamation-circle"></i></span></span>
|
||||
<span ng-switch-when="faileditems"><span class="hidden-xs" translate>Failed Items</span><span class="visible-xs" aria-label="{{'Failed Items' | translate}}"><i class="fas fa-fw fa-exclamation-circle"></i></span></span>
|
||||
<span ng-switch-when="localunencrypted"><span class="hidden-xs">{{'Unexpected Items' | translate}}</span><span class="visible-xs" aria-label="{{'Unexpected Items' | translate}}"><i class="fas fa-fw fa-exclamation-circle"></i></span></span>
|
||||
</div>
|
||||
<div class="panel-title-text">
|
||||
<span tooltip data-original-title="{{folder.label.length != 0 ? folder.id : ''}}">{{folder.label.length != 0 ? folder.label : folder.id}}</span>
|
||||
</div>
|
||||
</h4>
|
||||
</button>
|
||||
<div id="folder-{{$index}}" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
<table class="table table-condensed table-striped table-auto">
|
||||
<tbody>
|
||||
<tr ng-show="folder.label != undefined && folder.label.length > 0">
|
||||
<th><span class="fas fa-fw fa-info-circle"></span> <span translate>Folder ID</span></th>
|
||||
<td class="text-right no-overflow-ellipse">{{folder.id}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><span class="fas fa-fw fa-folder-open"></span> <span translate>Folder Path</span></th>
|
||||
<td class="text-right">
|
||||
<span tooltip data-original-title="{{folder.path}}">{{folder.path}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="!folder.paused && (model[folder.id].invalid || model[folder.id].error)">
|
||||
<th><span class="fas fa-fw fa-exclamation-triangle"></span> <span translate>Error</span></th>
|
||||
<td class="text-right">{{model[folder.id].invalid || model[folder.id].error}}</td>
|
||||
</tr>
|
||||
<tr ng-if="!folder.paused">
|
||||
<th><span class="fas fa-fw fa-globe"></span> <span translate>Global State</span></th>
|
||||
<td class="text-right">
|
||||
<span tooltip data-original-title="{{model[folder.id].globalFiles | alwaysNumber | localeNumber}} {{'files' | translate}}, {{model[folder.id].globalDirectories | alwaysNumber | localeNumber}} {{'directories' | translate}}, ~{{model[folder.id].globalBytes | binary}}B">
|
||||
<span class="far fa-copy"></span> {{model[folder.id].globalFiles | alwaysNumber | localeNumber}} 
|
||||
<span class="far fa-folder"></span> {{model[folder.id].globalDirectories | alwaysNumber | localeNumber}} 
|
||||
<span class="far fa-hdd"></span> ~{{model[folder.id].globalBytes | binary}}B
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="!folder.paused">
|
||||
<th><span class="fas fa-fw fa-home"></span> <span translate>Local State</span></th>
|
||||
<td class="text-right">
|
||||
<span tooltip data-original-title="{{model[folder.id].localFiles | alwaysNumber | localeNumber}} {{'files' | translate}}, {{model[folder.id].localDirectories | alwaysNumber | localeNumber}} {{'directories' | translate}}, ~{{model[folder.id].localBytes | binary}}B">
|
||||
<span class="far fa-copy"></span> {{model[folder.id].localFiles | alwaysNumber | localeNumber}} 
|
||||
<span class="far fa-folder"></span> {{model[folder.id].localDirectories | alwaysNumber | localeNumber}} 
|
||||
<span class="far fa-hdd"></span> ~{{model[folder.id].localBytes | binary}}B<!-- get rid of the annoying trailing whitespace
|
||||
--><span ng-if="model[folder.id].ignorePatterns"><br/><i><small translate class="text-muted">Reduced by ignore patterns</small></i></span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="model[folder.id].needTotalItems > 0">
|
||||
<th><span class="fas fa-fw fa-cloud-download-alt"></span> <span translate>Out of Sync Items</span></th>
|
||||
<td class="text-right">
|
||||
<a href="" ng-click="showNeed(folder.id)">{{model[folder.id].needTotalItems | alwaysNumber | localeNumber}} <span translate>items</span>, ~{{model[folder.id].needBytes | binary}}B</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="folderStatus(folder) === 'scanning' && scanRate(folder.id) > 0">
|
||||
<th><span class="fas fa-fw fa-hourglass-half"></span> <span translate>Scan Time Remaining</span></th>
|
||||
<td class="text-right">
|
||||
<span tooltip data-original-title="{{scanRate(folder.id) | binary}}B/s">~ {{scanRemaining(folder.id)}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="hasFailedFiles(folder.id)">
|
||||
<th><span class="fas fa-fw fa-exclamation-circle"></span> <span translate>Failed Items</span></th>
|
||||
<!-- Show the number of failed items as a link to bring up the list. -->
|
||||
<td class="text-right">
|
||||
<a href="" ng-click="showFailed(folder.id)">{{model[folder.id].pullErrors | alwaysNumber | localeNumber}} <span translate>items</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="hasReceiveOnlyChanged(folder)">
|
||||
<th><span class="fas fa-fw fa-exclamation-circle"></span> <span translate>Locally Changed Items</span></th>
|
||||
<td class="text-right">
|
||||
<a href="" ng-click="showLocalChanged(folder.id, folder.type)">{{model[folder.id].receiveOnlyTotalItems | alwaysNumber | localeNumber}} <span translate>items</span>, ~{{model[folder.id].receiveOnlyChangedBytes | binary}}B</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="hasReceiveEncryptedItems(folder)">
|
||||
<th><span class="fas fa-fw fa-exclamation-circle"></span> <span translate>Locally Changed Items</span></th>
|
||||
<td class="text-right">
|
||||
<a href="" ng-click="showLocalChanged(folder.id, folder.type)">{{receiveEncryptedItemsCount(folder) | alwaysNumber | localeNumber}} <span translate>items</span>, ~{{model[folder.id].receiveOnlyChangedBytes | binary}}B</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="folder.type != 'sendreceive'">
|
||||
<th><span class="fas fa-fw fa-folder"></span> <span translate>Folder Type</span></th>
|
||||
<td class="text-right">
|
||||
<span ng-if="folder.type == 'sendonly'" translate>Send Only</span>
|
||||
<span ng-if="folder.type == 'receiveonly'" translate>Receive Only</span>
|
||||
<span ng-if="folder.type == 'receiveencrypted'" translate>Receive Encrypted</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="folder.ignorePerms">
|
||||
<th><span class="far fa-fw fa-minus-square"></span> <span translate>Ignore Permissions</span></th>
|
||||
<td class="text-right">
|
||||
<span translate>Yes</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><span class="fas fa-fw fa-refresh"></span> <span translate>Rescans</span></th>
|
||||
<td class="text-right">
|
||||
<div ng-if="folder.rescanIntervalS > 0">
|
||||
<span ng-if="!folder.fsWatcherEnabled" tooltip data-original-title="{{'Periodic scanning at given interval and disabled watching for changes' | translate}}">
|
||||
<span class="far fa-clock"></span> {{folder.rescanIntervalS | duration}} 
|
||||
<span class="fas fa-eye-slash"></span> <span translate>Disabled</span>
|
||||
</span>
|
||||
<span ng-if="folder.fsWatcherEnabled && (!model[folder.id].watchError || folder.paused || folderStatus(folder) === 'stopped')" tooltip data-original-title="{{'Periodic scanning at given interval and enabled watching for changes' | translate}}">
|
||||
<span class="far fa-clock"></span> {{folder.rescanIntervalS | duration}} 
|
||||
<span class="fas fa-eye"></span> <span translate>Enabled</span>
|
||||
</span>
|
||||
<span ng-if="folder.fsWatcherEnabled && !folder.paused && folderStatus(folder) !== 'stopped' && model[folder.id].watchError" tooltip data-original-title="{{'Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:' | translate}}<br/>{{model[folder.id].watchError}}">
|
||||
<span class="far fa-clock"></span> {{folder.rescanIntervalS | duration}} 
|
||||
<span class="fas fa-eye-slash"></span> <span translate>Failed to setup, retrying</span>
|
||||
</span>
|
||||
</div>
|
||||
<div ng-if="folder.rescanIntervalS <= 0">
|
||||
<span ng-if="!folder.fsWatcherEnabled" tooltip data-original-title="{{'Disabled periodic scanning and disabled watching for changes' | translate}}">
|
||||
<span class="far fa-clock"></span> <span translate>Disabled</span> 
|
||||
<span class="fas fa-eye-slash"></span> <span translate>Disabled</span>
|
||||
</span>
|
||||
<span ng-if="folder.fsWatcherEnabled && (!model[folder.id].watchError || folder.paused || folderStatus(folder) === 'stopped')" tooltip data-original-title="{{'Disabled periodic scanning and enabled watching for changes' | translate}}">
|
||||
<span class="far fa-clock"></span> <span translate>Disabled</span> 
|
||||
<span class="fas fa-eye"></span> <span translate>Enabled</span>
|
||||
</span>
|
||||
<span ng-if="folder.fsWatcherEnabled && !folder.paused && folderStatus(folder) !== 'stopped' && model[folder.id].watchError" tooltip data-original-title="{{'Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:' | translate}}<br/>{{model[folder.id].watchError}}">
|
||||
<span class="far fa-clock"></span> <span translate>Disabled</span> 
|
||||
<span class="fas fa-eye-slash"></span> <span translate>Failed to setup, retrying</span>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="folder.order != 'random' && folder.type != 'sendonly'">
|
||||
<th><span class="fas fa-fw fa-sort"></span> <span translate>File Pull Order</span></th>
|
||||
<td class="text-right" ng-switch="folder.order">
|
||||
<span ng-switch-when="random" translate>Random</span>
|
||||
<span ng-switch-when="alphabetic" translate>Alphabetic</span>
|
||||
<span ng-switch-when="smallestFirst" translate>Smallest First</span>
|
||||
<span ng-switch-when="largestFirst" translate>Largest First</span>
|
||||
<span ng-switch-when="oldestFirst" translate>Oldest First</span>
|
||||
<span ng-switch-when="newestFirst" translate>Newest First</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="folder.versioning.type">
|
||||
<th><span class="far fa-fw fa-copy"></span> <span translate>File Versioning</span></th>
|
||||
<td class="text-right" ng-switch="folder.versioning.type">
|
||||
<span ng-switch-when="trashcan" translate>Trash Can File Versioning</span>
|
||||
<span ng-switch-when="staggered" translate>Staggered File Versioning</span>
|
||||
<span ng-switch-when="simple" translate>Simple File Versioning</span>
|
||||
<span ng-switch-when="external" translate>External File Versioning</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><span class="fas fa-fw fa-share-alt"></span> <span translate>Shared With</span></th>
|
||||
<td class="text-right" ng-attr-title="{{sharesFolder(folder)}}">{{sharesFolder(folder)}}</td>
|
||||
</tr>
|
||||
<tr ng-if="folderStats[folder.id].lastScan">
|
||||
<th><span class="far fa-fw fa-clock"></span> <span translate>Last Scan</span></th>
|
||||
<td translate ng-if="folderStats[folder.id].lastScanDays >= 365" class="text-right">Never</td>
|
||||
<td ng-if="folderStats[folder.id].lastScanDays < 365" class="text-right">
|
||||
<span>{{folderStats[folder.id].lastScan | date:'yyyy-MM-dd HH:mm:ss'}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="folder.type != 'sendonly' && folder.type != 'receiveencrypted' && folderStats[folder.id].lastFile && folderStats[folder.id].lastFile.filename">
|
||||
<th><span class="fas fa-fw fa-exchange-alt"></span> <span translate>Latest Change</span></th>
|
||||
<td class="text-right">
|
||||
<span tooltip data-original-title="{{folderStats[folder.id].lastFile.filename}} @ {{folderStats[folder.id].lastFile.at | date:'yyyy-MM-dd HH:mm:ss'}}">
|
||||
<span translate ng-if="!folderStats[folder.id].lastFile.deleted">Updated</span>
|
||||
<span translate ng-if="folderStats[folder.id].lastFile.deleted">Deleted</span>
|
||||
{{folderStats[folder.id].lastFile.filename | basename}}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<button type="button" class="btn btn-sm btn-danger pull-left" ng-click="override(folder.id)" ng-if="folderStatus(folder) == 'outofsync' && folder.type == 'sendonly'">
|
||||
<span class="fas fa-arrow-circle-up"></span> <span translate>Override Changes</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-danger pull-left" ng-click="revert(folder.id)" ng-if="hasReceiveOnlyChanged(folder)">
|
||||
<span class="fa fa-arrow-circle-down"></span> <span translate>Revert Local Changes</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-danger pull-left" ng-click="deleteEncryptionModal(folder.id)" ng-if="hasReceiveEncryptedItems(folder)">
|
||||
<span class="fa fa-arrow-lock"></span> <span translate>Delete Unexpected Items</span>
|
||||
</button>
|
||||
<span class="pull-right">
|
||||
<button ng-if="!folder.paused" type="button" class="btn btn-sm btn-default" ng-click="setFolderPause(folder.id, true)">
|
||||
<span class="fas fa-pause"></span> <span translate>Pause</span>
|
||||
</button>
|
||||
<button ng-if="folder.paused" type="button" class="btn btn-sm btn-default" ng-click="setFolderPause(folder.id, false)">
|
||||
<span class="fas fa-play"></span> <span translate>Resume</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-sm" ng-click="restoreVersions.show(folder.id)" ng-if="folder.versioning.type">
|
||||
<span class="fas fa-undo"></span> <span translate>Versions</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="rescanFolder(folder.id)" ng-disabled="['idle', 'stopped', 'unshared', 'outofsync', 'faileditems', 'localadditions'].indexOf(folderStatus(folder)) < 0">
|
||||
<span class="fas fa-refresh"></span> <span translate>Rescan</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="editFolder(folder)">
|
||||
<span class="fas fa-pencil-alt"></span> <span translate>Edit</span>
|
||||
</button>
|
||||
</span>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="pull-right">
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="setAllFoldersPause(true)" ng-if="isAtleastOneFolderPausedStateSetTo(false)">
|
||||
<span class="fas fa-pause"></span> <span translate>Pause All</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="setAllFoldersPause(false)" ng-if="isAtleastOneFolderPausedStateSetTo(true)">
|
||||
<span class="fas fa-play"></span> <span translate>Resume All</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="rescanAllFolders()">
|
||||
<span class="fas fa-refresh"></span> <span translate>Rescan All</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="addFolder()">
|
||||
<span class="fas fa-plus"></span> <span translate>Add Folder</span>
|
||||
</button>
|
||||
</span>
|
||||
<div class="clearfix"></div>
|
||||
<hr class="visible-sm"/>
|
||||
</div>
|
||||
|
||||
<!-- Device list (top right) -->
|
||||
|
||||
<!-- This device -->
|
||||
|
||||
<div class="col-md-6" aria-label="{{'Devices' | translate}}" role="region">
|
||||
<h3 translate>This Device</h3>
|
||||
<div class="panel panel-default" ng-repeat="deviceCfg in [thisDevice()]">
|
||||
<button class="btn panel-heading" data-toggle="collapse" data-target="#device-this" aria-expanded="true">
|
||||
<h4 class="panel-title">
|
||||
<identicon class="panel-icon" data-value="deviceCfg.deviceID"></identicon>
|
||||
<div class="panel-title-text">{{deviceName(deviceCfg)}}</div>
|
||||
</h4>
|
||||
</button>
|
||||
<div id="device-this" class="panel-collapse collapse in">
|
||||
<div class="panel-body">
|
||||
<table class="table table-condensed table-striped table-auto">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th><span class="fas fa-fw fa-cloud-download-alt"></span> <span translate>Download Rate</span></th>
|
||||
<td class="text-right">
|
||||
<a href="#" class="toggler" ng-click="toggleUnits()">
|
||||
<span ng-if="!metricRates">{{connectionsTotal.inbps | binary}}B/s</span>
|
||||
<span ng-if="metricRates">{{connectionsTotal.inbps*8 | metric}}bps</span>
|
||||
({{connectionsTotal.inBytesTotal | binary}}B)
|
||||
<small ng-if="config.options.maxRecvKbps > 0"><br/>
|
||||
<i class="text-muted"><span translate>Limit</span>:
|
||||
<span ng-if="!metricRates">{{config.options.maxRecvKbps*1024 | binary}}B/s</span>
|
||||
<span ng-if="metricRates">{{config.options.maxRecvKbps*1024*8 | metric}}bps</span>
|
||||
</i>
|
||||
</small>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><span class="fas fa-fw fa-cloud-upload-alt"></span> <span translate>Upload Rate</span></th>
|
||||
<td class="text-right">
|
||||
<a href="#" class="toggler" ng-click="toggleUnits()">
|
||||
<span ng-if="!metricRates">{{connectionsTotal.outbps | binary}}B/s</span>
|
||||
<span ng-if="metricRates">{{connectionsTotal.outbps*8 | metric}}bps</span>
|
||||
({{connectionsTotal.outBytesTotal | binary}}B)
|
||||
<small ng-if="config.options.maxSendKbps > 0"><br/>
|
||||
<i class="text-muted"><span translate>Limit</span>:
|
||||
<span ng-if="!metricRates">{{config.options.maxSendKbps*1024 | binary}}B/s</span>
|
||||
<span ng-if="metricRates">{{config.options.maxSendKbps*1024*8 | metric}}bps</span>
|
||||
</i>
|
||||
</small>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><span class="fas fa-fw fa-home"></span> <span translate>Local State (Total)</span></th>
|
||||
<td class="text-right">
|
||||
<span tooltip data-original-title="{{localStateTotal.files | alwaysNumber | localeNumber}} {{'files' | translate}}, {{ localStateTotal.directories | alwaysNumber | localeNumber}} {{'directories' | translate}}, ~{{ localStateTotal.bytes | binary}}B">
|
||||
<span class="far fa-copy"></span> {{localStateTotal.files | alwaysNumber | localeNumber}} 
|
||||
<span class="far fa-folder"></span> {{localStateTotal.directories| alwaysNumber | localeNumber}} 
|
||||
<span class="far fa-hdd"></span> ~{{localStateTotal.bytes | binary}}B
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><span class="fas fa-fw fa-sitemap"></span> <span translate>Listeners</span></th>
|
||||
<td class="text-right">
|
||||
<span ng-if="listenersFailed.length == 0" class="data text-success">
|
||||
<span>{{listenersTotal}}/{{listenersTotal}}</span>
|
||||
</span>
|
||||
<span ng-if="listenersFailed.length != 0" class="data" ng-class="{'text-danger': listenersFailed.length == listenersTotal}">
|
||||
<span popover data-trigger="hover" data-placement="bottom" data-html="true" data-content="{{listenersFailed.join('<br>\n')}}">
|
||||
{{listenersTotal-listenersFailed.length}}/{{listenersTotal}}
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="system.discoveryEnabled">
|
||||
<th><span class="fas fa-fw fa-map-signs"></span> <span translate>Discovery</span></th>
|
||||
<td class="text-right">
|
||||
<span ng-if="discoveryFailed.length == 0" class="data text-success">
|
||||
<span>{{discoveryTotal}}/{{discoveryTotal}}</span>
|
||||
</span>
|
||||
<span ng-if="discoveryFailed.length != 0" class="data" ng-class="{'text-danger': discoveryFailed.length == discoveryTotal}">
|
||||
<span popover data-trigger="hover" data-placement="bottom" data-content="{{'Click to see discovery failures' | translate}}.">
|
||||
<a href="" style="color:inherit" ng-click="showDiscoveryFailures()">{{discoveryTotal-discoveryFailed.length}}/{{discoveryTotal}}</a>
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><span class="far fa-fw fa-clock"></span> <span translate>Uptime</span></th>
|
||||
<td class="text-right">{{system.uptime | duration:"m"}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><span class="fas fa-fw fa-tag"></span> <span translate>Version</span></th>
|
||||
<td class="text-right">
|
||||
<span tooltip data-original-title="{{versionString()}}">{{versionString()}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Remote devices -->
|
||||
<h3 translate>Remote Devices</h3>
|
||||
<div class="panel-group" id="devices">
|
||||
<div class="panel panel-default" ng-repeat="deviceCfg in otherDevices()">
|
||||
<button class="btn panel-heading" data-toggle="collapse" data-parent="#devices" data-target="#device-{{$index}}" aria-expanded="false">
|
||||
<div class="panel-progress" ng-show="deviceStatus(deviceCfg) == 'syncing'" ng-attr-style="width: {{completion[deviceCfg.deviceID]._total | percent}}"></div>
|
||||
<h4 class="panel-title">
|
||||
<identicon class="panel-icon" data-value="deviceCfg.deviceID"></identicon>
|
||||
<span ng-switch="deviceStatus(deviceCfg)" class="pull-right text-{{deviceClass(deviceCfg)}}">
|
||||
<span ng-switch-when="insync"><span class="hidden-xs" translate>Up to Date</span><span class="visible-xs" aria-label="{{'Up to Date' | translate}}"><i class="fas fa-fw fa-check"></i></span></span>
|
||||
<span ng-switch-when="unused-insync"><span class="hidden-xs" translate>Connected (Unused)</span><span class="visible-xs" aria-label="{{'Connected (Unused)' | translate}}"><i class="fas fa-fw fa-unlink"></i></span></span>
|
||||
<span ng-switch-when="syncing">
|
||||
<span class="hidden-xs" translate>Syncing</span> ({{completion[deviceCfg.deviceID]._total | percent}}, {{completion[deviceCfg.deviceID]._needBytes | binary}}B)
|
||||
</span>
|
||||
<span ng-switch-when="paused"><span class="hidden-xs" translate>Paused</span><span class="visible-xs" aria-label="{{'Paused' | translate}}"><i class="fas fa-fw fa-pause"></i></span></span>
|
||||
<span ng-switch-when="unused-paused"><span class="hidden-xs" translate>Paused (Unused)</span><span class="visible-xs" aria-label="{{'Paused (Unused)' | translate}}"><i class="fas fa-fw fa-unlink"></i></span></span>
|
||||
<span ng-switch-when="disconnected"><span class="hidden-xs" translate>Disconnected</span><span class="visible-xs" aria-label="{{'Disconnected' | translate}}"><i class="fas fa-fw fa-power-off"></i></span></span>
|
||||
<span ng-switch-when="unused-disconnected"><span class="hidden-xs" translate>Disconnected (Unused)</span><span class="visible-xs" aria-label="{{'Disconnected (Unused)' | translate}}"><i class="fas fa-fw fa-unlink"></i></span></span>
|
||||
</span>
|
||||
<span>{{deviceName(deviceCfg)}}</span>
|
||||
</h4>
|
||||
</button>
|
||||
<div id="device-{{$index}}" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
<table class="table table-condensed table-striped table-auto">
|
||||
<tbody>
|
||||
<tr ng-if="connections[deviceCfg.deviceID].connected">
|
||||
<th><span class="fas fa-fw fa-cloud-download-alt"></span> <span translate>Download Rate</span></th>
|
||||
<td class="text-right">
|
||||
<a href="#" class="toggler" ng-click="toggleUnits()">
|
||||
<span ng-if="!metricRates">{{connections[deviceCfg.deviceID].inbps | binary}}B/s</span>
|
||||
<span ng-if="metricRates">{{connections[deviceCfg.deviceID].inbps*8 | metric}}bps</span>
|
||||
({{connections[deviceCfg.deviceID].inBytesTotal | binary}}B)
|
||||
<small ng-if="deviceCfg.maxRecvKbps > 0"><br/>
|
||||
<i class="text-muted"><span translate>Limit</span>:
|
||||
<span ng-if="!metricRates">{{deviceCfg.maxRecvKbps*1024 | binary}}B/s</span>
|
||||
<span ng-if="metricRates">{{deviceCfg.maxRecvKbps*1024*8 | metric}}bps</span>
|
||||
</i>
|
||||
</small>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="connections[deviceCfg.deviceID].connected">
|
||||
<th><span class="fas fa-fw fa-cloud-upload-alt"></span> <span translate>Upload Rate</span></th>
|
||||
<td class="text-right">
|
||||
<a href="#" class="toggler" ng-click="toggleUnits()">
|
||||
<span ng-if="!metricRates">{{connections[deviceCfg.deviceID].outbps | binary}}B/s</span>
|
||||
<span ng-if="metricRates">{{connections[deviceCfg.deviceID].outbps*8 | metric}}bps</span>
|
||||
({{connections[deviceCfg.deviceID].outBytesTotal | binary}}B)
|
||||
<small ng-if="deviceCfg.maxSendKbps > 0"><br/>
|
||||
<i class="text-muted"><span translate>Limit</span>:
|
||||
<span ng-if="!metricRates">{{deviceCfg.maxSendKbps*1024 | binary}}B/s</span>
|
||||
<span ng-if="metricRates">{{deviceCfg.maxSendKbps*1024*8 | metric}}bps</span>
|
||||
</i>
|
||||
</small>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="deviceStatus(deviceCfg) == 'syncing'">
|
||||
<th><span class="fas fa-fw fa-exchange-alt"></span> <span translate>Out of Sync Items</span></th>
|
||||
<td class="text-right">
|
||||
<a href="" ng-click="showRemoteNeed(deviceCfg)">{{completion[deviceCfg.deviceID]._needItems | alwaysNumber | localeNumber}} <span translate>items</span>, ~{{completion[deviceCfg.deviceID]._needBytes | binary}}B</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><span class="fas fa-fw fa-link"></span> <span translate>Address</span></th>
|
||||
<td ng-if="connections[deviceCfg.deviceID].connected" class="text-right">
|
||||
<span tooltip data-original-title="{{ connections[deviceCfg.deviceID].type.indexOf('Relay') > -1 ? '' : connections[deviceCfg.deviceID].type }} {{ connections[deviceCfg.deviceID].crypto }}">
|
||||
{{deviceAddr(deviceCfg)}}
|
||||
</span>
|
||||
</td>
|
||||
<td ng-if="!connections[deviceCfg.deviceID].connected" class="text-right">
|
||||
<span ng-repeat="addr in deviceCfg.addresses">
|
||||
<span tooltip data-original-title="{{'Configured' | translate}}">{{addr}}</span><br>
|
||||
<small ng-if="system.lastDialStatus[addr].error" tooltip data-original-title="{{system.lastDialStatus[addr].error}}" class="text-danger">{{abbreviatedError(addr)}}<br></small>
|
||||
</span>
|
||||
<span ng-repeat="addr in discoveryCache[deviceCfg.deviceID].addresses">
|
||||
<span tooltip data-original-title="{{'Discovered' | translate}}">{{addr}}</span><br>
|
||||
<small ng-if="system.lastDialStatus[addr].error" tooltip data-original-title="{{system.lastDialStatus[addr].error}}" class="text-danger">{{abbreviatedError(addr)}}<br></small>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="connections[deviceCfg.deviceID].connected && connections[deviceCfg.deviceID].type.indexOf('Relay') > -1" tooltip data-original-title="Connections via relays might be rate limited by the relay">
|
||||
<th><span class="fas fa-fw fa-exclamation-triangle text-danger"></span> <span translate>Connection Type</span></th>
|
||||
<td class="text-right">{{connections[deviceCfg.deviceID].type}}</td>
|
||||
</tr>
|
||||
<tr ng-if="deviceCfg.allowedNetworks.length > 0">
|
||||
<th><span class="fas fa-fw fa-filter"></span> <span translate>Allowed Networks</span></th>
|
||||
<td class="text-right">
|
||||
<span>{{deviceCfg.allowedNetworks.join(", ")}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="deviceCfg.compression != 'metadata'">
|
||||
<th><span class="fas fa-fw fa-compress"></span> <span translate>Compression</span></th>
|
||||
<td class="text-right">
|
||||
<span ng-if="deviceCfg.compression == 'always'" translate>All Data</span>
|
||||
<span ng-if="deviceCfg.compression == 'never'" translate>Off</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="deviceCfg.introducer">
|
||||
<th><span class="far fa-fw fa-thumbs-up"></span> <span translate>Introducer</span></th>
|
||||
<td translate class="text-right">Yes</td>
|
||||
</tr>
|
||||
<tr ng-if="deviceCfg.introducedBy">
|
||||
<th><span class="far fa-fw fa-handshake-o"></span> <span translate>Introduced By</span></th>
|
||||
<td class="text-right">{{ deviceName(devices[deviceCfg.introducedBy]) || deviceCfg.introducedBy.substring(0, 5) }}</td>
|
||||
</tr>
|
||||
<tr ng-if="connections[deviceCfg.deviceID].clientVersion">
|
||||
<th><span class="fas fa-fw fa-tag"></span> <span translate>Version</span></th>
|
||||
<td class="text-right">{{connections[deviceCfg.deviceID].clientVersion}}</td>
|
||||
</tr>
|
||||
<tr ng-if="!connections[deviceCfg.deviceID].connected">
|
||||
<th><span class="fas fa-fw fa-eye"></span> <span translate>Last seen</span></th>
|
||||
<td translate ng-if="!deviceStats[deviceCfg.deviceID].lastSeenDays || deviceStats[deviceCfg.deviceID].lastSeenDays >= 365" class="text-right">Never</td>
|
||||
<td ng-if="deviceStats[deviceCfg.deviceID].lastSeenDays < 365" class="text-right">{{deviceStats[deviceCfg.deviceID].lastSeen | date:"yyyy-MM-dd HH:mm:ss"}}</td>
|
||||
</tr>
|
||||
<tr ng-if="deviceFolders(deviceCfg).length > 0">
|
||||
<th><span class="fas fa-fw fa-folder"></span> <span translate>Folders</span></th>
|
||||
<td class="text-right" ng-attr-title="{{deviceFolders(deviceCfg).map(folderLabel).join(', ')}}">{{deviceFolders(deviceCfg).map(folderLabel).join(", ")}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<span class="pull-right">
|
||||
<button ng-if="!deviceCfg.paused" type="button" class="btn btn-sm btn-default" ng-click="setDevicePause(deviceCfg.deviceID, true)">
|
||||
<span class="fas fa-pause"></span> <span translate>Pause</span>
|
||||
</button>
|
||||
<button ng-if="deviceCfg.paused" type="button" class="btn btn-sm btn-default" ng-click="setDevicePause(deviceCfg.deviceID, false)">
|
||||
<span class="fas fa-play"></span> <span translate>Resume</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="editDevice(deviceCfg)">
|
||||
<span class="fas fa-pencil-alt"></span> <span translate>Edit</span>
|
||||
</button>
|
||||
</span>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span class="pull-right">
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="setAllDevicesPause(true)" ng-if="isAtleastOneDevicePausedStateSetTo(false)">
|
||||
<span class="fas fa-pause"></span> <span translate>Pause All</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="setAllDevicesPause(false)" ng-if="isAtleastOneDevicePausedStateSetTo(true)">
|
||||
<span class="fas fa-play"></span> <span translate>Resume All</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="globalChanges()">
|
||||
<span class="fas fa-fw fa-info-circle"></span> <span translate>Recent Changes</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="addDevice()">
|
||||
<span class="fas fa-plus"></span> <span translate>Add Remote Device</span>
|
||||
</button>
|
||||
</span>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row -->
|
||||
|
||||
</div> <!-- /container -->
|
||||
</div> <!-- /ng-cloak -->
|
||||
|
||||
<!-- Bottom bar -->
|
||||
|
||||
<nav class="navbar navbar-default navbar-fixed-bottom">
|
||||
<div class="container">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a class="navbar-link" href="https://syncthing.net/" target="_blank"><span class="fas fa-home"></span> <span translate>Home page</span></a></li>
|
||||
<li><a class="navbar-link" href="https://docs.syncthing.net/" target="_blank"><span class="fas fa-book"></span> <span translate>Documentation</span></a></li>
|
||||
<li><a class="navbar-link" href="https://forum.syncthing.net" target="_blank"><span class="fas fa-question-circle"></span> <span translate>Support</span></a></li>
|
||||
<li><a class="navbar-link" href="https://data.syncthing.net/" target="_blank"><span class="fas fa-bar-chart"></span> <span translate>Statistics</span></a></li>
|
||||
<li><a class="navbar-link" href="https://github.com/syncthing/syncthing/releases" target="_blank"><span class="far fa-file-alt"></span> <span translate>Changelog</span></a></li>
|
||||
<li><a class="navbar-link" href="https://github.com/syncthing/syncthing/issues" target="_blank"><span class="fas fa-bug"></span> <span translate>Bugs</span></a></li>
|
||||
<li><a class="navbar-link" href="https://github.com/syncthing/syncthing" target="_blank"><span class="fas fa-wrench"></span> <span translate>Source Code</span></a></li>
|
||||
<li><a class="navbar-link" href="https://twitter.com/syncthing" target="_blank"><span class="fab fa-twitter"></span> Twitter</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<ng-include src="'syncthing/core/networkErrorDialogView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/core/httpErrorDialogView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/core/restartingDialogView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/core/upgradingDialogView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/core/shutdownDialogView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/device/idqrModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/device/editDeviceModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/device/globalChangesModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/folder/editFolderModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/folder/restoreVersionsModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/folder/restoreVersionsConfirmation.html'"></ng-include>
|
||||
<ng-include src="'syncthing/settings/settingsModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/settings/advancedSettingsModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/settings/discardChangesConfirmation.html'"></ng-include>
|
||||
<ng-include src="'syncthing/usagereport/usageReportModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/usagereport/usageReportPreviewModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/transfer/neededFilesModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/transfer/failedFilesModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/transfer/remoteNeededFilesModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/transfer/localChangedFilesModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/core/upgradeModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/core/majorUpgradeModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/core/aboutModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/core/discoveryFailuresModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/folder/removeFolderDialogView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/folder/deleteEncryptionFolderDialogView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/device/removeDeviceDialogView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/core/logViewerModalView.html'"></ng-include>
|
||||
|
||||
<!-- vendor scripts -->
|
||||
<script type="text/javascript" src="vendor/jquery/jquery-2.2.2.js"></script>
|
||||
<script type="text/javascript" src="vendor/angular/angular.js"></script>
|
||||
<script type="text/javascript" src="vendor/angular/angular-sanitize.js"></script>
|
||||
<script type="text/javascript" src="vendor/angular/angular-translate.js"></script>
|
||||
<script type="text/javascript" src="vendor/angular/angular-translate-loader-static-files.js"></script>
|
||||
<script type="text/javascript" src="vendor/angular/angular-dirPagination.js"></script>
|
||||
<script type="text/javascript" src="vendor/moment/moment.js"></script>
|
||||
<script type="text/javascript" src="vendor/bootstrap/js/bootstrap.js"></script>
|
||||
<script type="text/javascript" src="vendor/daterangepicker/daterangepicker.js"></script>
|
||||
<script type="text/javascript" src="vendor/fancytree/jquery.fancytree-all-deps.js"></script>
|
||||
<!-- / vendor scripts -->
|
||||
|
||||
<!-- gui application code -->
|
||||
<script type="text/javascript" src="syncthing/core/module.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/alwaysNumberFilter.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/basenameFilter.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/binaryFilter.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/localeNumberFilter.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/percentFilter.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/durationFilter.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/eventService.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/identiconDirective.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/languageSelectDirective.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/lastErrorComponentFilter.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/localeService.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/modalDirective.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/metricFilter.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/notificationDirective.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/pathIsSubDirDirective.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/popoverDirective.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/selectOnClickDirective.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/syncthingController.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/tooltipDirective.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/uncamelFilter.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/uniqueFolderDirective.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/validDeviceidDirective.js"></script>
|
||||
<script type="text/javascript" src="assets/lang/valid-langs.js"></script>
|
||||
<script type="text/javascript" src="assets/lang/prettyprint.js"></script>
|
||||
<script type="text/javascript" src="meta.js"></script>
|
||||
<script type="text/javascript" src="syncthing/app.js"></script>
|
||||
<!-- / gui application code -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
35
gui/default/untrusted/syncthing/core/editShareTemplate.html
Normal file
35
gui/default/untrusted/syncthing/core/editShareTemplate.html
Normal file
@@ -0,0 +1,35 @@
|
||||
<div class="col-md-6 checkbox">
|
||||
<label for="sharedwith-{{id}}">
|
||||
<input id="sharedwith-{{id}}" ng-model="selected[id]" type="checkbox" />
|
||||
<span tooltip data-original-title="{{id}}">{{label}}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" ng-switch="folderType !== 'receiveencrypted' && !encryptionPasswords[id]">
|
||||
<span ng-switch-when='true' class="fas fa-fw fa-unlock" />
|
||||
<span ng-switch-default class="fas fa-fw fa-lock" />
|
||||
</span>
|
||||
<span ng-switch="folderType === 'receiveencrypted'">
|
||||
<span ng-switch-when='true'>
|
||||
<input class="form-control input-sm" type="password" placeholder="{{'Received data is already encrypted' | translate}}" disabled />
|
||||
</span>
|
||||
<span ng-switch-default ng-switch="selected[id]">
|
||||
<span ng-switch-when='true' ng-class="{'has-error': untrusted && !encryptionPasswords[id]}">
|
||||
<input class="form-control input-sm" type="{{plain ? 'text' : 'password'}}" ng-model="encryptionPasswords[id]" ng-required="untrusted" placeholder="{{'If untrusted, enter encryption password' | translate}}" />
|
||||
</span>
|
||||
<span ng-switch-default>
|
||||
<input class="form-control input-sm" type="password" placeholder="{{'Not shared' | translate}}" disabled />
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<span ng-switch="selected[id] && folderType !== 'receiveencrypted'" class="input-group-addon">
|
||||
<span ng-switch-when='true'>
|
||||
<span class="button fas fa-fw fa-eye" ng-click="togglePasswordVisibility()" />
|
||||
</span>
|
||||
<span ng-switch-default>
|
||||
<span class="button fas fa-fw fa-eye" disabled />
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
2586
gui/default/untrusted/syncthing/core/syncthingController.js
Executable file
2586
gui/default/untrusted/syncthing/core/syncthingController.js
Executable file
File diff suppressed because it is too large
Load Diff
166
gui/default/untrusted/syncthing/device/editDeviceModalView.html
Normal file
166
gui/default/untrusted/syncthing/device/editDeviceModalView.html
Normal file
@@ -0,0 +1,166 @@
|
||||
<modal id="editDevice" status="default" icon="{{editingExisting ? 'fas fa-pencil-alt' : 'fas fa-desktop'}}" heading="{{editingExisting ? 'Edit Device' : 'Add Device' | translate}} {{currentDevice.name}}" large="yes" closeable="yes">
|
||||
<div class="modal-body">
|
||||
<form role="form" name="deviceEditor">
|
||||
<ul class="nav nav-tabs" ng-init="loadFormIntoScope(deviceEditor)">
|
||||
<li class="active"><a data-toggle="tab" href="#device-general"><span class="fas fa-cog"></span> <span translate>General</span></a></li>
|
||||
<li><a data-toggle="tab" href="#device-sharing"><span class="fas fa-share-alt"></span> <span translate>Sharing</span></a></li>
|
||||
<li><a data-toggle="tab" href="#device-advanced"><span class="fas fa-cogs"></span> <span translate>Advanced</span></a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div id="device-general" class="tab-pane in active">
|
||||
<div class="form-group" ng-class="{'has-error': deviceEditor.deviceID.$invalid && deviceEditor.deviceID.$dirty}" ng-init="loadFormIntoScope(deviceEditor)">
|
||||
<label translate for="deviceID">Device ID</label>
|
||||
<div ng-if="!editingExisting">
|
||||
<input name="deviceID" id="deviceID" class="form-control text-monospace" type="text" ng-model="currentDevice.deviceID" required="" valid-deviceid list="discovery-list" aria-required="true" />
|
||||
<datalist id="discovery-list">
|
||||
<option ng-repeat="id in discovery" value="{{id}}" />
|
||||
</datalist>
|
||||
<p class="help-block" ng-if="discovery && discovery.length !== 0">
|
||||
<span translate>You can also select one of these nearby devices:</span>
|
||||
<ul>
|
||||
<li ng-repeat="id in discovery"><a href="#" ng-click="currentDevice.deviceID = id">{{id}}</a></li>
|
||||
</ul>
|
||||
</p>
|
||||
<p class="help-block">
|
||||
<span translate ng-if="deviceEditor.deviceID.$valid || deviceEditor.deviceID.$pristine">The device ID to enter here can be found in the "Actions > Show ID" dialog on the other device. Spaces and dashes are optional (ignored).</span>
|
||||
<span translate ng-show="deviceEditor.deviceID.$valid || deviceEditor.deviceID.$pristine">When adding a new device, keep in mind that this device must be added on the other side too.</span>
|
||||
<span translate ng-if="deviceEditor.deviceID.$error.required && deviceEditor.deviceID.$dirty">The device ID cannot be blank.</span>
|
||||
<span translate ng-if="deviceEditor.deviceID.$error.validDeviceid && deviceEditor.deviceID.$dirty">The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.</span>
|
||||
<span translate ng-if="deviceEditor.deviceID.$error.unique && deviceEditor.deviceID.$dirty">A device with that ID is already added.</span>
|
||||
</p>
|
||||
</div>
|
||||
<div ng-if="editingExisting" class="well well-sm text-monospace" select-on-click>{{currentDevice.deviceID}}</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label translate for="name">Device Name</label>
|
||||
<input id="name" class="form-control" type="text" ng-model="currentDevice.name" />
|
||||
<p translate ng-if="currentDevice.deviceID == myID" class="help-block">Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.</p>
|
||||
<p translate ng-if="currentDevice.deviceID != myID" class="help-block">Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div id="device-sharing" class="tab-pane">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="currentDevice.introducer">
|
||||
<span translate>Introducer</span>
|
||||
<p translate class="help-block">Add devices from the introducer to our device list, for mutually shared folders.</p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="currentDevice.autoAcceptFolders">
|
||||
<span translate>Auto Accept</span>
|
||||
<p translate class="help-block">Automatically create or share folders that this device advertises at the default path.</p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-horizontal" ng-if="currentSharing.shared.length">
|
||||
<label translate for="folders">Shared Folders</label>
|
||||
<p class="help-block">
|
||||
<span translate>Select the folders to share with this device.</span> 
|
||||
<small><a href="#" ng-click="selectAllSharedFolders(true)" translate>Select All</a> 
|
||||
<a href="#" ng-click="selectAllSharedFolders(false)" translate>Deselect All</a></small>
|
||||
</p>
|
||||
<div class="form-group" ng-repeat="folder in currentSharing.shared">
|
||||
<share-template selected="currentSharing.selected" encryption-passwords="currentSharing.encryptionPasswords" id="{{folder.id}}" label="{{folderLabel(folder.id)}}" folder-type="{{folder.type}}" untrusted="{{device.untrusted}}" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-horizontal" ng-if="currentSharing.unrelated.length">
|
||||
<label translate>Unshared Folders</label>
|
||||
<p class="help-block">
|
||||
<span translate>Select additional folders to share with this device.</span> 
|
||||
<small><a href="#" ng-click="selectAllUnrelatedFolders(true)" translate>Select All</a> 
|
||||
<a href="#" ng-click="selectAllUnrelatedFolders(false)" translate>Deselect All</a></small>
|
||||
</p>
|
||||
<div class="form-group" ng-repeat="folder in currentSharing.unrelated">
|
||||
<share-template selected="currentSharing.selected" encryption-passwords="currentSharing.encryptionPasswords" id="{{folder.id}}" label="{{folderLabel(folder.id)}}" folder-type="{{folder.type}}" untrusted="{{device.untrusted}}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="device-advanced" class="tab-pane">
|
||||
<div class="row form-group">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label translate for="addresses">Addresses</label>
|
||||
<input ng-disabled="currentDevice.deviceID == myID" id="addresses" class="form-control" type="text" ng-model="currentDevice._addressesStr"></input>
|
||||
<p translate class="help-block">Enter comma separated ("tcp://ip:port", "tcp://host:port") addresses or "dynamic" to perform automatic discovery of the address.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label translate>Compression</label>
|
||||
<select class="form-control" ng-model="currentDevice.compression">
|
||||
<option value="always" translate>All Data</option>
|
||||
<option value="metadata" translate>Metadata Only</option>
|
||||
<option value="never" translate>Off</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<div class="col-md-12">
|
||||
<label translate>Device rate limits</label>
|
||||
<div class="row">
|
||||
<div class="col-md-6" ng-class="{'has-error': deviceEditor.maxRecvKbps.$invalid && deviceEditor.maxRecvKbps.$dirty}">
|
||||
<div class="row">
|
||||
<span class="col-md-8" translate>Incoming Rate Limit (KiB/s)</span>
|
||||
<div class="col-md-4">
|
||||
<input name="maxRecvKbps" id="maxRecvKbps" class="form-control" type="number" pattern="\d+" ng-model="currentDevice.maxRecvKbps" min="0" />
|
||||
</div>
|
||||
</div>
|
||||
<p class="help-block" ng-if="!deviceEditor.maxRecvKbps.$valid && deviceEditor.maxRecvKbps.$dirty" translate>The rate limit must be a non-negative number (0: no limit)</p>
|
||||
</div>
|
||||
<div class="col-md-6" ng-class="{'has-error': deviceEditor.maxSendKbps.$invalid && deviceEditor.maxSendKbps.$dirty}">
|
||||
<div class="row">
|
||||
<span class="col-md-8" translate>Outgoing Rate Limit (KiB/s)</span>
|
||||
<div class="col-md-4">
|
||||
<input name="maxSendKbps" id="maxSendKbps" class="form-control" type="number" pattern="\d+" ng-model="currentDevice.maxSendKbps" min="0" />
|
||||
</div>
|
||||
</div>
|
||||
<p class="help-block" ng-if="!deviceEditor.maxSendKbps.$valid && deviceEditor.maxSendKbps.$dirty" translate>The rate limit must be a non-negative number (0: no limit)</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="form-group col-md-6">
|
||||
<input type="checkbox" id="untrusted" ng-model="currentDevice.untrusted" />
|
||||
<label for="untrusted" translate>Untrusted</label>
|
||||
<p translate class="help-block">All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary btn-sm" ng-click="saveDevice()" ng-disabled="deviceEditor.$invalid">
|
||||
<span class="fas fa-check"></span> <span translate>Save</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-sm" data-toggle="modal" data-target="#idqr" ng-if="editingExisting || deviceEditor.deviceID.$valid">
|
||||
<span class="fas fa-qrcode"></span> <span translate>Show QR</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal">
|
||||
<span class="fas fa-times"></span> <span translate>Close</span>
|
||||
</button>
|
||||
<div ng-if="editingExisting" class="pull-left">
|
||||
<button type="button" class="btn btn-warning btn-sm disabled" ng-if="willBeReintroducedBy" tooltip data-original-title="This device will be reintroduced by {{ willBeReintroducedBy }}">
|
||||
<span class="fas fa-minus-circle"></span> <span translate>Remove</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-warning btn-sm" data-toggle="modal" data-target="#remove-device-confirmation" ng-if="!willBeReintroducedBy">
|
||||
<span class="fas fa-minus-circle"></span> <span translate>Remove</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</modal>
|
||||
@@ -0,0 +1,19 @@
|
||||
<modal id="delete-encryption-confirmation" status="danger" icon="fas fa-question-circle" heading="{{'Delete Unexpected Items' | translate}}" large="no" closeable="yes">
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
<span translate>Unexpected items have been found in this folder.</span></br>
|
||||
<span translate translate-value-receive-encrypted="{{'Receive Encrypted' | translate}}">You should never add or change anything locally in a "{%receiveEncrypted%}" folder.</span>
|
||||
</p>
|
||||
<p translate>
|
||||
Are you sure you want to permanently delete all these files?
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-danger pull-left btn-sm" data-dismiss="modal" ng-click="revert(revertEncryptionFolder)">
|
||||
<span class="fas fa-check"></span> <span translate>Yes</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal">
|
||||
<span class="fas fa-times"></span> <span translate>No</span>
|
||||
</button>
|
||||
</div>
|
||||
</modal>
|
||||
278
gui/default/untrusted/syncthing/folder/editFolderModalView.html
Normal file
278
gui/default/untrusted/syncthing/folder/editFolderModalView.html
Normal file
@@ -0,0 +1,278 @@
|
||||
<modal id="editFolder" status="default" icon="{{editingExisting ? 'fas fa-pencil-alt' : 'fas fa-folder'}}" heading="{{editingExisting ? 'Edit Folder' : 'Add Folder' | translate}} ({{folderLabel(currentFolder.id)}})" large="yes" closeable="yes">
|
||||
<div class="modal-body">
|
||||
<form role="form" name="folderEditor">
|
||||
<ul class="nav nav-tabs" ng-init="loadFormIntoScope(folderEditor)">
|
||||
<li class="active"><a data-toggle="tab" href="#folder-general"><span class="fas fa-cog"></span> <span translate>General</span></a></li>
|
||||
<li><a data-toggle="tab" href="#folder-sharing"><span class="fas fa-share-alt"></span> <span translate>Sharing</span></a></li>
|
||||
<li><a data-toggle="tab" href="#folder-versioning"><span class="fas fa-copy"></span> <span translate>File Versioning</span></a></li>
|
||||
<li><a data-toggle="tab" href="#folder-ignores"><span class="fas fa-filter"></span> <span translate>Ignore Patterns</span></a></li>
|
||||
<li><a data-toggle="tab" href="#folder-advanced"><span class="fas fa-cogs"></span> <span translate>Advanced</span></a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
|
||||
<div id="folder-general" class="tab-pane in active">
|
||||
<div class="form-group" ng-class="{'has-error': folderEditor.folderLabel.$invalid && folderEditor.folderLabel.$dirty}">
|
||||
<label for="folderLabel"><span translate>Folder Label</span></label>
|
||||
<input name="folderLabel" id="folderLabel" class="form-control" type="text" ng-model="currentFolder.label" value="{{currentFolder.label}}" />
|
||||
<p class="help-block">
|
||||
<span translate ng-if="folderEditor.folderLabel.$valid || folderEditor.folderLabel.$pristine">Optional descriptive label for the folder. Can be different on each device.</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="form-group" ng-class="{'has-error': folderEditor.folderID.$invalid && folderEditor.folderID.$dirty}">
|
||||
<label for="folderID"><span translate>Folder ID</span></label>
|
||||
<input name="folderID" ng-readonly="editingExisting || (!editingExisting && currentFolder.viewFlags.importFromOtherDevice)" id="folderID" class="form-control" type="text" ng-model="currentFolder.id" required="" aria-required="true" unique-folder value="{{currentFolder.id}}" />
|
||||
<p class="help-block">
|
||||
<span translate ng-if="folderEditor.folderID.$valid || folderEditor.folderID.$pristine">Required identifier for the folder. Must be the same on all cluster devices.</span>
|
||||
<span translate ng-if="folderEditor.folderID.$error.uniqueFolder">The folder ID must be unique.</span>
|
||||
<span translate ng-if="folderEditor.folderID.$error.required && folderEditor.folderID.$dirty">The folder ID cannot be blank.</span>
|
||||
<span translate ng-show="!editingExisting">When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="form-group" ng-class="{'has-error': folderEditor.folderPath.$invalid && folderEditor.folderPath.$dirty}">
|
||||
<label translate for="folderPath">Folder Path</label>
|
||||
<input name="folderPath" ng-readonly="editingExisting" id="folderPath" class="form-control" type="text" ng-model="currentFolder.path" list="directory-list" required="" aria-required="true" path-is-sub-dir />
|
||||
<datalist id="directory-list">
|
||||
<option ng-repeat="directory in directoryList" value="{{ directory }}" />
|
||||
</datalist>
|
||||
<p class="help-block">
|
||||
<span ng-if="folderEditor.folderPath.$valid || folderEditor.folderPath.$pristine"><span translate>Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for</span> <code>{{system.tilde}}</code>.</br></span>
|
||||
<span translate ng-if="folderEditor.folderPath.$error.required && folderEditor.folderPath.$dirty">The folder path cannot be blank.</span>
|
||||
<span class="text-danger" translate translate-value-other-folder="{{folderPathErrors.otherID}}" ng-if="folderPathErrors.isSub && folderPathErrors.otherLabel.length == 0">Warning, this path is a subdirectory of an existing folder "{%otherFolder%}".</span>
|
||||
<span class="text-danger" translate translate-value-other-folder="{{folderPathErrors.otherID}}" translate-value-other-folder-label="{{folderPathErrors.otherLabel}}" ng-if="folderPathErrors.isSub && folderPathErrors.otherLabel.length != 0">Warning, this path is a subdirectory of an existing folder "{%otherFolderLabel%}" ({%otherFolder%}).</span>
|
||||
<span class="text-danger" translate translate-value-other-folder="{{folderPathErrors.otherID}}" ng-if="folderPathErrors.isParent && folderPathErrors.otherLabel.length == 0">Warning, this path is a parent directory of an existing folder "{%otherFolder%}".</span>
|
||||
<span class="text-danger" translate translate-value-other-folder="{{folderPathErrors.otherID}}" translate-value-other-folder-label="{{folderPathErrors.otherLabel}}" ng-if="folderPathErrors.isParent && folderPathErrors.otherLabel.length != 0">Warning, this path is a parent directory of an existing folder "{%otherFolderLabel%}" ({%otherFolder%}).</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="folder-sharing" class="tab-pane">
|
||||
<div class="form-horizontal" ng-if="currentSharing.shared.length">
|
||||
<label translate>Currently Shared With Devices</label>
|
||||
<p class="help-block">
|
||||
<span translate>Deselect devices to stop sharing this folder with.</span> 
|
||||
<small><a href="#" ng-click="selectAllSharedDevices(true)" translate>Select All</a> 
|
||||
<a href="#" ng-click="selectAllSharedDevices(false)" translate>Deselect All</a></small>
|
||||
</p>
|
||||
<div class="form-group" ng-repeat="device in currentSharing.shared">
|
||||
<share-template selected="currentSharing.selected" encryption-passwords="currentSharing.encryptionPasswords" id="{{device.deviceID}}" label="{{deviceName(device)}}" folder-type="{{currentFolder.type}}" untrusted="{{device.untrusted}}" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-horizontal" ng-if="currentSharing.unrelated.length || otherDevices().length <= 0">
|
||||
<label translate>Unshared Devices</label>
|
||||
<p class="help-block" ng-if="otherDevices().length > 0">
|
||||
<span translate>Select additional devices to share this folder with.</span> 
|
||||
<small><a href="#" ng-click="selectAllUnrelatedDevices(true)" translate>Select All</a> 
|
||||
<a href="#" ng-click="selectAllUnrelatedDevices(false)" translate>Deselect All</a></small>
|
||||
</p>
|
||||
<p class="help-block" ng-if="otherDevices().length <= 0">
|
||||
<span translate>There are no devices to share this folder with.</span>
|
||||
</p>
|
||||
<div class="form-group" ng-repeat="device in currentSharing.unrelated" ng-init="id = device.deviceID; folder = currentFolder">
|
||||
<share-template selected="currentSharing.selected" encryption-passwords="currentSharing.encryptionPasswords" id="{{device.deviceID}}" label="{{deviceName(device)}}" folder-type="{{currentFolder.type}}" untrusted="{{device.untrusted}}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="folder-versioning" class="tab-pane">
|
||||
<div class="form-group">
|
||||
<label translate>File Versioning</label> <a href="https://docs.syncthing.net/users/versioning.html" target="_blank"><span class="fas fa-question-circle"></span> <span translate>Help</span></a>
|
||||
<select class="form-control" ng-model="currentFolder.fileVersioningSelector">
|
||||
<option value="none" translate>No File Versioning</option>
|
||||
<option value="trashcan" translate>Trash Can File Versioning</option>
|
||||
<option value="simple" translate>Simple File Versioning</option>
|
||||
<option value="staggered" translate>Staggered File Versioning</option>
|
||||
<option value="external" translate>External File Versioning</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" ng-if="currentFolder.fileVersioningSelector=='trashcan' || currentFolder.fileVersioningSelector=='simple'" ng-class="{'has-error': folderEditor.trashcanClean.$invalid && folderEditor.trashcanClean.$dirty}">
|
||||
<p translate class="help-block">Files are moved to .stversions directory when replaced or deleted by Syncthing.</p>
|
||||
<label translate for="trashcanClean">Clean out after</label>
|
||||
<div class="input-group">
|
||||
<input name="trashcanClean" id="trashcanClean" class="form-control text-right" type="number" ng-model="currentFolder.trashcanClean" required="" aria-required="true" min="0" />
|
||||
<div class="input-group-addon" translate>days</div>
|
||||
</div>
|
||||
<p class="help-block">
|
||||
<span translate ng-if="folderEditor.trashcanClean.$valid || folderEditor.trashcanClean.$pristine">The number of days to keep files in the trash can. Zero means forever.</span>
|
||||
<span translate ng-if="folderEditor.trashcanClean.$error.required && folderEditor.trashcanClean.$dirty">The number of days must be a number and cannot be blank.</span>
|
||||
<span translate ng-if="folderEditor.trashcanClean.$error.min && folderEditor.trashcanClean.$dirty">A negative number of days doesn't make sense.</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="form-group" ng-if="currentFolder.fileVersioningSelector=='simple'" ng-class="{'has-error': folderEditor.simpleKeep.$invalid && folderEditor.simpleKeep.$dirty}">
|
||||
<p translate class="help-block">Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.</p>
|
||||
<label translate for="simpleKeep">Keep Versions</label>
|
||||
<input name="simpleKeep" id="simpleKeep" class="form-control" type="number" ng-model="currentFolder.simpleKeep" required="" aria-required="true" min="1" />
|
||||
<p class="help-block">
|
||||
<span translate ng-if="folderEditor.simpleKeep.$valid || folderEditor.simpleKeep.$pristine">The number of old versions to keep, per file.</span>
|
||||
<span translate ng-if="folderEditor.simpleKeep.$error.required && folderEditor.simpleKeep.$dirty">The number of versions must be a number and cannot be blank.</span>
|
||||
<span translate ng-if="folderEditor.simpleKeep.$error.min && folderEditor.simpleKeep.$dirty">You must keep at least one version.</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="form-group" ng-if="currentFolder.fileVersioningSelector=='staggered'" ng-class="{'has-error': folderEditor.staggeredMaxAge.$invalid && folderEditor.staggeredMaxAge.$dirty}">
|
||||
<p class="help-block"><span translate>Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.</span> <span translate>Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.</span></p>
|
||||
<p translate class="help-block">The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.</p>
|
||||
<label translate for="staggeredMaxAge">Maximum Age</label>
|
||||
<input name="staggeredMaxAge" id="staggeredMaxAge" class="form-control" type="number" ng-model="currentFolder.staggeredMaxAge" required="" aria-required="true" min="0" />
|
||||
<p class="help-block">
|
||||
<span translate ng-if="folderEditor.staggeredMaxAge.$valid || folderEditor.staggeredMaxAge.$pristine">The maximum time to keep a version (in days, set to 0 to keep versions forever).</span>
|
||||
<span translate ng-if="folderEditor.staggeredMaxAge.$error.required && folderEditor.staggeredMaxAge.$dirty">The maximum age must be a number and cannot be blank.</span>
|
||||
<span translate ng-if="folderEditor.staggeredMaxAge.$error.min && folderEditor.staggeredMaxAge.$dirty">A negative number of days doesn't make sense.</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="form-group" ng-if="currentFolder.fileVersioningSelector == 'staggered'">
|
||||
<label translate for="staggeredVersionsPath">Versions Path</label>
|
||||
<input name="staggeredVersionsPath" id="staggeredVersionsPath" class="form-control" type="text" ng-model="currentFolder.staggeredVersionsPath" />
|
||||
<p translate class="help-block">Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).</p>
|
||||
</div>
|
||||
<div class="form-group" ng-if="currentFolder.fileVersioningSelector=='external'" ng-class="{'has-error': folderEditor.externalCommand.$invalid && folderEditor.externalCommand.$dirty}">
|
||||
<p translate class="help-block">An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.</p>
|
||||
<label translate for="externalCommand">Command</label>
|
||||
<input name="externalCommand" id="externalCommand" class="form-control" type="text" ng-model="currentFolder.externalCommand" required="" aria-required="true" />
|
||||
<p class="help-block">
|
||||
<span translate ng-if="folderEditor.externalCommand.$valid || folderEditor.externalCommand.$pristine">See external versioning help for supported templated command line parameters.</span>
|
||||
<span translate ng-if="folderEditor.externalCommand.$error.required && folderEditor.externalCommand.$dirty">The path cannot be blank.</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="form-group" ng-if="currentFolder.fileVersioningSelector != 'none'" ng-class="{'has-error': folderEditor.versioningCleanupIntervalS.$invalid && folderEditor.versioningCleanupIntervalS.$dirty}">
|
||||
<label translate for="versioningCleanupIntervalS">Cleanup Interval</label>
|
||||
<div class="input-group">
|
||||
<input name="versioningCleanupIntervalS" id="versioningCleanupIntervalS" class="form-control text-right" type="number" ng-model="currentFolder.versioningCleanupIntervalS" required="" min="0" max="31536000" aria-required="true" />
|
||||
<div class="input-group-addon" translate>seconds</div>
|
||||
</div>
|
||||
<p class="help-block">
|
||||
<span translate ng-if="folderEditor.versioningCleanupIntervalS.$valid || folderEditor.versioningCleanupIntervalS.$pristine"class="help-block">The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.</span>
|
||||
<span translate ng-if="folderEditor.versioningCleanupIntervalS.$error.required && folderEditor.versioningCleanupIntervalS.$dirty">The cleanup interval cannot be blank.</span>
|
||||
<span translate ng-if="folderEditor.versioningCleanupIntervalS.$error.min && folderEditor.versioningCleanupIntervalS.$dirty">The interval must be a positive number of seconds.</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="folder-ignores" class="tab-pane">
|
||||
<p translate>Enter ignore patterns, one per line.</p>
|
||||
<div ng-class="{'has-error': ignores.error != null}">
|
||||
<textarea class="form-control" rows="5" ng-model="ignores.text" ng-disabled="ignores.disabled"></textarea>
|
||||
<p class="help-block" ng-if="ignores.error">
|
||||
{{ignores.error}}
|
||||
</p>
|
||||
</div>
|
||||
<hr />
|
||||
<p class="small"><span translate>Quick guide to supported patterns</span> (<a href="https://docs.syncthing.net/users/ignoring.html" target="_blank" translate>full documentation</a>):</p>
|
||||
<dl class="dl-horizontal dl-narrow small">
|
||||
<dt><code>(?d)</code></dt>
|
||||
<dd><b><span translate>Prefix indicating that the file can be deleted if preventing directory removal</span></b></dd>
|
||||
<dt><code>(?i)</code></dt>
|
||||
<dd><span translate>Prefix indicating that the pattern should be matched without case sensitivity</span></dd>
|
||||
<dt><code>!</code></dt>
|
||||
<dd><span translate>Inversion of the given condition (i.e. do not exclude)</span></dd>
|
||||
<dt><code>*</code></dt>
|
||||
<dd><span translate>Single level wildcard (matches within a directory only)</span></dd>
|
||||
<dt><code>**</code></dt>
|
||||
<dd><span translate>Multi level wildcard (matches multiple directory levels)</span></dd>
|
||||
<dt><code>//</code></dt>
|
||||
<dd><span translate>Comment, when used at the start of a line</span></dd>
|
||||
</dl>
|
||||
<hr />
|
||||
<span translate ng-show="editingExisting" translate-value-path="{{currentFolder.path}}{{system.pathSeparator}}.stignore">Editing {%path%}.</span>
|
||||
<span translate ng-show="!editingExisting" translate-value-path="{{currentFolder.path}}{{system.pathSeparator}}.stignore">Creating ignore patterns, overwriting an existing file at {%path%}.</span>
|
||||
</div>
|
||||
|
||||
<div id="folder-advanced" class="tab-pane">
|
||||
<div class="row form-group" ng-class="{'has-error': folderEditor.rescanIntervalS.$invalid && folderEditor.rescanIntervalS.$dirty}">
|
||||
<div class="col-md-12">
|
||||
<label translate>Scanning</label>
|
||||
<a href="https://docs.syncthing.net/users/syncing.html#scanning" target="_blank"><span class="fas fa-question-circle"></span> <span translate>Help</span></a></br>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="currentFolder.fsWatcherEnabled" ng-change="fsWatcherToggled()" tooltip data-original-title="{{'Use notifications from the filesystem to detect changed items.' | translate }}"> <span translate>Watch for Changes</span>
|
||||
</label>
|
||||
<p translate class="help-block">Watching for changes discovers most changes without periodic scanning.</p>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="rescanIntervalS" translate>Full Rescan Interval (s)</label>
|
||||
<input name="rescanIntervalS" id="rescanIntervalS" class="form-control" type="number" ng-model="currentFolder.rescanIntervalS" required="" aria-required="true" min="0" />
|
||||
<p class="help-block" ng-if="!folderEditor.rescanIntervalS.$valid && folderEditor.rescanIntervalS.$dirty" translate>
|
||||
The rescan interval must be a non-negative number of seconds.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 form-group">
|
||||
<label translate>Folder Type</label>
|
||||
<a href="https://docs.syncthing.net/users/foldertypes.html" target="_blank"><span class="fas fa-question-circle"></span> <span translate>Help</span></a>
|
||||
<select class="form-control" ng-model="currentFolder.type" ng-disabled="editingExisting && currentFolder.type === 'receiveencrypted'">
|
||||
<option value="sendreceive" translate>Send & Receive</option>
|
||||
<option value="sendonly" translate>Send Only</option>
|
||||
<option value="receiveonly" translate>Receive Only</option>
|
||||
<option value="receiveencrypted" ng-disabled="editingExisting" translate>Receive Encrypted</option>
|
||||
</select>
|
||||
<p ng-if="currentFolder.type == 'sendonly'" translate class="help-block">Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.</p>
|
||||
<p ng-if="currentFolder.type == 'receiveonly'" translate class="help-block">Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.</p>
|
||||
<p ng-if="currentFolder.type == 'receiveencrypted'" translate class="help-block" translate-value-receive-encrypted="{{'Receive Encrypted' | translate}}">Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type "{%receiveEncrypted%}" too.</p>
|
||||
<p ng-if="editingExisting" translate class="help-block" translate-value-receive-encrypted="{{'Receive Encrypted' | translate}}">Folder type "{%receiveEncrypted%}" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.</p>
|
||||
</div>
|
||||
<div class="col-md-6 form-group">
|
||||
<label translate>File Pull Order</label>
|
||||
<select class="form-control" ng-model="currentFolder.order" ng-if="currentFolder.type != 'sendonly'">
|
||||
<option value="random" translate>Random</option>
|
||||
<option value="alphabetic" translate>Alphabetic</option>
|
||||
<option value="smallestFirst" translate>Smallest First</option>
|
||||
<option value="largestFirst" translate>Largest First</option>
|
||||
<option value="oldestFirst" translate>Oldest First</option>
|
||||
<option value="newestFirst" translate>Newest First</option>
|
||||
</select>
|
||||
<select class="form-control" ng-if="currentFolder.type == 'sendonly'" disabled>
|
||||
<option value="disabled" translate>Disabled</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 form-group" ng-class="{'has-error': folderEditor.minDiskFree.$invalid && folderEditor.minDiskFree.$dirty}">
|
||||
<label for="minDiskFree" translate>Minimum Free Disk Space</label><br />
|
||||
<div class="row">
|
||||
<div class="col-xs-9">
|
||||
<input name="minDiskFree" id="minDiskFree" class="form-control" type="number" ng-model="currentFolder.minDiskFree.value" required="" aria-required="true" min="0" step="0.01" />
|
||||
</div>
|
||||
<div class="col-xs-3">
|
||||
<select class="form-control" ng-model="currentFolder.minDiskFree.unit">
|
||||
<option value="%">%</option>
|
||||
<option value="kB">kB</option>
|
||||
<option value="MB">MB</option>
|
||||
<option value="GB">GB</option>
|
||||
<option value="TB">TB</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<p class="help-block" ng-show="folderEditor.minDiskFree.$invalid" translate>
|
||||
Enter a non-negative number (e.g., "2.35") and select a unit. Percentages are as part of the total disk size.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-6 form-group">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="currentFolder.ignorePerms" /> <span translate>Ignore Permissions</span>
|
||||
</label>
|
||||
<p translate class="help-block">
|
||||
Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary btn-sm" ng-click="saveFolder()" ng-disabled="folderEditor.$invalid">
|
||||
<span class="fas fa-check"></span> <span translate>Save</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal">
|
||||
<span class="fas fa-times"></span> <span translate>Close</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-warning pull-left btn-sm" data-toggle="modal" data-target="#remove-folder-confirmation" ng-if="editingExisting">
|
||||
<span class="fas fa-minus-circle"></span> <span translate>Remove</span>
|
||||
</button>
|
||||
</div>
|
||||
</modal>
|
||||
@@ -0,0 +1,35 @@
|
||||
<modal id="localChanged" status="{{localChangedType === 'receiveencrypted' ? 'warning' : 'info'}}" icon="fas fa-exclamation-circle" heading="{{localChangedHeading(localChangedType)}}" large="yes" closeable="yes">
|
||||
<div class="modal-body" ng-switch="localChangedType">
|
||||
<p ng-switch-when="receiveonly" translate>
|
||||
The following items were changed locally.
|
||||
</p>
|
||||
<p ng-switch-when="receiveencrypted">
|
||||
<span translate>The following unexpected items were found.</span>
|
||||
<span translate translate-value-receive-encrypted="{{'Receive Encrypted' | translate}}">You should never add or change anything locally in a "{%receiveEncrypted%}" folder.</span>
|
||||
</p>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th translate>Path</th>
|
||||
<th translate>Size</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr dir-paginate="file in localChanged.files | itemsPerPage: localChanged.perpage" current-page="localChanged.page" total-items="model[localChangedFolder].receiveOnlyTotalItems" pagination-id="localChanged">
|
||||
<td class="file-path">{{file.name}}</td>
|
||||
<td><span ng-hide="file.type == 'DIRECTORY'">{{file.size | binary}}B</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
<dir-pagination-controls on-page-change="refreshLocalChanged(newPageNumber, localChanged.perpage)" pagination-id="localChanged"></dir-pagination-controls>
|
||||
<ul class="pagination pull-right">
|
||||
<li ng-repeat="option in [10, 25, 50]" ng-class="{ active: localChanged.perpage == option }">
|
||||
<a href="#" ng-click="refreshLocalChanged(localChanged.page, option)">{{option}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal">
|
||||
<span class="fas fa-times"></span> <span translate>Close</span>
|
||||
</button>
|
||||
</div>
|
||||
</modal>
|
||||
211
lib/api/api.go
211
lib/api/api.go
@@ -31,10 +31,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/julienschmidt/httprouter"
|
||||
metrics "github.com/rcrowley/go-metrics"
|
||||
"github.com/thejerf/suture"
|
||||
"github.com/vitrun/qart/qr"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
@@ -65,6 +65,7 @@ const (
|
||||
EventSubBufferSize = 1000
|
||||
defaultEventTimeout = time.Minute
|
||||
httpsCertLifetimeDays = 820
|
||||
featureFlagUntrusted = "untrusted"
|
||||
)
|
||||
|
||||
type service struct {
|
||||
@@ -81,7 +82,6 @@ type service struct {
|
||||
connectionsService connections.Service
|
||||
fss model.FolderSummaryService
|
||||
urService *ur.Service
|
||||
systemConfigMut sync.Mutex // serializes posts to /rest/system/config
|
||||
contr Controller
|
||||
noUpgrade bool
|
||||
tlsDefaultCommonName string
|
||||
@@ -111,7 +111,7 @@ func New(id protocol.DeviceID, cfg config.Wrapper, assetDir, tlsDefaultCommonNam
|
||||
s := &service{
|
||||
id: id,
|
||||
cfg: cfg,
|
||||
statics: newStaticsServer(cfg.GUI().Theme, assetDir),
|
||||
statics: newStaticsServer(cfg.GUI().Theme, assetDir, cfg.Options().FeatureFlag(featureFlagUntrusted)),
|
||||
model: m,
|
||||
eventSubs: map[events.EventType]events.BufferedSubscription{
|
||||
DefaultEventMask: defaultSub,
|
||||
@@ -123,7 +123,6 @@ func New(id protocol.DeviceID, cfg config.Wrapper, assetDir, tlsDefaultCommonNam
|
||||
connectionsService: connectionsService,
|
||||
fss: fss,
|
||||
urService: urService,
|
||||
systemConfigMut: sync.NewMutex(),
|
||||
guiErrors: errors,
|
||||
systemLog: systemLog,
|
||||
contr: contr,
|
||||
@@ -243,60 +242,80 @@ func (s *service) serve(ctx context.Context) {
|
||||
s.cfg.Subscribe(s)
|
||||
defer s.cfg.Unsubscribe(s)
|
||||
|
||||
restMux := httprouter.New()
|
||||
|
||||
// The GET handlers
|
||||
getRestMux := http.NewServeMux()
|
||||
getRestMux.HandleFunc("/rest/db/completion", s.getDBCompletion) // [device] [folder]
|
||||
getRestMux.HandleFunc("/rest/db/file", s.getDBFile) // folder file
|
||||
getRestMux.HandleFunc("/rest/db/ignores", s.getDBIgnores) // folder
|
||||
getRestMux.HandleFunc("/rest/db/need", s.getDBNeed) // folder [perpage] [page]
|
||||
getRestMux.HandleFunc("/rest/db/remoteneed", s.getDBRemoteNeed) // device folder [perpage] [page]
|
||||
getRestMux.HandleFunc("/rest/db/localchanged", s.getDBLocalChanged) // folder
|
||||
getRestMux.HandleFunc("/rest/db/status", s.getDBStatus) // folder
|
||||
getRestMux.HandleFunc("/rest/db/browse", s.getDBBrowse) // folder [prefix] [dirsonly] [levels]
|
||||
getRestMux.HandleFunc("/rest/folder/versions", s.getFolderVersions) // folder
|
||||
getRestMux.HandleFunc("/rest/folder/errors", s.getFolderErrors) // folder
|
||||
getRestMux.HandleFunc("/rest/folder/pullerrors", s.getFolderErrors) // folder (deprecated)
|
||||
getRestMux.HandleFunc("/rest/events", s.getIndexEvents) // [since] [limit] [timeout] [events]
|
||||
getRestMux.HandleFunc("/rest/events/disk", s.getDiskEvents) // [since] [limit] [timeout]
|
||||
getRestMux.HandleFunc("/rest/stats/device", s.getDeviceStats) // -
|
||||
getRestMux.HandleFunc("/rest/stats/folder", s.getFolderStats) // -
|
||||
getRestMux.HandleFunc("/rest/svc/deviceid", s.getDeviceID) // id
|
||||
getRestMux.HandleFunc("/rest/svc/lang", s.getLang) // -
|
||||
getRestMux.HandleFunc("/rest/svc/report", s.getReport) // -
|
||||
getRestMux.HandleFunc("/rest/svc/random/string", s.getRandomString) // [length]
|
||||
getRestMux.HandleFunc("/rest/system/browse", s.getSystemBrowse) // current
|
||||
getRestMux.HandleFunc("/rest/system/config", s.getSystemConfig) // -
|
||||
getRestMux.HandleFunc("/rest/system/config/insync", s.getSystemConfigInsync) // -
|
||||
getRestMux.HandleFunc("/rest/system/connections", s.getSystemConnections) // -
|
||||
getRestMux.HandleFunc("/rest/system/discovery", s.getSystemDiscovery) // -
|
||||
getRestMux.HandleFunc("/rest/system/error", s.getSystemError) // -
|
||||
getRestMux.HandleFunc("/rest/system/ping", s.restPing) // -
|
||||
getRestMux.HandleFunc("/rest/system/status", s.getSystemStatus) // -
|
||||
getRestMux.HandleFunc("/rest/system/upgrade", s.getSystemUpgrade) // -
|
||||
getRestMux.HandleFunc("/rest/system/version", s.getSystemVersion) // -
|
||||
getRestMux.HandleFunc("/rest/system/debug", s.getSystemDebug) // -
|
||||
getRestMux.HandleFunc("/rest/system/log", s.getSystemLog) // [since]
|
||||
getRestMux.HandleFunc("/rest/system/log.txt", s.getSystemLogTxt) // [since]
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/db/completion", s.getDBCompletion) // [device] [folder]
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/db/file", s.getDBFile) // folder file
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/db/ignores", s.getDBIgnores) // folder
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/db/need", s.getDBNeed) // folder [perpage] [page]
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/db/remoteneed", s.getDBRemoteNeed) // device folder [perpage] [page]
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/db/localchanged", s.getDBLocalChanged) // folder
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/db/status", s.getDBStatus) // folder
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/db/browse", s.getDBBrowse) // folder [prefix] [dirsonly] [levels]
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/folder/versions", s.getFolderVersions) // folder
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/folder/errors", s.getFolderErrors) // folder
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/folder/pullerrors", s.getFolderErrors) // folder (deprecated)
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/events", s.getIndexEvents) // [since] [limit] [timeout] [events]
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/events/disk", s.getDiskEvents) // [since] [limit] [timeout]
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/stats/device", s.getDeviceStats) // -
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/stats/folder", s.getFolderStats) // -
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/svc/deviceid", s.getDeviceID) // id
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/svc/lang", s.getLang) // -
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/svc/report", s.getReport) // -
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/svc/random/string", s.getRandomString) // [length]
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/system/browse", s.getSystemBrowse) // current
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/system/connections", s.getSystemConnections) // -
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/system/discovery", s.getSystemDiscovery) // -
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/system/error", s.getSystemError) // -
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/system/ping", s.restPing) // -
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/system/status", s.getSystemStatus) // -
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/system/upgrade", s.getSystemUpgrade) // -
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/system/version", s.getSystemVersion) // -
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/system/debug", s.getSystemDebug) // -
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/system/log", s.getSystemLog) // [since]
|
||||
restMux.HandlerFunc(http.MethodGet, "/rest/system/log.txt", s.getSystemLogTxt) // [since]
|
||||
|
||||
// The POST handlers
|
||||
postRestMux := http.NewServeMux()
|
||||
postRestMux.HandleFunc("/rest/db/prio", s.postDBPrio) // folder file [perpage] [page]
|
||||
postRestMux.HandleFunc("/rest/db/ignores", s.postDBIgnores) // folder
|
||||
postRestMux.HandleFunc("/rest/db/override", s.postDBOverride) // folder
|
||||
postRestMux.HandleFunc("/rest/db/revert", s.postDBRevert) // folder
|
||||
postRestMux.HandleFunc("/rest/db/scan", s.postDBScan) // folder [sub...] [delay]
|
||||
postRestMux.HandleFunc("/rest/folder/versions", s.postFolderVersionsRestore) // folder <body>
|
||||
postRestMux.HandleFunc("/rest/system/config", s.postSystemConfig) // <body>
|
||||
postRestMux.HandleFunc("/rest/system/error", s.postSystemError) // <body>
|
||||
postRestMux.HandleFunc("/rest/system/error/clear", s.postSystemErrorClear) // -
|
||||
postRestMux.HandleFunc("/rest/system/ping", s.restPing) // -
|
||||
postRestMux.HandleFunc("/rest/system/reset", s.postSystemReset) // [folder]
|
||||
postRestMux.HandleFunc("/rest/system/restart", s.postSystemRestart) // -
|
||||
postRestMux.HandleFunc("/rest/system/shutdown", s.postSystemShutdown) // -
|
||||
postRestMux.HandleFunc("/rest/system/upgrade", s.postSystemUpgrade) // -
|
||||
postRestMux.HandleFunc("/rest/system/pause", s.makeDevicePauseHandler(true)) // [device]
|
||||
postRestMux.HandleFunc("/rest/system/resume", s.makeDevicePauseHandler(false)) // [device]
|
||||
postRestMux.HandleFunc("/rest/system/debug", s.postSystemDebug) // [enable] [disable]
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/db/prio", s.postDBPrio) // folder file [perpage] [page]
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/db/ignores", s.postDBIgnores) // folder
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/db/override", s.postDBOverride) // folder
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/db/revert", s.postDBRevert) // folder
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/db/scan", s.postDBScan) // folder [sub...] [delay]
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/folder/versions", s.postFolderVersionsRestore) // folder <body>
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/system/error", s.postSystemError) // <body>
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/system/error/clear", s.postSystemErrorClear) // -
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/system/ping", s.restPing) // -
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/system/reset", s.postSystemReset) // [folder]
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/system/restart", s.postSystemRestart) // -
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/system/shutdown", s.postSystemShutdown) // -
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/system/upgrade", s.postSystemUpgrade) // -
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/system/pause", s.makeDevicePauseHandler(true)) // [device]
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/system/resume", s.makeDevicePauseHandler(false)) // [device]
|
||||
restMux.HandlerFunc(http.MethodPost, "/rest/system/debug", s.postSystemDebug) // [enable] [disable]
|
||||
|
||||
// Config endpoints
|
||||
|
||||
configBuilder := &configMuxBuilder{
|
||||
Router: restMux,
|
||||
id: s.id,
|
||||
cfg: s.cfg,
|
||||
mut: sync.NewMutex(),
|
||||
}
|
||||
|
||||
configBuilder.registerConfig("/rest/config")
|
||||
configBuilder.registerConfigInsync("/rest/config/insync")
|
||||
configBuilder.registerFolders("/rest/config/folders")
|
||||
configBuilder.registerDevices("/rest/config/devices")
|
||||
configBuilder.registerFolder("/rest/config/folders/:id")
|
||||
configBuilder.registerDevice("/rest/config/devices/:id")
|
||||
configBuilder.registerOptions("/rest/config/options")
|
||||
configBuilder.registerLDAP("/rest/config/ldap")
|
||||
configBuilder.registerGUI("/rest/config/gui")
|
||||
|
||||
// Deprecated config endpoints
|
||||
configBuilder.registerConfigDeprecated("/rest/system/config") // POST instead of PUT
|
||||
configBuilder.registerConfigInsync("/rest/system/config/insync")
|
||||
|
||||
// Debug endpoints, not for general use
|
||||
debugMux := http.NewServeMux()
|
||||
@@ -305,15 +324,14 @@ func (s *service) serve(ctx context.Context) {
|
||||
debugMux.HandleFunc("/rest/debug/cpuprof", s.getCPUProf) // duration
|
||||
debugMux.HandleFunc("/rest/debug/heapprof", s.getHeapProf)
|
||||
debugMux.HandleFunc("/rest/debug/support", s.getSupportBundle)
|
||||
getRestMux.Handle("/rest/debug/", s.whenDebugging(debugMux))
|
||||
restMux.Handler(http.MethodGet, "/rest/debug/*method", s.whenDebugging(debugMux))
|
||||
|
||||
// A handler that splits requests between the two above and disables
|
||||
// caching
|
||||
restMux := noCacheMiddleware(metricsMiddleware(getPostHandler(getRestMux, postRestMux)))
|
||||
// A handler that disables caching
|
||||
noCacheRestMux := noCacheMiddleware(metricsMiddleware(restMux))
|
||||
|
||||
// The main routing handler
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/rest/", restMux)
|
||||
mux.Handle("/rest/", noCacheRestMux)
|
||||
mux.HandleFunc("/qr/", s.getQR)
|
||||
|
||||
// Serve compiled in assets unless an asset directory was set (for development)
|
||||
@@ -432,7 +450,12 @@ func (s *service) CommitConfiguration(from, to config.Configuration) bool {
|
||||
// No action required when this changes, so mask the fact that it changed at all.
|
||||
from.GUI.Debugging = to.GUI.Debugging
|
||||
|
||||
if untrusted := to.Options.FeatureFlag(featureFlagUntrusted); untrusted != from.Options.FeatureFlag(featureFlagUntrusted) {
|
||||
s.statics.setUntrusted(untrusted)
|
||||
}
|
||||
|
||||
if to.GUI == from.GUI {
|
||||
// No GUI changes, we're done here.
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -446,19 +469,6 @@ func (s *service) CommitConfiguration(from, to config.Configuration) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func getPostHandler(get, post http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case "GET":
|
||||
get.ServeHTTP(w, r)
|
||||
case "POST":
|
||||
post.ServeHTTP(w, r)
|
||||
default:
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func debugMiddleware(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
t0 := time.Now()
|
||||
@@ -499,8 +509,8 @@ func corsMiddleware(next http.Handler, allowFrameLoading bool) http.Handler {
|
||||
if r.Method == "OPTIONS" {
|
||||
// Add a generous access-control-allow-origin header for CORS requests
|
||||
w.Header().Add("Access-Control-Allow-Origin", "*")
|
||||
// Only GET/POST Methods are supported
|
||||
w.Header().Set("Access-Control-Allow-Methods", "GET, POST")
|
||||
// Only GET/POST/OPTIONS Methods are supported
|
||||
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS")
|
||||
// Only these headers can be set
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, X-API-Key")
|
||||
// The request is meant to be cached 10 minutes
|
||||
@@ -837,57 +847,6 @@ func (s *service) getDBFile(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *service) getSystemConfig(w http.ResponseWriter, r *http.Request) {
|
||||
sendJSON(w, s.cfg.RawCopy())
|
||||
}
|
||||
|
||||
func (s *service) postSystemConfig(w http.ResponseWriter, r *http.Request) {
|
||||
s.systemConfigMut.Lock()
|
||||
defer s.systemConfigMut.Unlock()
|
||||
|
||||
to, err := config.ReadJSON(r.Body, s.id)
|
||||
r.Body.Close()
|
||||
if err != nil {
|
||||
l.Warnln("Decoding posted config:", err)
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if to.GUI.Password != s.cfg.GUI().Password {
|
||||
if to.GUI.Password != "" && !bcryptExpr.MatchString(to.GUI.Password) {
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(to.GUI.Password), 0)
|
||||
if err != nil {
|
||||
l.Warnln("bcrypting password:", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
to.GUI.Password = string(hash)
|
||||
}
|
||||
}
|
||||
|
||||
// Activate and save. Wait for the configuration to become active before
|
||||
// completing the request.
|
||||
|
||||
if wg, err := s.cfg.Replace(to); err != nil {
|
||||
l.Warnln("Replacing config:", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
} else {
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
if err := s.cfg.Save(); err != nil {
|
||||
l.Warnln("Saving config:", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) getSystemConfigInsync(w http.ResponseWriter, r *http.Request) {
|
||||
sendJSON(w, map[string]bool{"configInSync": !s.cfg.RequiresRestart()})
|
||||
}
|
||||
|
||||
func (s *service) postSystemRestart(w http.ResponseWriter, r *http.Request) {
|
||||
s.flushResponse(`{"ok": "restarting"}`, w)
|
||||
go s.contr.Restart()
|
||||
|
||||
@@ -30,15 +30,17 @@ type staticsServer struct {
|
||||
mut sync.RWMutex
|
||||
theme string
|
||||
lastThemeChange time.Time
|
||||
untrusted bool
|
||||
}
|
||||
|
||||
func newStaticsServer(theme, assetDir string) *staticsServer {
|
||||
func newStaticsServer(theme, assetDir string, untrusted bool) *staticsServer {
|
||||
s := &staticsServer{
|
||||
assetDir: assetDir,
|
||||
assets: auto.Assets(),
|
||||
mut: sync.NewRWMutex(),
|
||||
theme: theme,
|
||||
lastThemeChange: time.Now().UTC(),
|
||||
untrusted: untrusted,
|
||||
}
|
||||
|
||||
seen := make(map[string]struct{})
|
||||
@@ -60,6 +62,10 @@ func newStaticsServer(theme, assetDir string) *staticsServer {
|
||||
}
|
||||
}
|
||||
|
||||
if untrusted {
|
||||
l.Infoln(`Feature flag "untrusted":`, untrusted)
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -88,6 +94,7 @@ func (s *staticsServer) serveAsset(w http.ResponseWriter, r *http.Request) {
|
||||
s.mut.RLock()
|
||||
theme := s.theme
|
||||
modificationTime := s.lastThemeChange
|
||||
untrusted := s.untrusted
|
||||
s.mut.RUnlock()
|
||||
|
||||
// If path starts with special prefix, get theme and file from path
|
||||
@@ -105,44 +112,68 @@ func (s *staticsServer) serveAsset(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Check for an override for the current theme.
|
||||
if s.assetDir != "" {
|
||||
p := filepath.Join(s.assetDir, theme, filepath.FromSlash(file))
|
||||
if _, err := os.Stat(p); err == nil {
|
||||
mtype := assets.MimeTypeForFile(file)
|
||||
if len(mtype) != 0 {
|
||||
w.Header().Set("Content-Type", mtype)
|
||||
}
|
||||
http.ServeFile(w, r, p)
|
||||
return
|
||||
}
|
||||
if untrusted && s.serveFromAssetDir(file, theme+"/untrusted", w, r) {
|
||||
l.Debugln("serving", file, "from override untrusted")
|
||||
return
|
||||
}
|
||||
if s.serveFromAssetDir(file, theme, w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
// Check for a compiled in asset for the current theme.
|
||||
as, ok := s.assets[theme+"/"+file]
|
||||
if !ok {
|
||||
// Check for an overridden default asset.
|
||||
if s.assetDir != "" {
|
||||
p := filepath.Join(s.assetDir, config.DefaultTheme, filepath.FromSlash(file))
|
||||
if _, err := os.Stat(p); err == nil {
|
||||
mtype := assets.MimeTypeForFile(file)
|
||||
if len(mtype) != 0 {
|
||||
w.Header().Set("Content-Type", mtype)
|
||||
}
|
||||
http.ServeFile(w, r, p)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Check for a compiled in default asset.
|
||||
as, ok = s.assets[config.DefaultTheme+"/"+file]
|
||||
if !ok {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
if untrusted && s.serveFromAssets(file, theme+"/untrusted", modificationTime, w, r) {
|
||||
l.Debugln("serving", file, "from compiled untrusted")
|
||||
return
|
||||
}
|
||||
if s.serveFromAssets(file, theme, modificationTime, w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
// Check for an overridden default asset.
|
||||
if untrusted && s.serveFromAssetDir(file, config.DefaultTheme+"/untrusted", w, r) {
|
||||
l.Debugln("serving", file, "from override untrusted")
|
||||
return
|
||||
}
|
||||
if s.serveFromAssetDir(file, config.DefaultTheme, w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
// Check for a compiled in default asset.
|
||||
if untrusted && s.serveFromAssets(file, config.DefaultTheme+"/untrusted", modificationTime, w, r) {
|
||||
l.Debugln("serving", file, "from compiled untrusted")
|
||||
return
|
||||
}
|
||||
if s.serveFromAssets(file, config.DefaultTheme, modificationTime, w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
|
||||
func (s *staticsServer) serveFromAssetDir(file, theme string, w http.ResponseWriter, r *http.Request) bool {
|
||||
if s.assetDir == "" {
|
||||
return false
|
||||
}
|
||||
p := filepath.Join(s.assetDir, theme, filepath.FromSlash(file))
|
||||
if _, err := os.Stat(p); err != nil {
|
||||
return false
|
||||
}
|
||||
mtype := assets.MimeTypeForFile(file)
|
||||
if len(mtype) != 0 {
|
||||
w.Header().Set("Content-Type", mtype)
|
||||
}
|
||||
http.ServeFile(w, r, p)
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *staticsServer) serveFromAssets(file, theme string, modificationTime time.Time, w http.ResponseWriter, r *http.Request) bool {
|
||||
as, ok := s.assets[theme+"/"+file]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
as.Modified = modificationTime
|
||||
assets.Serve(w, r, as)
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *staticsServer) serveThemes(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -158,6 +189,13 @@ func (s *staticsServer) setTheme(theme string) {
|
||||
s.mut.Unlock()
|
||||
}
|
||||
|
||||
func (s *staticsServer) setUntrusted(enabled bool) {
|
||||
s.mut.Lock()
|
||||
l.Infoln(`Feature flag "untrusted":`, enabled)
|
||||
s.untrusted = enabled
|
||||
s.mut.Unlock()
|
||||
}
|
||||
|
||||
func (s *staticsServer) String() string {
|
||||
return fmt.Sprintf("staticsServer@%p", s)
|
||||
}
|
||||
|
||||
@@ -40,8 +40,13 @@ import (
|
||||
var (
|
||||
confDir = filepath.Join("testdata", "config")
|
||||
token = filepath.Join(confDir, "csrftokens.txt")
|
||||
dev1 protocol.DeviceID
|
||||
)
|
||||
|
||||
func init() {
|
||||
dev1, _ = protocol.DeviceIDFromString("AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR")
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
orig := locations.GetBaseDir(locations.ConfigBaseDir)
|
||||
locations.SetBaseDir(locations.ConfigBaseDir, confDir)
|
||||
@@ -396,6 +401,62 @@ func TestAPIServiceRequests(t *testing.T) {
|
||||
Type: "text/plain",
|
||||
Prefix: "",
|
||||
},
|
||||
|
||||
// /rest/config
|
||||
{
|
||||
URL: "/rest/config",
|
||||
Code: 200,
|
||||
Type: "application/json",
|
||||
Prefix: "",
|
||||
},
|
||||
{
|
||||
URL: "/rest/config/folders",
|
||||
Code: 200,
|
||||
Type: "application/json",
|
||||
Prefix: "",
|
||||
},
|
||||
{
|
||||
URL: "/rest/config/folders/missing",
|
||||
Code: 404,
|
||||
Type: "text/plain",
|
||||
Prefix: "",
|
||||
},
|
||||
{
|
||||
URL: "/rest/config/devices",
|
||||
Code: 200,
|
||||
Type: "application/json",
|
||||
Prefix: "",
|
||||
},
|
||||
{
|
||||
URL: "/rest/config/devices/illegalid",
|
||||
Code: 400,
|
||||
Type: "text/plain",
|
||||
Prefix: "",
|
||||
},
|
||||
{
|
||||
URL: "/rest/config/devices/" + protocol.GlobalDeviceID.String(),
|
||||
Code: 404,
|
||||
Type: "text/plain",
|
||||
Prefix: "",
|
||||
},
|
||||
{
|
||||
URL: "/rest/config/options",
|
||||
Code: 200,
|
||||
Type: "application/json",
|
||||
Prefix: "{",
|
||||
},
|
||||
{
|
||||
URL: "/rest/config/gui",
|
||||
Code: 200,
|
||||
Type: "application/json",
|
||||
Prefix: "{",
|
||||
},
|
||||
{
|
||||
URL: "/rest/config/ldap",
|
||||
Code: 200,
|
||||
Type: "application/json",
|
||||
Prefix: "{",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
@@ -520,7 +581,7 @@ func TestHTTPLogin(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func startHTTP(cfg *mockedConfig) (string, *suture.Supervisor, error) {
|
||||
func startHTTP(cfg config.Wrapper) (string, *suture.Supervisor, error) {
|
||||
m := new(mockedModel)
|
||||
assetDir := "../../gui"
|
||||
eventSub := new(mockedEventSub)
|
||||
@@ -552,7 +613,7 @@ func startHTTP(cfg *mockedConfig) (string, *suture.Supervisor, error) {
|
||||
return "", nil, fmt.Errorf("weird address from API service: %w", err)
|
||||
}
|
||||
|
||||
host, _, _ := net.SplitHostPort(cfg.gui.RawAddress)
|
||||
host, _, _ := net.SplitHostPort(cfg.GUI().RawAddress)
|
||||
if host == "" || host == "0.0.0.0" {
|
||||
host = "127.0.0.1"
|
||||
}
|
||||
@@ -1018,8 +1079,8 @@ func TestOptionsRequest(t *testing.T) {
|
||||
if resp.Header.Get("Access-Control-Allow-Origin") != "*" {
|
||||
t.Fatal("OPTIONS on /rest/system/status should return a 'Access-Control-Allow-Origin: *' header")
|
||||
}
|
||||
if resp.Header.Get("Access-Control-Allow-Methods") != "GET, POST" {
|
||||
t.Fatal("OPTIONS on /rest/system/status should return a 'Access-Control-Allow-Methods: GET, POST' header")
|
||||
if resp.Header.Get("Access-Control-Allow-Methods") != "GET, POST, PUT, PATCH, DELETE, OPTIONS" {
|
||||
t.Fatal("OPTIONS on /rest/system/status should return a 'Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS' header")
|
||||
}
|
||||
if resp.Header.Get("Access-Control-Allow-Headers") != "Content-Type, X-API-Key" {
|
||||
t.Fatal("OPTIONS on /rest/system/status should return a 'Access-Control-Allow-Headers: Content-Type, X-API-KEY' header")
|
||||
@@ -1174,6 +1235,127 @@ func TestShouldRegenerateCertificate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigChanges(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const testAPIKey = "foobarbaz"
|
||||
cfg := config.Configuration{
|
||||
GUI: config.GUIConfiguration{
|
||||
RawAddress: "127.0.0.1:0",
|
||||
RawUseTLS: false,
|
||||
APIKey: testAPIKey,
|
||||
},
|
||||
}
|
||||
tmpFile, err := ioutil.TempFile("", "syncthing-testConfig-")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer os.Remove(tmpFile.Name())
|
||||
w := config.Wrap(tmpFile.Name(), cfg, events.NoopLogger)
|
||||
tmpFile.Close()
|
||||
baseURL, sup, err := startHTTP(w)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error from getting base URL:", err)
|
||||
}
|
||||
defer sup.Stop()
|
||||
|
||||
cli := &http.Client{
|
||||
Timeout: time.Second,
|
||||
}
|
||||
|
||||
do := func(req *http.Request, status int) *http.Response {
|
||||
t.Helper()
|
||||
req.Header.Set("X-API-Key", testAPIKey)
|
||||
resp, err := cli.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp.StatusCode != status {
|
||||
t.Errorf("Expected status %v, got %v", status, resp.StatusCode)
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
mod := func(method, path string, data interface{}) {
|
||||
t.Helper()
|
||||
bs, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
req, _ := http.NewRequest(method, baseURL+path, bytes.NewReader(bs))
|
||||
do(req, http.StatusOK).Body.Close()
|
||||
}
|
||||
|
||||
get := func(path string) *http.Response {
|
||||
t.Helper()
|
||||
req, _ := http.NewRequest(http.MethodGet, baseURL+path, nil)
|
||||
return do(req, http.StatusOK)
|
||||
}
|
||||
|
||||
dev1Path := "/rest/config/devices/" + dev1.String()
|
||||
|
||||
// Create device
|
||||
mod(http.MethodPut, "/rest/config/devices", []config.DeviceConfiguration{{DeviceID: dev1}})
|
||||
|
||||
// Check its there
|
||||
get(dev1Path).Body.Close()
|
||||
|
||||
// Modify just a single attribute
|
||||
mod(http.MethodPatch, dev1Path, map[string]bool{"Paused": true})
|
||||
|
||||
// Check that attribute
|
||||
resp := get(dev1Path)
|
||||
var dev config.DeviceConfiguration
|
||||
if err := unmarshalTo(resp.Body, &dev); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !dev.Paused {
|
||||
t.Error("Expected device to be paused")
|
||||
}
|
||||
|
||||
folder2Path := "/rest/config/folders/folder2"
|
||||
|
||||
// Create a folder and add another
|
||||
mod(http.MethodPut, "/rest/config/folders", []config.FolderConfiguration{{ID: "folder1", Path: "folder1"}})
|
||||
mod(http.MethodPut, folder2Path, config.FolderConfiguration{ID: "folder2", Path: "folder2"})
|
||||
|
||||
// Check they are there
|
||||
get("/rest/config/folders/folder1").Body.Close()
|
||||
get(folder2Path).Body.Close()
|
||||
|
||||
// Modify just a single attribute
|
||||
mod(http.MethodPatch, folder2Path, map[string]bool{"Paused": true})
|
||||
|
||||
// Check that attribute
|
||||
resp = get(folder2Path)
|
||||
var folder config.FolderConfiguration
|
||||
if err := unmarshalTo(resp.Body, &folder); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !dev.Paused {
|
||||
t.Error("Expected folder to be paused")
|
||||
}
|
||||
|
||||
// Delete folder2
|
||||
req, _ := http.NewRequest(http.MethodDelete, baseURL+folder2Path, nil)
|
||||
do(req, http.StatusOK)
|
||||
|
||||
// Check folder1 is still there and folder2 gone
|
||||
get("/rest/config/folders/folder1").Body.Close()
|
||||
req, _ = http.NewRequest(http.MethodGet, baseURL+folder2Path, nil)
|
||||
do(req, http.StatusNotFound)
|
||||
|
||||
mod(http.MethodPatch, "/rest/config/options", map[string]int{"maxSendKbps": 50})
|
||||
resp = get("/rest/config/options")
|
||||
var opts config.OptionsConfiguration
|
||||
if err := unmarshalTo(resp.Body, &opts); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if opts.MaxSendKbps != 50 {
|
||||
t.Error("Exepcted 50 for MaxSendKbps, got", opts.MaxSendKbps)
|
||||
}
|
||||
}
|
||||
|
||||
func equalStrings(a, b []string) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
|
||||
382
lib/api/confighandler.go
Normal file
382
lib/api/confighandler.go
Normal file
@@ -0,0 +1,382 @@
|
||||
// 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/.
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
)
|
||||
|
||||
type configMuxBuilder struct {
|
||||
*httprouter.Router
|
||||
id protocol.DeviceID
|
||||
cfg config.Wrapper
|
||||
mut sync.Mutex
|
||||
}
|
||||
|
||||
func (c *configMuxBuilder) registerConfig(path string) {
|
||||
c.HandlerFunc(http.MethodGet, path, func(w http.ResponseWriter, _ *http.Request) {
|
||||
sendJSON(w, c.cfg.RawCopy())
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPut, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.adjustConfig(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *configMuxBuilder) registerConfigDeprecated(path string) {
|
||||
c.HandlerFunc(http.MethodGet, path, func(w http.ResponseWriter, _ *http.Request) {
|
||||
sendJSON(w, c.cfg.RawCopy())
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPost, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.adjustConfig(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *configMuxBuilder) registerConfigInsync(path string) {
|
||||
c.HandlerFunc(http.MethodGet, path, func(w http.ResponseWriter, _ *http.Request) {
|
||||
sendJSON(w, map[string]bool{"configInSync": !c.cfg.RequiresRestart()})
|
||||
})
|
||||
}
|
||||
|
||||
func (c *configMuxBuilder) registerFolders(path string) {
|
||||
c.HandlerFunc(http.MethodGet, path, func(w http.ResponseWriter, _ *http.Request) {
|
||||
sendJSON(w, c.cfg.FolderList())
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPut, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.mut.Lock()
|
||||
defer c.mut.Unlock()
|
||||
var folders []config.FolderConfiguration
|
||||
if err := unmarshalTo(r.Body, &folders); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
waiter, err := c.cfg.SetFolders(folders)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
c.finish(w, waiter)
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPost, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.mut.Lock()
|
||||
defer c.mut.Unlock()
|
||||
var folder config.FolderConfiguration
|
||||
if err := unmarshalTo(r.Body, &folder); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
waiter, err := c.cfg.SetFolder(folder)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
c.finish(w, waiter)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *configMuxBuilder) registerDevices(path string) {
|
||||
c.HandlerFunc(http.MethodGet, path, func(w http.ResponseWriter, _ *http.Request) {
|
||||
sendJSON(w, c.cfg.DeviceList())
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPut, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.mut.Lock()
|
||||
defer c.mut.Unlock()
|
||||
var devices []config.DeviceConfiguration
|
||||
if err := unmarshalTo(r.Body, &devices); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
waiter, err := c.cfg.SetDevices(devices)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
c.finish(w, waiter)
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPost, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.mut.Lock()
|
||||
defer c.mut.Unlock()
|
||||
var device config.DeviceConfiguration
|
||||
if err := unmarshalTo(r.Body, &device); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
waiter, err := c.cfg.SetDevice(device)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
c.finish(w, waiter)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *configMuxBuilder) registerFolder(path string) {
|
||||
c.Handle(http.MethodGet, path, func(w http.ResponseWriter, _ *http.Request, p httprouter.Params) {
|
||||
folder, ok := c.cfg.Folder(p.ByName("id"))
|
||||
if !ok {
|
||||
http.Error(w, "No folder with given ID", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
sendJSON(w, folder)
|
||||
})
|
||||
|
||||
c.Handle(http.MethodPut, path, func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
c.adjustFolder(w, r, config.FolderConfiguration{})
|
||||
})
|
||||
|
||||
c.Handle(http.MethodPatch, path, func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
folder, ok := c.cfg.Folder(p.ByName("id"))
|
||||
if !ok {
|
||||
http.Error(w, "No folder with given ID", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
c.adjustFolder(w, r, folder)
|
||||
})
|
||||
|
||||
c.Handle(http.MethodDelete, path, func(w http.ResponseWriter, _ *http.Request, p httprouter.Params) {
|
||||
c.mut.Lock()
|
||||
defer c.mut.Unlock()
|
||||
waiter, err := c.cfg.RemoveFolder(p.ByName("id"))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
c.finish(w, waiter)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *configMuxBuilder) registerDevice(path string) {
|
||||
deviceFromParams := func(w http.ResponseWriter, p httprouter.Params) (config.DeviceConfiguration, bool) {
|
||||
id, err := protocol.DeviceIDFromString(p.ByName("id"))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return config.DeviceConfiguration{}, false
|
||||
}
|
||||
device, ok := c.cfg.Device(id)
|
||||
if !ok {
|
||||
http.Error(w, "No device with given ID", http.StatusNotFound)
|
||||
return config.DeviceConfiguration{}, false
|
||||
}
|
||||
return device, true
|
||||
}
|
||||
|
||||
c.Handle(http.MethodGet, path, func(w http.ResponseWriter, _ *http.Request, p httprouter.Params) {
|
||||
if device, ok := deviceFromParams(w, p); ok {
|
||||
sendJSON(w, device)
|
||||
}
|
||||
})
|
||||
|
||||
c.Handle(http.MethodPut, path, func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
c.adjustDevice(w, r, config.DeviceConfiguration{})
|
||||
})
|
||||
|
||||
c.Handle(http.MethodPatch, path, func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
if device, ok := deviceFromParams(w, p); ok {
|
||||
c.adjustDevice(w, r, device)
|
||||
}
|
||||
})
|
||||
|
||||
c.Handle(http.MethodDelete, path, func(w http.ResponseWriter, _ *http.Request, p httprouter.Params) {
|
||||
c.mut.Lock()
|
||||
defer c.mut.Unlock()
|
||||
id, err := protocol.DeviceIDFromString(p.ByName("id"))
|
||||
waiter, err := c.cfg.RemoveDevice(id)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
c.finish(w, waiter)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *configMuxBuilder) registerOptions(path string) {
|
||||
c.HandlerFunc(http.MethodGet, path, func(w http.ResponseWriter, _ *http.Request) {
|
||||
sendJSON(w, c.cfg.Options())
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPut, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.adjustOptions(w, r, config.OptionsConfiguration{})
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPatch, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.adjustOptions(w, r, c.cfg.Options())
|
||||
})
|
||||
}
|
||||
|
||||
func (c *configMuxBuilder) registerLDAP(path string) {
|
||||
c.HandlerFunc(http.MethodGet, path, func(w http.ResponseWriter, _ *http.Request) {
|
||||
sendJSON(w, c.cfg.LDAP())
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPut, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.adjustLDAP(w, r, config.LDAPConfiguration{})
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPatch, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.adjustLDAP(w, r, c.cfg.LDAP())
|
||||
})
|
||||
}
|
||||
|
||||
func (c *configMuxBuilder) registerGUI(path string) {
|
||||
c.HandlerFunc(http.MethodGet, path, func(w http.ResponseWriter, _ *http.Request) {
|
||||
sendJSON(w, c.cfg.GUI())
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPut, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.adjustGUI(w, r, config.GUIConfiguration{})
|
||||
})
|
||||
|
||||
c.HandlerFunc(http.MethodPatch, path, func(w http.ResponseWriter, r *http.Request) {
|
||||
c.adjustGUI(w, r, c.cfg.GUI())
|
||||
})
|
||||
}
|
||||
|
||||
func (c *configMuxBuilder) adjustConfig(w http.ResponseWriter, r *http.Request) {
|
||||
c.mut.Lock()
|
||||
defer c.mut.Unlock()
|
||||
cfg, err := config.ReadJSON(r.Body, c.id)
|
||||
r.Body.Close()
|
||||
if err != nil {
|
||||
l.Warnln("Decoding posted config:", err)
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if cfg.GUI.Password, err = checkGUIPassword(c.cfg.GUI().Password, cfg.GUI.Password); err != nil {
|
||||
l.Warnln("bcrypting password:", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
waiter, err := c.cfg.Replace(cfg)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
c.finish(w, waiter)
|
||||
}
|
||||
|
||||
func (c *configMuxBuilder) adjustFolder(w http.ResponseWriter, r *http.Request, folder config.FolderConfiguration) {
|
||||
c.mut.Lock()
|
||||
defer c.mut.Unlock()
|
||||
if err := unmarshalTo(r.Body, &folder); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
waiter, err := c.cfg.SetFolder(folder)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
c.finish(w, waiter)
|
||||
}
|
||||
|
||||
func (c *configMuxBuilder) adjustDevice(w http.ResponseWriter, r *http.Request, device config.DeviceConfiguration) {
|
||||
c.mut.Lock()
|
||||
defer c.mut.Unlock()
|
||||
if err := unmarshalTo(r.Body, &device); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
waiter, err := c.cfg.SetDevice(device)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
c.finish(w, waiter)
|
||||
}
|
||||
|
||||
func (c *configMuxBuilder) adjustOptions(w http.ResponseWriter, r *http.Request, opts config.OptionsConfiguration) {
|
||||
c.mut.Lock()
|
||||
defer c.mut.Unlock()
|
||||
if err := unmarshalTo(r.Body, &opts); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
waiter, err := c.cfg.SetOptions(opts)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
c.finish(w, waiter)
|
||||
}
|
||||
|
||||
func (c *configMuxBuilder) adjustGUI(w http.ResponseWriter, r *http.Request, gui config.GUIConfiguration) {
|
||||
c.mut.Lock()
|
||||
defer c.mut.Unlock()
|
||||
oldPassword := gui.Password
|
||||
err := unmarshalTo(r.Body, &gui)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if gui.Password, err = checkGUIPassword(oldPassword, gui.Password); err != nil {
|
||||
l.Warnln("bcrypting password:", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
waiter, err := c.cfg.SetGUI(gui)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
c.finish(w, waiter)
|
||||
}
|
||||
|
||||
func (c *configMuxBuilder) adjustLDAP(w http.ResponseWriter, r *http.Request, ldap config.LDAPConfiguration) {
|
||||
c.mut.Lock()
|
||||
defer c.mut.Unlock()
|
||||
if err := unmarshalTo(r.Body, &ldap); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
waiter, err := c.cfg.SetLDAP(ldap)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
c.finish(w, waiter)
|
||||
}
|
||||
|
||||
// Unmarshals the content of the given body and stores it in to (i.e. to must be a pointer).
|
||||
func unmarshalTo(body io.ReadCloser, to interface{}) error {
|
||||
bs, err := ioutil.ReadAll(body)
|
||||
body.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(bs, to)
|
||||
}
|
||||
|
||||
func checkGUIPassword(oldPassword, newPassword string) (string, error) {
|
||||
if newPassword == oldPassword {
|
||||
return newPassword, nil
|
||||
}
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(newPassword), 0)
|
||||
return string(hash), err
|
||||
}
|
||||
|
||||
func (c *configMuxBuilder) finish(w http.ResponseWriter, waiter config.Waiter) {
|
||||
waiter.Wait()
|
||||
if err := c.cfg.Save(); err != nil {
|
||||
l.Warnln("Saving config:", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,10 @@ func (c *mockedConfig) LDAP() config.LDAPConfiguration {
|
||||
return config.LDAPConfiguration{}
|
||||
}
|
||||
|
||||
func (c *mockedConfig) SetLDAP(config.LDAPConfiguration) (config.Waiter, error) {
|
||||
return noopWaiter{}, nil
|
||||
}
|
||||
|
||||
func (c *mockedConfig) RawCopy() config.Configuration {
|
||||
cfg := config.Configuration{}
|
||||
util.SetDefaults(&cfg.Options)
|
||||
@@ -54,6 +58,10 @@ func (c *mockedConfig) Devices() map[protocol.DeviceID]config.DeviceConfiguratio
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *mockedConfig) DeviceList() []config.DeviceConfiguration {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *mockedConfig) SetDevice(config.DeviceConfiguration) (config.Waiter, error) {
|
||||
return noopWaiter{}, nil
|
||||
}
|
||||
@@ -102,6 +110,14 @@ func (c *mockedConfig) SetFolders(folders []config.FolderConfiguration) (config.
|
||||
return noopWaiter{}, nil
|
||||
}
|
||||
|
||||
func (c *mockedConfig) RemoveFolder(id string) (config.Waiter, error) {
|
||||
return noopWaiter{}, nil
|
||||
}
|
||||
|
||||
func (c *mockedConfig) FolderPasswords(device protocol.DeviceID) map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *mockedConfig) Device(id protocol.DeviceID) (config.DeviceConfiguration, bool) {
|
||||
return config.DeviceConfiguration{}, false
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ func (m *mockedModel) IndexUpdate(deviceID protocol.DeviceID, folder string, fil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockedModel) Request(deviceID protocol.DeviceID, folder, name string, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (protocol.RequestResponse, error) {
|
||||
func (m *mockedModel) Request(deviceID protocol.DeviceID, folder, name string, blockNo, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (protocol.RequestResponse, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -149,9 +149,9 @@ func (m *mockedModel) DownloadProgress(deviceID protocol.DeviceID, folder string
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockedModel) AddConnection(conn connections.Connection, hello protocol.HelloResult) {}
|
||||
func (m *mockedModel) AddConnection(conn connections.Connection, hello protocol.Hello) {}
|
||||
|
||||
func (m *mockedModel) OnHello(protocol.DeviceID, net.Addr, protocol.HelloResult) error {
|
||||
func (m *mockedModel) OnHello(protocol.DeviceID, net.Addr, protocol.Hello) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ var (
|
||||
"STHASHING",
|
||||
"STNORESTART",
|
||||
"STNOUPGRADE",
|
||||
"USE_BADGER",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ func init() {
|
||||
func init() { proto.RegisterFile("lib/config/authmode.proto", fileDescriptor_8e30b562e1bcea1e) }
|
||||
|
||||
var fileDescriptor_8e30b562e1bcea1e = []byte{
|
||||
// 230 bytes of a gzipped FileDescriptorProto
|
||||
// 234 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcc, 0xc9, 0x4c, 0xd2,
|
||||
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x4f, 0x2c, 0x2d, 0xc9, 0xc8, 0xcd, 0x4f, 0x49, 0xd5,
|
||||
0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x08, 0x4b, 0x29, 0x17, 0xa5, 0x16, 0xe4, 0x17,
|
||||
@@ -60,10 +60,10 @@ var fileDescriptor_8e30b562e1bcea1e = []byte{
|
||||
0x8d, 0x0f, 0x0e, 0x71, 0x0c, 0xf1, 0x74, 0x16, 0x60, 0x90, 0x12, 0xea, 0x9a, 0xab, 0xc0, 0x07,
|
||||
0x53, 0x13, 0x5c, 0x92, 0x58, 0x92, 0x99, 0x2c, 0x64, 0xc2, 0xc5, 0x87, 0x50, 0xe9, 0xe3, 0xe2,
|
||||
0x18, 0x20, 0xc0, 0x28, 0xa5, 0xd0, 0x35, 0x57, 0x81, 0x07, 0xa6, 0x0e, 0x24, 0x76, 0xa9, 0x4f,
|
||||
0x15, 0x85, 0x2f, 0xc5, 0xb2, 0x62, 0x89, 0x1c, 0x83, 0x93, 0xfb, 0x89, 0x87, 0x72, 0x0c, 0x17,
|
||||
0x1e, 0xca, 0x31, 0xbc, 0x78, 0x24, 0xc7, 0x30, 0xe1, 0xb1, 0x1c, 0xc3, 0x82, 0xc7, 0x72, 0x8c,
|
||||
0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0xa5, 0x99, 0x9e, 0x59, 0x92, 0x51, 0x9a,
|
||||
0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x5f, 0x5c, 0x99, 0x97, 0x5c, 0x92, 0x91, 0x99, 0x97, 0x8e, 0xc4,
|
||||
0x42, 0x84, 0x40, 0x12, 0x1b, 0xd8, 0x07, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x04, 0x8c,
|
||||
0xb9, 0xb3, 0x16, 0x01, 0x00, 0x00,
|
||||
0x15, 0x85, 0x2f, 0xc5, 0xb2, 0x62, 0x89, 0x1c, 0x83, 0x93, 0xf7, 0x89, 0x87, 0x72, 0x0c, 0x17,
|
||||
0x1e, 0xca, 0x31, 0x9c, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c,
|
||||
0x0b, 0x1e, 0xcb, 0x31, 0x5e, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x66, 0x7a,
|
||||
0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x71, 0x65, 0x5e, 0x72, 0x49, 0x46,
|
||||
0x66, 0x5e, 0x3a, 0x12, 0x0b, 0x11, 0x0a, 0x49, 0x6c, 0x60, 0x5f, 0x18, 0x03, 0x02, 0x00, 0x00,
|
||||
0xff, 0xff, 0x48, 0x80, 0x1f, 0x0c, 0x1a, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ package config
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
@@ -51,20 +52,22 @@ func init() {
|
||||
func init() { proto.RegisterFile("lib/config/blockpullorder.proto", fileDescriptor_3c46a5289006da6c) }
|
||||
|
||||
var fileDescriptor_3c46a5289006da6c = []byte{
|
||||
// 237 bytes of a gzipped FileDescriptorProto
|
||||
// 271 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcf, 0xc9, 0x4c, 0xd2,
|
||||
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x4f, 0xca, 0xc9, 0x4f, 0xce, 0x2e, 0x28, 0xcd, 0xc9,
|
||||
0xc9, 0x2f, 0x4a, 0x49, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x48, 0x6a,
|
||||
0xed, 0x61, 0xe4, 0xe2, 0x73, 0x02, 0x29, 0x08, 0x28, 0xcd, 0xc9, 0xf1, 0x07, 0x29, 0x10, 0xb2,
|
||||
0xe4, 0x92, 0x74, 0xf2, 0xf1, 0x77, 0xf6, 0x8e, 0x0f, 0x08, 0xf5, 0xf1, 0x89, 0xf7, 0x0f, 0x72,
|
||||
0x71, 0x0d, 0x8a, 0x0f, 0x0e, 0x71, 0xf4, 0x73, 0x71, 0x0c, 0x72, 0x11, 0x60, 0x90, 0x92, 0xea,
|
||||
0x9a, 0xab, 0x20, 0x86, 0xaa, 0x25, 0xb8, 0x24, 0x31, 0x2f, 0x25, 0xb1, 0x28, 0x45, 0xc8, 0x94,
|
||||
0x4b, 0x1c, 0x43, 0x6b, 0x90, 0xa3, 0x9f, 0x8b, 0xbf, 0xaf, 0x00, 0xa3, 0x94, 0x44, 0xd7, 0x5c,
|
||||
0x05, 0x11, 0x54, 0x8d, 0x41, 0x89, 0x79, 0x29, 0xf9, 0xb9, 0x42, 0x16, 0x58, 0x6c, 0xf4, 0xf4,
|
||||
0x83, 0x30, 0x04, 0x98, 0xa4, 0x24, 0xbb, 0xe6, 0x2a, 0x88, 0xa2, 0x6a, 0xf4, 0xcc, 0x03, 0x53,
|
||||
0x4e, 0xee, 0x27, 0x1e, 0xca, 0x31, 0x5c, 0x78, 0x28, 0xc7, 0xf0, 0xe2, 0x91, 0x1c, 0xc3, 0x84,
|
||||
0xc7, 0x72, 0x0c, 0x0b, 0x1e, 0xcb, 0x31, 0x5e, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43,
|
||||
0x94, 0x66, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x71, 0x65, 0x5e,
|
||||
0x72, 0x49, 0x46, 0x66, 0x5e, 0x3a, 0x12, 0x0b, 0x11, 0x48, 0x49, 0x6c, 0xe0, 0x60, 0x31, 0x06,
|
||||
0x04, 0x00, 0x00, 0xff, 0xff, 0x46, 0xfd, 0xeb, 0xcf, 0x39, 0x01, 0x00, 0x00,
|
||||
0xc9, 0x2f, 0x4a, 0x49, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x48, 0x4a,
|
||||
0x29, 0x17, 0xa5, 0x16, 0xe4, 0x17, 0xeb, 0x83, 0x05, 0x93, 0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3,
|
||||
0xf3, 0xc1, 0x1c, 0x30, 0x0b, 0xa2, 0x58, 0xeb, 0x10, 0x23, 0x17, 0x9f, 0x13, 0xc8, 0x94, 0x80,
|
||||
0xd2, 0x9c, 0x1c, 0x7f, 0x90, 0x29, 0x42, 0x96, 0x5c, 0x92, 0x4e, 0x3e, 0xfe, 0xce, 0xde, 0xf1,
|
||||
0x01, 0xa1, 0x3e, 0x3e, 0xf1, 0xfe, 0x41, 0x2e, 0xae, 0x41, 0xf1, 0xc1, 0x21, 0x8e, 0x7e, 0x2e,
|
||||
0x8e, 0x41, 0x2e, 0x02, 0x0c, 0x52, 0x52, 0x5d, 0x73, 0x15, 0xc4, 0x50, 0xb5, 0x04, 0x97, 0x24,
|
||||
0xe6, 0xa5, 0x24, 0x16, 0xa5, 0x08, 0x99, 0x72, 0x89, 0x63, 0x68, 0x0d, 0x72, 0xf4, 0x73, 0xf1,
|
||||
0xf7, 0x15, 0x60, 0x94, 0x92, 0xe8, 0x9a, 0xab, 0x20, 0x82, 0xaa, 0x31, 0x28, 0x31, 0x2f, 0x25,
|
||||
0x3f, 0x57, 0xc8, 0x02, 0x8b, 0x8d, 0x9e, 0x7e, 0x10, 0x86, 0x00, 0x93, 0x94, 0x64, 0xd7, 0x5c,
|
||||
0x05, 0x51, 0x54, 0x8d, 0x9e, 0x79, 0x60, 0x4a, 0x8a, 0x65, 0xc5, 0x12, 0x39, 0x06, 0x27, 0xef,
|
||||
0x13, 0x0f, 0xe5, 0x18, 0x2e, 0x3c, 0x94, 0x63, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39,
|
||||
0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x16, 0x3c, 0x96, 0x63, 0xbc, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63,
|
||||
0x39, 0x86, 0x28, 0xcd, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0xfd, 0xe2,
|
||||
0xca, 0xbc, 0xe4, 0x92, 0x8c, 0xcc, 0xbc, 0x74, 0x24, 0x16, 0x22, 0x4c, 0x93, 0xd8, 0xc0, 0x01,
|
||||
0x63, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x8c, 0x0c, 0xb7, 0x46, 0x68, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
@@ -304,7 +304,9 @@ func (cfg *Configuration) clean() error {
|
||||
}
|
||||
|
||||
// Upgrade configuration versions as appropriate
|
||||
migrationsMut.Lock()
|
||||
migrations.apply(cfg)
|
||||
migrationsMut.Unlock()
|
||||
|
||||
// Build a list of available devices
|
||||
existingDevices := make(map[protocol.DeviceID]bool)
|
||||
@@ -417,6 +419,9 @@ nextPendingDevice:
|
||||
}
|
||||
}
|
||||
}
|
||||
if cfg.Options.FeatureFlags == nil {
|
||||
cfg.Options.FeatureFlags = []string{}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -430,6 +435,22 @@ func (cfg *Configuration) DeviceMap() map[protocol.DeviceID]DeviceConfiguration
|
||||
return m
|
||||
}
|
||||
|
||||
// FolderPasswords returns the folder passwords set for this device, for
|
||||
// folders that have an encryption password set.
|
||||
func (cfg Configuration) FolderPasswords(device protocol.DeviceID) map[string]string {
|
||||
res := make(map[string]string, len(cfg.Folders))
|
||||
nextFolder:
|
||||
for _, folder := range cfg.Folders {
|
||||
for _, dev := range folder.Devices {
|
||||
if dev.DeviceID == device && dev.EncryptionPassword != "" {
|
||||
res[folder.ID] = dev.EncryptionPassword
|
||||
continue nextFolder
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func ensureDevicePresent(devices []FolderDeviceConfiguration, myID protocol.DeviceID) []FolderDeviceConfiguration {
|
||||
for _, device := range devices {
|
||||
if device.DeviceID.Equals(myID) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
fmt "fmt"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
_ "github.com/syncthing/syncthing/proto/ext"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
@@ -40,16 +41,25 @@ func (*Configuration) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_baadf209193dc627, []int{0}
|
||||
}
|
||||
func (m *Configuration) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Configuration.Unmarshal(m, b)
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *Configuration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Configuration.Marshal(b, m, deterministic)
|
||||
if deterministic {
|
||||
return xxx_messageInfo_Configuration.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *Configuration) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Configuration.Merge(m, src)
|
||||
}
|
||||
func (m *Configuration) XXX_Size() int {
|
||||
return xxx_messageInfo_Configuration.Size(m)
|
||||
return m.ProtoSize()
|
||||
}
|
||||
func (m *Configuration) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Configuration.DiscardUnknown(m)
|
||||
@@ -64,43 +74,169 @@ func init() {
|
||||
func init() { proto.RegisterFile("lib/config/config.proto", fileDescriptor_baadf209193dc627) }
|
||||
|
||||
var fileDescriptor_baadf209193dc627 = []byte{
|
||||
// 544 bytes of a gzipped FileDescriptorProto
|
||||
// 547 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x93, 0x4f, 0x8b, 0xd3, 0x40,
|
||||
0x18, 0xc6, 0x53, 0xdb, 0x6d, 0xdd, 0xec, 0x3f, 0xc8, 0x8a, 0xa6, 0x2a, 0x99, 0x3a, 0x54, 0xa9,
|
||||
0xa2, 0x5d, 0x58, 0x2f, 0xe2, 0xcd, 0x5a, 0x2c, 0x05, 0x41, 0x19, 0x58, 0x51, 0x2f, 0xd2, 0x36,
|
||||
0xb3, 0xe9, 0x40, 0x3b, 0x53, 0x92, 0xb4, 0xac, 0xdf, 0x42, 0xfc, 0x04, 0x5e, 0xfd, 0x06, 0x7e,
|
||||
0x84, 0xbd, 0xb5, 0x47, 0x4f, 0x03, 0xbb, 0xbd, 0x48, 0x8e, 0x39, 0x7a, 0x92, 0xf9, 0xd7, 0x4d,
|
||||
0x24, 0x7a, 0x6a, 0xde, 0xf7, 0x79, 0x9e, 0xdf, 0xfb, 0xf2, 0x36, 0xb1, 0x6f, 0x4d, 0xc8, 0xf0,
|
||||
0x68, 0xc4, 0xe8, 0x29, 0x09, 0xf4, 0x4f, 0x7b, 0x16, 0xb2, 0x98, 0x39, 0x55, 0x55, 0xdd, 0x6e,
|
||||
0x66, 0x0c, 0xa7, 0x6c, 0xe2, 0xe3, 0x50, 0x15, 0xf3, 0x70, 0x10, 0x13, 0x46, 0x95, 0x3b, 0xe7,
|
||||
0xf2, 0xf1, 0x82, 0x8c, 0x70, 0x91, 0xeb, 0x5e, 0xc6, 0x15, 0xcc, 0x49, 0x91, 0x05, 0x66, 0x2c,
|
||||
0x13, 0x7f, 0x30, 0x2b, 0xf2, 0xdc, 0xcf, 0x78, 0xd8, 0x4c, 0x08, 0x51, 0x91, 0xad, 0x9e, 0xb5,
|
||||
0x0d, 0x23, 0x1c, 0x2e, 0xb0, 0xaf, 0xa5, 0x6d, 0x7c, 0x16, 0xab, 0x47, 0xf8, 0xa3, 0x6a, 0xef,
|
||||
0xbd, 0xcc, 0xa6, 0x1d, 0x64, 0xd7, 0x16, 0x38, 0x8c, 0x08, 0xa3, 0x6e, 0xa9, 0x51, 0x6a, 0x6d,
|
||||
0x75, 0x9e, 0x25, 0x1c, 0x98, 0x56, 0xca, 0x81, 0x73, 0x36, 0x9d, 0x3c, 0x87, 0xba, 0x7e, 0x3c,
|
||||
0x88, 0xe3, 0x10, 0xfe, 0xe6, 0xa0, 0x4c, 0x68, 0x9c, 0x2c, 0x9b, 0xbb, 0xd9, 0x3e, 0x32, 0x29,
|
||||
0xe7, 0x9d, 0x5d, 0x53, 0xc7, 0x8b, 0xdc, 0x6b, 0x8d, 0x72, 0x6b, 0xe7, 0xf8, 0x4e, 0x5b, 0x5f,
|
||||
0xfb, 0x95, 0x6c, 0xe7, 0x36, 0xe8, 0x80, 0x73, 0x0e, 0x2c, 0x31, 0x54, 0x67, 0x52, 0x0e, 0x76,
|
||||
0xe5, 0x50, 0x55, 0x43, 0x64, 0x04, 0xc1, 0x55, 0xe7, 0x8e, 0xdc, 0x72, 0x9e, 0xdb, 0x95, 0xed,
|
||||
0x7f, 0x70, 0x75, 0x66, 0xc3, 0x55, 0x35, 0x44, 0x46, 0x70, 0x90, 0x5d, 0x0e, 0xe6, 0xc4, 0xad,
|
||||
0x34, 0x4a, 0xad, 0x9d, 0x63, 0xd7, 0x30, 0x7b, 0x27, 0xfd, 0x3c, 0xf0, 0x81, 0x00, 0x5e, 0x72,
|
||||
0x50, 0xee, 0x9d, 0xf4, 0x13, 0x0e, 0x44, 0x26, 0xe5, 0x60, 0x5b, 0x32, 0x83, 0x39, 0x81, 0x5f,
|
||||
0x57, 0x4d, 0x21, 0x21, 0x21, 0x38, 0x1f, 0xec, 0x8a, 0xf8, 0x47, 0xdd, 0x2d, 0x09, 0xad, 0x1b,
|
||||
0xe8, 0xeb, 0xee, 0x8b, 0xb7, 0x79, 0xea, 0x23, 0x4d, 0xad, 0x08, 0x29, 0xe1, 0x40, 0xc6, 0x52,
|
||||
0x0e, 0x6c, 0xc9, 0x15, 0x85, 0x00, 0x4b, 0x15, 0x49, 0xcd, 0x79, 0x6f, 0xd7, 0xf4, 0x8b, 0xe0,
|
||||
0x56, 0x25, 0xfd, 0xae, 0xa1, 0xbf, 0x51, 0xed, 0xfc, 0x80, 0x86, 0xb9, 0x83, 0x0e, 0xa5, 0x1c,
|
||||
0xec, 0x49, 0xb6, 0xae, 0x21, 0x32, 0x8a, 0xf3, 0xbd, 0x64, 0x1f, 0x90, 0x80, 0xb2, 0x10, 0xfb,
|
||||
0x9f, 0xcc, 0xa5, 0x6b, 0xf2, 0xd2, 0x37, 0x37, 0x23, 0xf4, 0xbb, 0xa5, 0x2e, 0xde, 0x19, 0x6b,
|
||||
0xf8, 0x8d, 0x10, 0x4f, 0x59, 0x8c, 0xfb, 0x2a, 0xdc, 0xdd, 0x5c, 0xbc, 0x2e, 0x27, 0x15, 0x88,
|
||||
0x30, 0x59, 0x36, 0x0f, 0x0b, 0xfa, 0xe9, 0xb2, 0x59, 0xc8, 0x42, 0xfb, 0x24, 0x57, 0x3b, 0xd4,
|
||||
0x3e, 0x98, 0x61, 0xea, 0x13, 0x1a, 0x6c, 0x56, 0xbd, 0xfe, 0xdf, 0x55, 0x9f, 0xe8, 0x55, 0xf7,
|
||||
0x75, 0xec, 0x6a, 0xc9, 0x43, 0xb9, 0x64, 0xae, 0x0d, 0xd1, 0x5f, 0xb6, 0x4e, 0xef, 0xfc, 0xc2,
|
||||
0xb3, 0x56, 0x17, 0x9e, 0xf5, 0xeb, 0xd2, 0xb3, 0xbe, 0xac, 0x3d, 0xeb, 0xdb, 0xda, 0x2b, 0xad,
|
||||
0xd6, 0x9e, 0xf5, 0x73, 0xed, 0x59, 0x1f, 0x1f, 0x06, 0x24, 0x1e, 0xcf, 0x87, 0xed, 0x11, 0x9b,
|
||||
0x1e, 0x45, 0x9f, 0xe9, 0x28, 0x1e, 0x13, 0x1a, 0x64, 0x9e, 0xae, 0xbe, 0xce, 0x61, 0x55, 0x7e,
|
||||
0x8a, 0x4f, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0xce, 0xc5, 0x80, 0x7a, 0x8d, 0x04, 0x00, 0x00,
|
||||
0x18, 0xc6, 0x13, 0xbb, 0xdb, 0xba, 0xd9, 0x7f, 0x90, 0x15, 0x4d, 0x55, 0x32, 0x75, 0xa8, 0x52,
|
||||
0x45, 0xbb, 0xb0, 0x5e, 0xc4, 0x9b, 0xb5, 0xb8, 0x14, 0x05, 0x65, 0x60, 0x45, 0xbd, 0x48, 0xdb,
|
||||
0xcc, 0xa6, 0x03, 0xed, 0x4c, 0x49, 0xd2, 0xb2, 0x7e, 0x0b, 0xf1, 0x13, 0x78, 0xf5, 0x1b, 0xf8,
|
||||
0x11, 0x7a, 0x6b, 0x8f, 0x9e, 0x06, 0xb6, 0xbd, 0xf5, 0x98, 0xa3, 0x27, 0x99, 0x7f, 0xdd, 0x44,
|
||||
0xa2, 0xa7, 0xe6, 0x7d, 0x9f, 0xe7, 0xf9, 0xbd, 0x2f, 0x6f, 0x13, 0xe7, 0xd6, 0x90, 0xf4, 0x8e,
|
||||
0xfb, 0x8c, 0x9e, 0x93, 0x50, 0xff, 0x34, 0xc7, 0x11, 0x4b, 0x98, 0x5b, 0x56, 0xd5, 0xed, 0x7a,
|
||||
0xc6, 0x70, 0xce, 0x86, 0x01, 0x8e, 0x54, 0x31, 0x89, 0xba, 0x09, 0x61, 0x54, 0xb9, 0x73, 0xae,
|
||||
0x00, 0x4f, 0x49, 0x1f, 0x17, 0xb9, 0xee, 0x65, 0x5c, 0xe1, 0x84, 0x14, 0x59, 0x60, 0xc6, 0x32,
|
||||
0x0c, 0xba, 0xe3, 0x22, 0xcf, 0xfd, 0x8c, 0x87, 0x8d, 0x85, 0x10, 0x17, 0xd9, 0xaa, 0x59, 0x5b,
|
||||
0x2f, 0xc6, 0xd1, 0x14, 0x07, 0x5a, 0xda, 0xc1, 0x17, 0x89, 0x7a, 0x84, 0x3f, 0xcb, 0xce, 0xfe,
|
||||
0xcb, 0x6c, 0xda, 0x45, 0x4e, 0x65, 0x8a, 0xa3, 0x98, 0x30, 0xea, 0xd9, 0x35, 0xbb, 0xb1, 0xdd,
|
||||
0x7a, 0xb6, 0xe6, 0xc0, 0xb4, 0x52, 0x0e, 0xdc, 0x8b, 0xd1, 0xf0, 0x39, 0xd4, 0xf5, 0xe3, 0x6e,
|
||||
0x92, 0x44, 0xf0, 0x37, 0x07, 0x25, 0x42, 0x93, 0xf5, 0xbc, 0xbe, 0x97, 0xed, 0x23, 0x93, 0x72,
|
||||
0xdf, 0x3b, 0x15, 0x75, 0xbc, 0xd8, 0xbb, 0x56, 0x2b, 0x35, 0x76, 0x4f, 0xee, 0x34, 0xf5, 0xb5,
|
||||
0x5f, 0xc9, 0x76, 0x6e, 0x83, 0x16, 0x98, 0x71, 0x60, 0x89, 0xa1, 0x3a, 0x93, 0x72, 0xb0, 0x27,
|
||||
0x87, 0xaa, 0x1a, 0x22, 0x23, 0x08, 0xae, 0x3a, 0x77, 0xec, 0x95, 0xf2, 0xdc, 0xb6, 0x6c, 0xff,
|
||||
0x83, 0xab, 0x33, 0x1b, 0xae, 0xaa, 0x21, 0x32, 0x82, 0x8b, 0x9c, 0x52, 0x38, 0x21, 0xde, 0x56,
|
||||
0xcd, 0x6e, 0xec, 0x9e, 0x78, 0x86, 0x79, 0x7a, 0xd6, 0xc9, 0x03, 0x1f, 0x08, 0xe0, 0x92, 0x83,
|
||||
0xd2, 0xe9, 0x59, 0x67, 0xcd, 0x81, 0xc8, 0xa4, 0x1c, 0xec, 0x48, 0x66, 0x38, 0x21, 0xf0, 0xdb,
|
||||
0xa2, 0x2e, 0x24, 0x24, 0x04, 0xf7, 0xa3, 0xb3, 0x25, 0xfe, 0x51, 0x6f, 0x5b, 0x42, 0xab, 0x06,
|
||||
0xfa, 0xa6, 0xfd, 0xe2, 0x5d, 0x9e, 0xfa, 0x48, 0x53, 0xb7, 0x84, 0xb4, 0xe6, 0x40, 0xc6, 0x52,
|
||||
0x0e, 0x1c, 0xc9, 0x15, 0x85, 0x00, 0x4b, 0x15, 0x49, 0xcd, 0xfd, 0xe0, 0x54, 0xf4, 0x8b, 0xe0,
|
||||
0x95, 0x25, 0xfd, 0xae, 0xa1, 0xbf, 0x55, 0xed, 0xfc, 0x80, 0x9a, 0xb9, 0x83, 0x0e, 0xa5, 0x1c,
|
||||
0xec, 0x4b, 0xb6, 0xae, 0x21, 0x32, 0x8a, 0xfb, 0xc3, 0x76, 0x0e, 0x49, 0x48, 0x59, 0x84, 0x83,
|
||||
0xcf, 0xe6, 0xd2, 0x15, 0x79, 0xe9, 0x9b, 0x9b, 0x11, 0xfa, 0xdd, 0x52, 0x17, 0x6f, 0x0d, 0x34,
|
||||
0xfc, 0x46, 0x84, 0x47, 0x2c, 0xc1, 0x1d, 0x15, 0x6e, 0x6f, 0x2e, 0x5e, 0x95, 0x93, 0x0a, 0x44,
|
||||
0xb8, 0x9e, 0xd7, 0x8f, 0x0a, 0xfa, 0xe9, 0xbc, 0x5e, 0xc8, 0x42, 0x07, 0x24, 0x57, 0xbb, 0xd4,
|
||||
0x39, 0x1c, 0x63, 0x1a, 0x10, 0x1a, 0x6e, 0x56, 0xbd, 0xfe, 0xdf, 0x55, 0x9f, 0xe8, 0x55, 0x0f,
|
||||
0x74, 0xec, 0x6a, 0xc9, 0x23, 0xb9, 0x64, 0xae, 0x0d, 0xd1, 0x5f, 0xb6, 0xd6, 0xeb, 0xd9, 0xa5,
|
||||
0x6f, 0x2d, 0x2e, 0x7d, 0x6b, 0xb6, 0xf4, 0xed, 0xc5, 0xd2, 0xb7, 0xbf, 0xae, 0x7c, 0xeb, 0xfb,
|
||||
0xca, 0xb7, 0x17, 0x2b, 0xdf, 0xfa, 0xb5, 0xf2, 0xad, 0x4f, 0x0f, 0x43, 0x92, 0x0c, 0x26, 0xbd,
|
||||
0x66, 0x9f, 0x8d, 0x8e, 0xe3, 0x2f, 0xb4, 0x9f, 0x0c, 0x08, 0x0d, 0x33, 0x4f, 0x57, 0x5f, 0x68,
|
||||
0xaf, 0x2c, 0x3f, 0xc7, 0xa7, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xcb, 0xcf, 0x98, 0x86, 0x91,
|
||||
0x04, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *Configuration) Marshal() (dAtA []byte, err error) {
|
||||
size := m.ProtoSize()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *Configuration) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.ProtoSize()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *Configuration) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.PendingDevices) > 0 {
|
||||
for iNdEx := len(m.PendingDevices) - 1; iNdEx >= 0; iNdEx-- {
|
||||
{
|
||||
size, err := m.PendingDevices[iNdEx].MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintConfig(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x42
|
||||
}
|
||||
}
|
||||
if len(m.IgnoredDevices) > 0 {
|
||||
for iNdEx := len(m.IgnoredDevices) - 1; iNdEx >= 0; iNdEx-- {
|
||||
{
|
||||
size, err := m.IgnoredDevices[iNdEx].MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintConfig(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x3a
|
||||
}
|
||||
}
|
||||
{
|
||||
size, err := m.Options.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintConfig(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x32
|
||||
{
|
||||
size, err := m.LDAP.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintConfig(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x2a
|
||||
{
|
||||
size, err := m.GUI.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintConfig(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x22
|
||||
if len(m.Devices) > 0 {
|
||||
for iNdEx := len(m.Devices) - 1; iNdEx >= 0; iNdEx-- {
|
||||
{
|
||||
size, err := m.Devices[iNdEx].MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintConfig(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
}
|
||||
if len(m.Folders) > 0 {
|
||||
for iNdEx := len(m.Folders) - 1; iNdEx >= 0; iNdEx-- {
|
||||
{
|
||||
size, err := m.Folders[iNdEx].MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintConfig(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
}
|
||||
if m.Version != 0 {
|
||||
i = encodeVarintConfig(dAtA, i, uint64(m.Version))
|
||||
i--
|
||||
dAtA[i] = 0x8
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintConfig(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovConfig(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *Configuration) ProtoSize() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
@@ -149,3 +285,394 @@ func sovConfig(x uint64) (n int) {
|
||||
func sozConfig(x uint64) (n int) {
|
||||
return sovConfig(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *Configuration) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowConfig
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Configuration: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Configuration: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType)
|
||||
}
|
||||
m.Version = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowConfig
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Version |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Folders", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowConfig
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Folders = append(m.Folders, FolderConfiguration{})
|
||||
if err := m.Folders[len(m.Folders)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Devices", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowConfig
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Devices = append(m.Devices, DeviceConfiguration{})
|
||||
if err := m.Devices[len(m.Devices)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field GUI", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowConfig
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := m.GUI.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 5:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field LDAP", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowConfig
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := m.LDAP.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 6:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowConfig
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := m.Options.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 7:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field IgnoredDevices", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowConfig
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.IgnoredDevices = append(m.IgnoredDevices, ObservedDevice{})
|
||||
if err := m.IgnoredDevices[len(m.IgnoredDevices)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 8:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field PendingDevices", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowConfig
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.PendingDevices = append(m.PendingDevices, ObservedDevice{})
|
||||
if err := m.PendingDevices[len(m.PendingDevices)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipConfig(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthConfig
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipConfig(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowConfig
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowConfig
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowConfig
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthConfig
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupConfig
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthConfig
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthConfig = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowConfig = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupConfig = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
|
||||
@@ -77,6 +77,7 @@ func TestDefaultValues(t *testing.T) {
|
||||
StunKeepaliveMinS: 20,
|
||||
RawStunServers: []string{"default"},
|
||||
AnnounceLANAddresses: true,
|
||||
FeatureFlags: []string{},
|
||||
}
|
||||
|
||||
cfg := New(device1)
|
||||
@@ -129,6 +130,7 @@ func TestDeviceConfig(t *testing.T) {
|
||||
WeakHashThresholdPct: 25,
|
||||
MarkerName: DefaultMarkerName,
|
||||
JunctionsAsDirs: true,
|
||||
MaxConcurrentWrites: maxConcurrentWritesDefault,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -137,7 +139,7 @@ func TestDeviceConfig(t *testing.T) {
|
||||
DeviceID: device1,
|
||||
Name: "node one",
|
||||
Addresses: []string{"tcp://a"},
|
||||
Compression: protocol.CompressMetadata,
|
||||
Compression: protocol.CompressionMetadata,
|
||||
AllowedNetworks: []string{},
|
||||
IgnoredFolders: []ObservedFolder{},
|
||||
PendingFolders: []ObservedFolder{},
|
||||
@@ -146,7 +148,7 @@ func TestDeviceConfig(t *testing.T) {
|
||||
DeviceID: device4,
|
||||
Name: "node two",
|
||||
Addresses: []string{"tcp://b"},
|
||||
Compression: protocol.CompressMetadata,
|
||||
Compression: protocol.CompressionMetadata,
|
||||
AllowedNetworks: []string{},
|
||||
IgnoredFolders: []ObservedFolder{},
|
||||
PendingFolders: []ObservedFolder{},
|
||||
@@ -224,6 +226,7 @@ func TestOverriddenValues(t *testing.T) {
|
||||
StunKeepaliveStartS: 9000,
|
||||
StunKeepaliveMinS: 900,
|
||||
RawStunServers: []string{"foo"},
|
||||
FeatureFlags: []string{"feature"},
|
||||
}
|
||||
|
||||
os.Unsetenv("STNOUPGRADE")
|
||||
@@ -265,7 +268,7 @@ func TestDeviceAddressesDynamic(t *testing.T) {
|
||||
DeviceID: device4,
|
||||
Name: name, // Set when auto created
|
||||
Addresses: []string{"dynamic"},
|
||||
Compression: protocol.CompressMetadata,
|
||||
Compression: protocol.CompressionMetadata,
|
||||
AllowedNetworks: []string{},
|
||||
IgnoredFolders: []ObservedFolder{},
|
||||
PendingFolders: []ObservedFolder{},
|
||||
@@ -289,7 +292,7 @@ func TestDeviceCompression(t *testing.T) {
|
||||
device1: {
|
||||
DeviceID: device1,
|
||||
Addresses: []string{"dynamic"},
|
||||
Compression: protocol.CompressMetadata,
|
||||
Compression: protocol.CompressionMetadata,
|
||||
AllowedNetworks: []string{},
|
||||
IgnoredFolders: []ObservedFolder{},
|
||||
PendingFolders: []ObservedFolder{},
|
||||
@@ -297,7 +300,7 @@ func TestDeviceCompression(t *testing.T) {
|
||||
device2: {
|
||||
DeviceID: device2,
|
||||
Addresses: []string{"dynamic"},
|
||||
Compression: protocol.CompressMetadata,
|
||||
Compression: protocol.CompressionMetadata,
|
||||
AllowedNetworks: []string{},
|
||||
IgnoredFolders: []ObservedFolder{},
|
||||
PendingFolders: []ObservedFolder{},
|
||||
@@ -305,7 +308,7 @@ func TestDeviceCompression(t *testing.T) {
|
||||
device3: {
|
||||
DeviceID: device3,
|
||||
Addresses: []string{"dynamic"},
|
||||
Compression: protocol.CompressNever,
|
||||
Compression: protocol.CompressionNever,
|
||||
AllowedNetworks: []string{},
|
||||
IgnoredFolders: []ObservedFolder{},
|
||||
PendingFolders: []ObservedFolder{},
|
||||
@@ -314,7 +317,7 @@ func TestDeviceCompression(t *testing.T) {
|
||||
DeviceID: device4,
|
||||
Name: name, // Set when auto created
|
||||
Addresses: []string{"dynamic"},
|
||||
Compression: protocol.CompressMetadata,
|
||||
Compression: protocol.CompressionMetadata,
|
||||
AllowedNetworks: []string{},
|
||||
IgnoredFolders: []ObservedFolder{},
|
||||
PendingFolders: []ObservedFolder{},
|
||||
@@ -360,7 +363,7 @@ func TestDeviceAddressesStatic(t *testing.T) {
|
||||
DeviceID: device4,
|
||||
Name: name, // Set when auto created
|
||||
Addresses: []string{"dynamic"},
|
||||
Compression: protocol.CompressMetadata,
|
||||
Compression: protocol.CompressionMetadata,
|
||||
AllowedNetworks: []string{},
|
||||
IgnoredFolders: []ObservedFolder{},
|
||||
PendingFolders: []ObservedFolder{},
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
github_com_syncthing_syncthing_lib_protocol "github.com/syncthing/syncthing/lib/protocol"
|
||||
protocol "github.com/syncthing/syncthing/lib/protocol"
|
||||
_ "github.com/syncthing/syncthing/proto/ext"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
@@ -41,6 +42,7 @@ type DeviceConfiguration struct {
|
||||
IgnoredFolders []ObservedFolder `protobuf:"bytes,14,rep,name=ignored_folders,json=ignoredFolders,proto3" json:"ignoredFolders" xml:"ignoredFolder"`
|
||||
PendingFolders []ObservedFolder `protobuf:"bytes,15,rep,name=pending_folders,json=pendingFolders,proto3" json:"pendingFolders" xml:"pendingFolder"`
|
||||
MaxRequestKiB int `protobuf:"varint,16,opt,name=max_request_kib,json=maxRequestKib,proto3,casttype=int" json:"maxRequestKiB" xml:"maxRequestKiB"`
|
||||
Untrusted bool `protobuf:"varint,17,opt,name=untrusted,proto3" json:"untrusted" xml:"untrusted"`
|
||||
}
|
||||
|
||||
func (m *DeviceConfiguration) Reset() { *m = DeviceConfiguration{} }
|
||||
@@ -50,16 +52,25 @@ func (*DeviceConfiguration) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_744b782bd13071dd, []int{0}
|
||||
}
|
||||
func (m *DeviceConfiguration) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DeviceConfiguration.Unmarshal(m, b)
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *DeviceConfiguration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_DeviceConfiguration.Marshal(b, m, deterministic)
|
||||
if deterministic {
|
||||
return xxx_messageInfo_DeviceConfiguration.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *DeviceConfiguration) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_DeviceConfiguration.Merge(m, src)
|
||||
}
|
||||
func (m *DeviceConfiguration) XXX_Size() int {
|
||||
return xxx_messageInfo_DeviceConfiguration.Size(m)
|
||||
return m.ProtoSize()
|
||||
}
|
||||
func (m *DeviceConfiguration) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_DeviceConfiguration.DiscardUnknown(m)
|
||||
@@ -76,66 +87,256 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_744b782bd13071dd = []byte{
|
||||
// 900 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0x31, 0x6f, 0xdb, 0x46,
|
||||
0x18, 0x15, 0xeb, 0xc4, 0xb6, 0xce, 0x96, 0x65, 0xd3, 0x88, 0xc3, 0x18, 0x88, 0x4e, 0x60, 0x35,
|
||||
0x28, 0x68, 0x2a, 0x17, 0x6e, 0x27, 0xa3, 0x1d, 0xca, 0x04, 0x6d, 0x83, 0xa0, 0x49, 0x7b, 0xdd,
|
||||
0xbc, 0xb0, 0x24, 0xef, 0xac, 0x1c, 0x2c, 0xf2, 0x58, 0xf2, 0xa4, 0x48, 0x40, 0x87, 0x8e, 0x1d,
|
||||
0x3a, 0x14, 0x59, 0xbb, 0x14, 0x1d, 0x3a, 0xf4, 0x97, 0x04, 0xe8, 0x60, 0x8d, 0x45, 0x87, 0x03,
|
||||
0x62, 0x2f, 0x05, 0x47, 0x8e, 0x99, 0x0a, 0xde, 0x51, 0x14, 0x49, 0x47, 0x45, 0x80, 0x6e, 0x77,
|
||||
0xef, 0xbd, 0x7b, 0xef, 0xf8, 0x74, 0x1f, 0x04, 0x7a, 0x23, 0xea, 0x1e, 0x79, 0x2c, 0x38, 0xa3,
|
||||
0xc3, 0x23, 0x4c, 0x26, 0xd4, 0x23, 0x6a, 0x33, 0x8e, 0x1c, 0x4e, 0x59, 0x30, 0x08, 0x23, 0xc6,
|
||||
0x99, 0xbe, 0xae, 0xc0, 0xc3, 0x83, 0x4c, 0x2d, 0x21, 0x8f, 0x8d, 0x8e, 0x5c, 0x12, 0x2a, 0xfe,
|
||||
0xf0, 0x4e, 0xc9, 0x85, 0xb9, 0x31, 0x89, 0x26, 0x04, 0xe7, 0x54, 0x93, 0x4c, 0xb9, 0x5a, 0x9a,
|
||||
0x7f, 0xee, 0x80, 0xfd, 0x87, 0x32, 0xe3, 0x41, 0x39, 0x43, 0xff, 0x43, 0x03, 0x4d, 0x95, 0x6d,
|
||||
0x53, 0x6c, 0x68, 0x5d, 0xad, 0xbf, 0x6d, 0xfd, 0xa4, 0xbd, 0x14, 0xb0, 0xf1, 0xb7, 0x80, 0x1f,
|
||||
0x0d, 0x29, 0x7f, 0x36, 0x76, 0x07, 0x1e, 0xf3, 0x8f, 0xe2, 0x59, 0xe0, 0xf1, 0x67, 0x34, 0x18,
|
||||
0x96, 0x56, 0xe5, 0x1b, 0x0d, 0x94, 0xfb, 0xa3, 0x87, 0x97, 0x02, 0x6e, 0x2e, 0xd6, 0x89, 0x80,
|
||||
0x9b, 0x38, 0x5f, 0xa7, 0x02, 0xb6, 0xa6, 0xfe, 0xe8, 0xc4, 0xa4, 0xf8, 0xbe, 0xc3, 0x79, 0x64,
|
||||
0x26, 0x17, 0xbd, 0x8d, 0x7c, 0x9d, 0x5e, 0xf4, 0x0a, 0xdd, 0x8f, 0xf3, 0x9e, 0xf6, 0x62, 0xde,
|
||||
0x2b, 0x3c, 0xd0, 0x82, 0xc1, 0xfa, 0x57, 0xe0, 0x46, 0xe0, 0xf8, 0xc4, 0x78, 0xa7, 0xab, 0xf5,
|
||||
0x9b, 0xd6, 0xc7, 0x89, 0x80, 0x72, 0x9f, 0x0a, 0x78, 0x47, 0x3a, 0x67, 0x1b, 0xe9, 0x77, 0x9f,
|
||||
0xf9, 0x94, 0x13, 0x3f, 0xe4, 0xb3, 0x2c, 0x65, 0xff, 0x0d, 0x38, 0x92, 0x27, 0xf5, 0x29, 0x68,
|
||||
0x3a, 0x18, 0x47, 0x24, 0x8e, 0x49, 0x6c, 0xac, 0x75, 0xd7, 0xfa, 0x4d, 0xeb, 0x34, 0x11, 0x70,
|
||||
0x09, 0xa6, 0x02, 0xde, 0x93, 0xde, 0x39, 0x52, 0x72, 0xee, 0x62, 0x72, 0xe6, 0x8c, 0x47, 0xfc,
|
||||
0xc4, 0xc4, 0xb3, 0xc0, 0xf1, 0xa9, 0x97, 0x65, 0xed, 0x5d, 0xd3, 0xbd, 0xbe, 0xe8, 0x6d, 0xe4,
|
||||
0x02, 0xb4, 0xf4, 0xd5, 0x27, 0x60, 0xcb, 0x63, 0x7e, 0x98, 0xed, 0x28, 0x0b, 0x8c, 0x1b, 0x5d,
|
||||
0xad, 0xbf, 0x73, 0x7c, 0x6b, 0x50, 0xd4, 0xf9, 0x60, 0x49, 0x5a, 0x9f, 0x24, 0x02, 0x96, 0xd5,
|
||||
0xa9, 0x80, 0x07, 0xf2, 0x52, 0x25, 0xac, 0xe8, 0x74, 0xb7, 0x0e, 0xa2, 0xf2, 0x51, 0x9d, 0x80,
|
||||
0xa6, 0x47, 0x22, 0x6e, 0xcb, 0x22, 0x6f, 0xca, 0x22, 0xbf, 0xc8, 0x7e, 0xa6, 0x0c, 0x7c, 0xa2,
|
||||
0xca, 0xbc, 0xab, 0xbc, 0x73, 0xe0, 0x0d, 0x85, 0xde, 0x5e, 0xc1, 0xa1, 0xc2, 0x45, 0x3f, 0x05,
|
||||
0x80, 0x06, 0x3c, 0x62, 0x78, 0xec, 0x91, 0xc8, 0x58, 0xef, 0x6a, 0xfd, 0x4d, 0xeb, 0x24, 0x11,
|
||||
0xb0, 0x84, 0xa6, 0x02, 0xde, 0x52, 0x0f, 0xa2, 0x80, 0x8a, 0x8f, 0x68, 0xd7, 0x30, 0x54, 0x3a,
|
||||
0xa7, 0xff, 0xa6, 0x81, 0xc3, 0xf8, 0x9c, 0x86, 0xf6, 0x02, 0xcb, 0x5e, 0xb2, 0x1d, 0x11, 0x9f,
|
||||
0x4d, 0x9c, 0x51, 0x6c, 0x6c, 0xc8, 0x30, 0x9c, 0x08, 0x68, 0x64, 0xaa, 0x47, 0x25, 0x11, 0xca,
|
||||
0x35, 0xa9, 0x80, 0xef, 0xca, 0xe8, 0x55, 0x82, 0xe2, 0x22, 0x77, 0xff, 0x53, 0x81, 0x56, 0x26,
|
||||
0xe8, 0xbf, 0x6b, 0xa0, 0x55, 0xdc, 0x19, 0xdb, 0xee, 0xcc, 0xd8, 0x94, 0xc3, 0xf5, 0xc3, 0xff,
|
||||
0x1a, 0xae, 0x44, 0xc0, 0xed, 0xa5, 0xab, 0x35, 0x4b, 0x05, 0xbc, 0x5d, 0xed, 0x10, 0x5b, 0xb3,
|
||||
0xe2, 0xf2, 0x7b, 0xd7, 0xd0, 0x6c, 0xb8, 0x50, 0xc5, 0x41, 0x3f, 0x06, 0xeb, 0xa1, 0x33, 0x8e,
|
||||
0x09, 0x36, 0x9a, 0xb2, 0xb8, 0xc3, 0x44, 0xc0, 0x1c, 0x49, 0x05, 0xdc, 0x96, 0xee, 0x6a, 0x6b,
|
||||
0xa2, 0x1c, 0xd7, 0xbf, 0x07, 0xbb, 0xce, 0x68, 0xc4, 0x9e, 0x13, 0x6c, 0x07, 0x84, 0x3f, 0x67,
|
||||
0xd1, 0x79, 0x6c, 0x00, 0x39, 0x3d, 0x5f, 0x27, 0x02, 0xb6, 0x73, 0xee, 0x49, 0x4e, 0xa5, 0x02,
|
||||
0x76, 0xd4, 0x0c, 0x55, 0xf0, 0xea, 0x9b, 0x32, 0x56, 0x91, 0xa8, 0x6e, 0xa7, 0x7f, 0x0b, 0xf6,
|
||||
0x9d, 0x31, 0x67, 0xb6, 0xe3, 0x79, 0x24, 0xe4, 0xf6, 0x19, 0x1b, 0x61, 0x12, 0xc5, 0xc6, 0x96,
|
||||
0xbc, 0xfe, 0x07, 0x89, 0x80, 0x7b, 0x19, 0xfd, 0xa9, 0x64, 0x3f, 0x53, 0x64, 0xd1, 0xd3, 0x35,
|
||||
0xc6, 0x44, 0xd7, 0xd5, 0xfa, 0x53, 0xd0, 0xf2, 0x9d, 0xa9, 0x1d, 0x93, 0x00, 0xdb, 0xe7, 0x6e,
|
||||
0x18, 0x1b, 0xdb, 0x5d, 0xad, 0x7f, 0xd3, 0x7a, 0x2f, 0x9b, 0x43, 0xdf, 0x99, 0x7e, 0x43, 0x02,
|
||||
0xfc, 0xd8, 0x0d, 0x33, 0xd7, 0x3d, 0xe9, 0x5a, 0xc2, 0xcc, 0xd7, 0x02, 0xae, 0xd1, 0x80, 0xa3,
|
||||
0xb2, 0x70, 0x61, 0x18, 0x11, 0x6f, 0xa2, 0x0c, 0x5b, 0x15, 0x43, 0x44, 0xbc, 0x49, 0xdd, 0x70,
|
||||
0x81, 0x55, 0x0c, 0x17, 0xa0, 0x1e, 0x80, 0x36, 0x1d, 0x06, 0x2c, 0x22, 0xb8, 0xf8, 0xfe, 0x9d,
|
||||
0xee, 0x5a, 0x7f, 0xeb, 0xf8, 0x60, 0xa0, 0xfe, 0x0b, 0x06, 0x4f, 0xf3, 0xff, 0x02, 0xf5, 0x4d,
|
||||
0xd6, 0xfb, 0xd9, 0xb3, 0x4b, 0x04, 0xdc, 0xc9, 0x8f, 0x2d, 0x8b, 0xd9, 0x57, 0x0f, 0xa8, 0x0c,
|
||||
0x9b, 0xa8, 0x26, 0xcb, 0xf2, 0x42, 0x12, 0x60, 0x1a, 0x0c, 0x8b, 0xbc, 0xf6, 0xdb, 0xe5, 0xe5,
|
||||
0xc7, 0xea, 0x79, 0x15, 0xd8, 0x44, 0x35, 0x99, 0xfe, 0x8b, 0x06, 0xda, 0xaa, 0xb1, 0xef, 0xc6,
|
||||
0x24, 0xe6, 0xf6, 0x39, 0x75, 0x8d, 0x5d, 0xd9, 0x59, 0x7c, 0x29, 0x60, 0xeb, 0xcb, 0xac, 0x0a,
|
||||
0xc9, 0x3c, 0xa6, 0x56, 0x22, 0x60, 0xcb, 0x2f, 0x03, 0x45, 0x48, 0x05, 0x5d, 0x14, 0x99, 0x5c,
|
||||
0xf4, 0x6a, 0xf2, 0x3a, 0xf0, 0x62, 0xde, 0xab, 0x26, 0xa0, 0x0a, 0xef, 0x5a, 0x9f, 0xbf, 0x7c,
|
||||
0xd5, 0x69, 0xcc, 0x5f, 0x75, 0x1a, 0xff, 0x5c, 0x76, 0x1a, 0x3f, 0x5f, 0x75, 0x1a, 0xbf, 0x5e,
|
||||
0x75, 0xb4, 0xf9, 0x55, 0xa7, 0xf1, 0xd7, 0x55, 0xa7, 0x71, 0x7a, 0xef, 0x2d, 0x26, 0x5b, 0x95,
|
||||
0xe6, 0xae, 0xcb, 0x09, 0xff, 0xf0, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3c, 0x69, 0xcb, 0x9f,
|
||||
0x0b, 0x08, 0x00, 0x00,
|
||||
// 930 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0x3d, 0x6f, 0xdb, 0x46,
|
||||
0x00, 0x15, 0xeb, 0xc4, 0xb6, 0xce, 0x96, 0x65, 0xd3, 0x88, 0xc3, 0x18, 0x88, 0x8e, 0x60, 0x35,
|
||||
0x28, 0x68, 0x2a, 0x17, 0x6e, 0x27, 0xa3, 0x2d, 0x50, 0x26, 0x28, 0x1a, 0x18, 0x4d, 0xda, 0xeb,
|
||||
0xe6, 0x85, 0x25, 0x79, 0x67, 0xe5, 0x60, 0xf1, 0xa3, 0xe4, 0x51, 0x91, 0x80, 0x0e, 0x1d, 0x0b,
|
||||
0xb4, 0x43, 0x91, 0xb5, 0x4b, 0xd1, 0xa1, 0x43, 0x7f, 0x89, 0x37, 0x6b, 0x2c, 0x3a, 0x1c, 0x10,
|
||||
0x7b, 0xe3, 0xc8, 0x31, 0x53, 0xc1, 0x3b, 0x8a, 0x22, 0xe9, 0xb8, 0x08, 0x90, 0xed, 0xee, 0xbd,
|
||||
0x77, 0xef, 0x1d, 0x9f, 0xee, 0x74, 0xa0, 0x3f, 0xa6, 0xce, 0x81, 0x1b, 0xf8, 0xa7, 0x74, 0x74,
|
||||
0x80, 0xc9, 0x84, 0xba, 0x44, 0x4e, 0x92, 0xc8, 0x66, 0x34, 0xf0, 0x87, 0x61, 0x14, 0xb0, 0x40,
|
||||
0x5d, 0x95, 0xe0, 0xfe, 0x5e, 0xae, 0x16, 0x90, 0x1b, 0x8c, 0x0f, 0x1c, 0x12, 0x4a, 0x7e, 0xff,
|
||||
0x5e, 0xc5, 0x25, 0x70, 0x62, 0x12, 0x4d, 0x08, 0x2e, 0xa8, 0x36, 0x99, 0x32, 0x39, 0x34, 0x7e,
|
||||
0xe9, 0x82, 0xdd, 0xc7, 0x22, 0xe3, 0x51, 0x35, 0x43, 0xfd, 0x5b, 0x01, 0x6d, 0x99, 0x6d, 0x51,
|
||||
0xac, 0x29, 0xba, 0x32, 0xd8, 0x34, 0x7f, 0x55, 0xce, 0x39, 0x6c, 0xfd, 0xcb, 0xe1, 0x27, 0x23,
|
||||
0xca, 0x9e, 0x27, 0xce, 0xd0, 0x0d, 0xbc, 0x83, 0x78, 0xe6, 0xbb, 0xec, 0x39, 0xf5, 0x47, 0x95,
|
||||
0x51, 0x75, 0x47, 0x43, 0xe9, 0xfe, 0xe4, 0xf1, 0x25, 0x87, 0xeb, 0x8b, 0x71, 0xca, 0xe1, 0x3a,
|
||||
0x2e, 0xc6, 0x19, 0x87, 0x9d, 0xa9, 0x37, 0x3e, 0x32, 0x28, 0x7e, 0x68, 0x33, 0x16, 0x19, 0xe9,
|
||||
0x45, 0x7f, 0xad, 0x18, 0x67, 0x17, 0xfd, 0x52, 0xf7, 0xf3, 0xbc, 0xaf, 0xbc, 0x9c, 0xf7, 0x4b,
|
||||
0x0f, 0xb4, 0x60, 0xb0, 0xfa, 0x0d, 0xb8, 0xe5, 0xdb, 0x1e, 0xd1, 0xde, 0xd3, 0x95, 0x41, 0xdb,
|
||||
0xfc, 0x34, 0xe5, 0x50, 0xcc, 0x33, 0x0e, 0xef, 0x09, 0xe7, 0x7c, 0x22, 0xfc, 0x1e, 0x06, 0x1e,
|
||||
0x65, 0xc4, 0x0b, 0xd9, 0x2c, 0x4f, 0xd9, 0x7d, 0x03, 0x8e, 0xc4, 0x4a, 0x75, 0x0a, 0xda, 0x36,
|
||||
0xc6, 0x11, 0x89, 0x63, 0x12, 0x6b, 0x2b, 0xfa, 0xca, 0xa0, 0x6d, 0x9e, 0xa4, 0x1c, 0x2e, 0xc1,
|
||||
0x8c, 0xc3, 0x07, 0xc2, 0xbb, 0x40, 0x2a, 0xce, 0x3a, 0x26, 0xa7, 0x76, 0x32, 0x66, 0x47, 0x06,
|
||||
0x9e, 0xf9, 0xb6, 0x47, 0xdd, 0x3c, 0x6b, 0xe7, 0x9a, 0xee, 0xf5, 0x45, 0x7f, 0xad, 0x10, 0xa0,
|
||||
0xa5, 0xaf, 0x3a, 0x01, 0x1b, 0x6e, 0xe0, 0x85, 0xf9, 0x8c, 0x06, 0xbe, 0x76, 0x4b, 0x57, 0x06,
|
||||
0x5b, 0x87, 0x77, 0x86, 0x65, 0x9d, 0x8f, 0x96, 0xa4, 0xf9, 0x59, 0xca, 0x61, 0x55, 0x9d, 0x71,
|
||||
0xb8, 0x27, 0x36, 0x55, 0xc1, 0xca, 0x4e, 0xb7, 0x9b, 0x20, 0xaa, 0x2e, 0x55, 0x09, 0x68, 0xbb,
|
||||
0x24, 0x62, 0x96, 0x28, 0xf2, 0xb6, 0x28, 0xf2, 0xab, 0xfc, 0x67, 0xca, 0xc1, 0xa7, 0xb2, 0xcc,
|
||||
0xfb, 0xd2, 0xbb, 0x00, 0xde, 0x50, 0xe8, 0xdd, 0x1b, 0x38, 0x54, 0xba, 0xa8, 0x27, 0x00, 0x50,
|
||||
0x9f, 0x45, 0x01, 0x4e, 0x5c, 0x12, 0x69, 0xab, 0xba, 0x32, 0x58, 0x37, 0x8f, 0x52, 0x0e, 0x2b,
|
||||
0x68, 0xc6, 0xe1, 0x1d, 0x79, 0x20, 0x4a, 0xa8, 0xfc, 0x88, 0x6e, 0x03, 0x43, 0x95, 0x75, 0xea,
|
||||
0x9f, 0x0a, 0xd8, 0x8f, 0xcf, 0x68, 0x68, 0x2d, 0xb0, 0xfc, 0x24, 0x5b, 0x11, 0xf1, 0x82, 0x89,
|
||||
0x3d, 0x8e, 0xb5, 0x35, 0x11, 0x86, 0x53, 0x0e, 0xb5, 0x5c, 0xf5, 0xa4, 0x22, 0x42, 0x85, 0x26,
|
||||
0xe3, 0xf0, 0x7d, 0x11, 0x7d, 0x93, 0xa0, 0xdc, 0xc8, 0xfd, 0xff, 0x55, 0xa0, 0x1b, 0x13, 0xd4,
|
||||
0xbf, 0x14, 0xd0, 0x29, 0xf7, 0x8c, 0x2d, 0x67, 0xa6, 0xad, 0x8b, 0xcb, 0xf5, 0xd3, 0x3b, 0x5d,
|
||||
0xae, 0x94, 0xc3, 0xcd, 0xa5, 0xab, 0x39, 0xcb, 0x38, 0xbc, 0x5b, 0xef, 0x10, 0x9b, 0xb3, 0x72,
|
||||
0xf3, 0x3b, 0xd7, 0xd0, 0xfc, 0x72, 0xa1, 0x9a, 0x83, 0x7a, 0x08, 0x56, 0x43, 0x3b, 0x89, 0x09,
|
||||
0xd6, 0xda, 0xa2, 0xb8, 0xfd, 0x94, 0xc3, 0x02, 0xc9, 0x38, 0xdc, 0x14, 0xee, 0x72, 0x6a, 0xa0,
|
||||
0x02, 0x57, 0x7f, 0x04, 0xdb, 0xf6, 0x78, 0x1c, 0xbc, 0x20, 0xd8, 0xf2, 0x09, 0x7b, 0x11, 0x44,
|
||||
0x67, 0xb1, 0x06, 0xc4, 0xed, 0xf9, 0x36, 0xe5, 0xb0, 0x5b, 0x70, 0x4f, 0x0b, 0x2a, 0xe3, 0xb0,
|
||||
0x27, 0xef, 0x50, 0x0d, 0xaf, 0x9f, 0x29, 0xed, 0x26, 0x12, 0x35, 0xed, 0xd4, 0xef, 0xc1, 0xae,
|
||||
0x9d, 0xb0, 0xc0, 0xb2, 0x5d, 0x97, 0x84, 0xcc, 0x3a, 0x0d, 0xc6, 0x98, 0x44, 0xb1, 0xb6, 0x21,
|
||||
0xb6, 0xff, 0x51, 0xca, 0xe1, 0x4e, 0x4e, 0x7f, 0x21, 0xd8, 0x2f, 0x25, 0x59, 0xf6, 0x74, 0x8d,
|
||||
0x31, 0xd0, 0x75, 0xb5, 0xfa, 0x0c, 0x74, 0x3c, 0x7b, 0x6a, 0xc5, 0xc4, 0xc7, 0xd6, 0x99, 0x13,
|
||||
0xc6, 0xda, 0xa6, 0xae, 0x0c, 0x6e, 0x9b, 0x1f, 0xe4, 0xf7, 0xd0, 0xb3, 0xa7, 0xdf, 0x11, 0x1f,
|
||||
0x1f, 0x3b, 0x61, 0xee, 0xba, 0x23, 0x5c, 0x2b, 0x98, 0xf1, 0x9a, 0xc3, 0x15, 0xea, 0x33, 0x54,
|
||||
0x15, 0x2e, 0x0c, 0x23, 0xe2, 0x4e, 0xa4, 0x61, 0xa7, 0x66, 0x88, 0x88, 0x3b, 0x69, 0x1a, 0x2e,
|
||||
0xb0, 0x9a, 0xe1, 0x02, 0x54, 0x7d, 0xd0, 0xa5, 0x23, 0x3f, 0x88, 0x08, 0x2e, 0xbf, 0x7f, 0x4b,
|
||||
0x5f, 0x19, 0x6c, 0x1c, 0xee, 0x0d, 0xe5, 0x5b, 0x30, 0x7c, 0x56, 0xbc, 0x05, 0xf2, 0x9b, 0xcc,
|
||||
0x0f, 0xf3, 0x63, 0x97, 0x72, 0xb8, 0x55, 0x2c, 0x5b, 0x16, 0xb3, 0x2b, 0x0f, 0x50, 0x15, 0x36,
|
||||
0x50, 0x43, 0x96, 0xe7, 0x85, 0xc4, 0xc7, 0xd4, 0x1f, 0x95, 0x79, 0xdd, 0xb7, 0xcb, 0x2b, 0x96,
|
||||
0x35, 0xf3, 0x6a, 0xb0, 0x81, 0x1a, 0x32, 0xf5, 0x77, 0x05, 0x74, 0x65, 0x63, 0x3f, 0x24, 0x24,
|
||||
0x66, 0xd6, 0x19, 0x75, 0xb4, 0x6d, 0xd1, 0x59, 0x7c, 0xc9, 0x61, 0xe7, 0xeb, 0xbc, 0x0a, 0xc1,
|
||||
0x1c, 0x53, 0x33, 0xe5, 0xb0, 0xe3, 0x55, 0x81, 0x32, 0xa4, 0x86, 0x2e, 0x8a, 0x4c, 0x2f, 0xfa,
|
||||
0x0d, 0x79, 0x13, 0x78, 0x39, 0xef, 0xd7, 0x13, 0x50, 0x8d, 0x77, 0xd4, 0xcf, 0x41, 0x3b, 0xf1,
|
||||
0x59, 0x94, 0xc4, 0x8c, 0x60, 0x6d, 0x47, 0x9c, 0x3b, 0x3d, 0x7f, 0x36, 0x4a, 0x30, 0xe3, 0xb0,
|
||||
0x2b, 0x76, 0x50, 0x22, 0x06, 0x5a, 0xb2, 0xe6, 0xf1, 0xf9, 0xab, 0x5e, 0x6b, 0xfe, 0xaa, 0xd7,
|
||||
0x3a, 0xbf, 0xec, 0x29, 0xf3, 0xcb, 0x9e, 0xf2, 0xdb, 0x55, 0xaf, 0xf5, 0xc7, 0x55, 0x4f, 0x99,
|
||||
0x5f, 0xf5, 0x5a, 0xff, 0x5c, 0xf5, 0x5a, 0x27, 0x0f, 0xde, 0xe2, 0xdf, 0x41, 0x16, 0xef, 0xac,
|
||||
0x8a, 0x7f, 0x89, 0x8f, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x73, 0xb5, 0x15, 0x0d, 0x4f, 0x08,
|
||||
0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *DeviceConfiguration) Marshal() (dAtA []byte, err error) {
|
||||
size := m.ProtoSize()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *DeviceConfiguration) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.ProtoSize()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *DeviceConfiguration) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Untrusted {
|
||||
i--
|
||||
if m.Untrusted {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x1
|
||||
i--
|
||||
dAtA[i] = 0x88
|
||||
}
|
||||
if m.MaxRequestKiB != 0 {
|
||||
i = encodeVarintDeviceconfiguration(dAtA, i, uint64(m.MaxRequestKiB))
|
||||
i--
|
||||
dAtA[i] = 0x1
|
||||
i--
|
||||
dAtA[i] = 0x80
|
||||
}
|
||||
if len(m.PendingFolders) > 0 {
|
||||
for iNdEx := len(m.PendingFolders) - 1; iNdEx >= 0; iNdEx-- {
|
||||
{
|
||||
size, err := m.PendingFolders[iNdEx].MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintDeviceconfiguration(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x7a
|
||||
}
|
||||
}
|
||||
if len(m.IgnoredFolders) > 0 {
|
||||
for iNdEx := len(m.IgnoredFolders) - 1; iNdEx >= 0; iNdEx-- {
|
||||
{
|
||||
size, err := m.IgnoredFolders[iNdEx].MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintDeviceconfiguration(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x72
|
||||
}
|
||||
}
|
||||
if m.MaxRecvKbps != 0 {
|
||||
i = encodeVarintDeviceconfiguration(dAtA, i, uint64(m.MaxRecvKbps))
|
||||
i--
|
||||
dAtA[i] = 0x68
|
||||
}
|
||||
if m.MaxSendKbps != 0 {
|
||||
i = encodeVarintDeviceconfiguration(dAtA, i, uint64(m.MaxSendKbps))
|
||||
i--
|
||||
dAtA[i] = 0x60
|
||||
}
|
||||
if m.AutoAcceptFolders {
|
||||
i--
|
||||
if m.AutoAcceptFolders {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x58
|
||||
}
|
||||
if len(m.AllowedNetworks) > 0 {
|
||||
for iNdEx := len(m.AllowedNetworks) - 1; iNdEx >= 0; iNdEx-- {
|
||||
i -= len(m.AllowedNetworks[iNdEx])
|
||||
copy(dAtA[i:], m.AllowedNetworks[iNdEx])
|
||||
i = encodeVarintDeviceconfiguration(dAtA, i, uint64(len(m.AllowedNetworks[iNdEx])))
|
||||
i--
|
||||
dAtA[i] = 0x52
|
||||
}
|
||||
}
|
||||
if m.Paused {
|
||||
i--
|
||||
if m.Paused {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x48
|
||||
}
|
||||
{
|
||||
size := m.IntroducedBy.ProtoSize()
|
||||
i -= size
|
||||
if _, err := m.IntroducedBy.MarshalTo(dAtA[i:]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i = encodeVarintDeviceconfiguration(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x42
|
||||
if m.SkipIntroductionRemovals {
|
||||
i--
|
||||
if m.SkipIntroductionRemovals {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x38
|
||||
}
|
||||
if m.Introducer {
|
||||
i--
|
||||
if m.Introducer {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x30
|
||||
}
|
||||
if len(m.CertName) > 0 {
|
||||
i -= len(m.CertName)
|
||||
copy(dAtA[i:], m.CertName)
|
||||
i = encodeVarintDeviceconfiguration(dAtA, i, uint64(len(m.CertName)))
|
||||
i--
|
||||
dAtA[i] = 0x2a
|
||||
}
|
||||
if m.Compression != 0 {
|
||||
i = encodeVarintDeviceconfiguration(dAtA, i, uint64(m.Compression))
|
||||
i--
|
||||
dAtA[i] = 0x20
|
||||
}
|
||||
if len(m.Addresses) > 0 {
|
||||
for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- {
|
||||
i -= len(m.Addresses[iNdEx])
|
||||
copy(dAtA[i:], m.Addresses[iNdEx])
|
||||
i = encodeVarintDeviceconfiguration(dAtA, i, uint64(len(m.Addresses[iNdEx])))
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
}
|
||||
if len(m.Name) > 0 {
|
||||
i -= len(m.Name)
|
||||
copy(dAtA[i:], m.Name)
|
||||
i = encodeVarintDeviceconfiguration(dAtA, i, uint64(len(m.Name)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
{
|
||||
size := m.DeviceID.ProtoSize()
|
||||
i -= size
|
||||
if _, err := m.DeviceID.MarshalTo(dAtA[i:]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i = encodeVarintDeviceconfiguration(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintDeviceconfiguration(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovDeviceconfiguration(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *DeviceConfiguration) ProtoSize() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
@@ -202,6 +403,9 @@ func (m *DeviceConfiguration) ProtoSize() (n int) {
|
||||
if m.MaxRequestKiB != 0 {
|
||||
n += 2 + sovDeviceconfiguration(uint64(m.MaxRequestKiB))
|
||||
}
|
||||
if m.Untrusted {
|
||||
n += 3
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
@@ -211,3 +415,578 @@ func sovDeviceconfiguration(x uint64) (n int) {
|
||||
func sozDeviceconfiguration(x uint64) (n int) {
|
||||
return sovDeviceconfiguration(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *DeviceConfiguration) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: DeviceConfiguration: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: DeviceConfiguration: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field DeviceID", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := m.DeviceID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Name = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Addresses = append(m.Addresses, string(dAtA[iNdEx:postIndex]))
|
||||
iNdEx = postIndex
|
||||
case 4:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Compression", wireType)
|
||||
}
|
||||
m.Compression = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Compression |= protocol.Compression(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 5:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field CertName", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.CertName = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 6:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Introducer", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.Introducer = bool(v != 0)
|
||||
case 7:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field SkipIntroductionRemovals", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.SkipIntroductionRemovals = bool(v != 0)
|
||||
case 8:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field IntroducedBy", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := m.IntroducedBy.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 9:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Paused", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.Paused = bool(v != 0)
|
||||
case 10:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field AllowedNetworks", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.AllowedNetworks = append(m.AllowedNetworks, string(dAtA[iNdEx:postIndex]))
|
||||
iNdEx = postIndex
|
||||
case 11:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field AutoAcceptFolders", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.AutoAcceptFolders = bool(v != 0)
|
||||
case 12:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field MaxSendKbps", wireType)
|
||||
}
|
||||
m.MaxSendKbps = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.MaxSendKbps |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 13:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field MaxRecvKbps", wireType)
|
||||
}
|
||||
m.MaxRecvKbps = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.MaxRecvKbps |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 14:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field IgnoredFolders", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.IgnoredFolders = append(m.IgnoredFolders, ObservedFolder{})
|
||||
if err := m.IgnoredFolders[len(m.IgnoredFolders)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 15:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field PendingFolders", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.PendingFolders = append(m.PendingFolders, ObservedFolder{})
|
||||
if err := m.PendingFolders[len(m.PendingFolders)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 16:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field MaxRequestKiB", wireType)
|
||||
}
|
||||
m.MaxRequestKiB = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.MaxRequestKiB |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 17:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Untrusted", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.Untrusted = bool(v != 0)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipDeviceconfiguration(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipDeviceconfiguration(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupDeviceconfiguration
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthDeviceconfiguration
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthDeviceconfiguration = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowDeviceconfiguration = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupDeviceconfiguration = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
|
||||
@@ -26,7 +26,11 @@ var (
|
||||
ErrMarkerMissing = errors.New("folder marker missing (this indicates potential data loss, search docs/forum to get information about how to proceed)")
|
||||
)
|
||||
|
||||
const DefaultMarkerName = ".stfolder"
|
||||
const (
|
||||
DefaultMarkerName = ".stfolder"
|
||||
maxConcurrentWritesDefault = 2
|
||||
maxConcurrentWritesLimit = 64
|
||||
)
|
||||
|
||||
func NewFolderConfiguration(myID protocol.DeviceID, id, label string, fsType fs.FilesystemType, path string) FolderConfiguration {
|
||||
f := FolderConfiguration{
|
||||
@@ -71,7 +75,7 @@ func (f FolderConfiguration) ModTimeWindow() time.Duration {
|
||||
if usage, err := disk.Usage(f.Filesystem().URI()); err != nil {
|
||||
dur = 2 * time.Second
|
||||
l.Debugf(`Detecting FS at "%v" on android: Setting mtime window to 2s: err == "%v"`, f.Path, err)
|
||||
} else if usage.Fstype == "" || strings.Contains(strings.ToLower(usage.Fstype), "fat") {
|
||||
} else if usage.Fstype == "" || strings.Contains(strings.ToLower(usage.Fstype), "fat") || strings.Contains(strings.ToLower(usage.Fstype), "msdos") {
|
||||
dur = 2 * time.Second
|
||||
l.Debugf(`Detecting FS at "%v" on android: Setting mtime window to 2s: usage.Fstype == "%v"`, f.Path, usage.Fstype)
|
||||
} else {
|
||||
@@ -206,6 +210,12 @@ func (f *FolderConfiguration) prepare() {
|
||||
if f.MarkerName == "" {
|
||||
f.MarkerName = DefaultMarkerName
|
||||
}
|
||||
|
||||
if f.MaxConcurrentWrites <= 0 {
|
||||
f.MaxConcurrentWrites = maxConcurrentWritesDefault
|
||||
} else if f.MaxConcurrentWrites > maxConcurrentWritesLimit {
|
||||
f.MaxConcurrentWrites = maxConcurrentWritesLimit
|
||||
}
|
||||
}
|
||||
|
||||
// RequiresRestartOnly returns a copy with only the attributes that require
|
||||
@@ -226,16 +236,21 @@ func (f FolderConfiguration) RequiresRestartOnly() FolderConfiguration {
|
||||
return copy
|
||||
}
|
||||
|
||||
func (f *FolderConfiguration) SharedWith(device protocol.DeviceID) bool {
|
||||
func (f *FolderConfiguration) Device(device protocol.DeviceID) (FolderDeviceConfiguration, bool) {
|
||||
for _, dev := range f.Devices {
|
||||
if dev.DeviceID == device {
|
||||
return true
|
||||
return dev, true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return FolderDeviceConfiguration{}, false
|
||||
}
|
||||
|
||||
func (f *FolderConfiguration) CheckAvailableSpace(req int64) error {
|
||||
func (f *FolderConfiguration) SharedWith(device protocol.DeviceID) bool {
|
||||
_, ok := f.Device(device)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (f *FolderConfiguration) CheckAvailableSpace(req uint64) error {
|
||||
val := f.MinDiskFree.BaseValue()
|
||||
if val <= 0 {
|
||||
return nil
|
||||
@@ -245,11 +260,8 @@ func (f *FolderConfiguration) CheckAvailableSpace(req int64) error {
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
usage.Free -= req
|
||||
if usage.Free > 0 {
|
||||
if err := CheckFreeSpace(f.MinDiskFree, usage); err == nil {
|
||||
return nil
|
||||
}
|
||||
if !checkAvailableSpace(req, f.MinDiskFree, usage) {
|
||||
return fmt.Errorf("insufficient space in %v %v", fs.Type(), fs.URI())
|
||||
}
|
||||
return fmt.Errorf("insufficient space in %v %v", fs.Type(), fs.URI())
|
||||
return nil
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,8 @@ func (t FolderType) String() string {
|
||||
return "sendonly"
|
||||
case FolderTypeReceiveOnly:
|
||||
return "receiveonly"
|
||||
case FolderTypeReceiveEncrypted:
|
||||
return "receiveencrypted"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
@@ -31,6 +33,8 @@ func (t *FolderType) UnmarshalText(bs []byte) error {
|
||||
*t = FolderTypeSendOnly
|
||||
case "receiveonly":
|
||||
*t = FolderTypeReceiveOnly
|
||||
case "receiveencrypted":
|
||||
*t = FolderTypeReceiveEncrypted
|
||||
default:
|
||||
*t = FolderTypeSendReceive
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ package config
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
@@ -23,21 +24,24 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
type FolderType int32
|
||||
|
||||
const (
|
||||
FolderTypeSendReceive FolderType = 0
|
||||
FolderTypeSendOnly FolderType = 1
|
||||
FolderTypeReceiveOnly FolderType = 2
|
||||
FolderTypeSendReceive FolderType = 0
|
||||
FolderTypeSendOnly FolderType = 1
|
||||
FolderTypeReceiveOnly FolderType = 2
|
||||
FolderTypeReceiveEncrypted FolderType = 3
|
||||
)
|
||||
|
||||
var FolderType_name = map[int32]string{
|
||||
0: "FOLDER_TYPE_SEND_RECEIVE",
|
||||
1: "FOLDER_TYPE_SEND_ONLY",
|
||||
2: "FOLDER_TYPE_RECEIVE_ONLY",
|
||||
3: "FOLDER_TYPE_RECEIVE_ENCRYPTED",
|
||||
}
|
||||
|
||||
var FolderType_value = map[string]int32{
|
||||
"FOLDER_TYPE_SEND_RECEIVE": 0,
|
||||
"FOLDER_TYPE_SEND_ONLY": 1,
|
||||
"FOLDER_TYPE_RECEIVE_ONLY": 2,
|
||||
"FOLDER_TYPE_SEND_RECEIVE": 0,
|
||||
"FOLDER_TYPE_SEND_ONLY": 1,
|
||||
"FOLDER_TYPE_RECEIVE_ONLY": 2,
|
||||
"FOLDER_TYPE_RECEIVE_ENCRYPTED": 3,
|
||||
}
|
||||
|
||||
func (FolderType) EnumDescriptor() ([]byte, []int) {
|
||||
@@ -51,19 +55,23 @@ func init() {
|
||||
func init() { proto.RegisterFile("lib/config/foldertype.proto", fileDescriptor_ea6ddb20c0633575) }
|
||||
|
||||
var fileDescriptor_ea6ddb20c0633575 = []byte{
|
||||
// 220 bytes of a gzipped FileDescriptorProto
|
||||
// 287 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xce, 0xc9, 0x4c, 0xd2,
|
||||
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x4f, 0xcb, 0xcf, 0x49, 0x49, 0x2d, 0x2a, 0xa9, 0x2c,
|
||||
0x48, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x48, 0x68, 0x6d, 0x64, 0xe4, 0xe2,
|
||||
0x72, 0x03, 0x4b, 0x86, 0x54, 0x16, 0xa4, 0x0a, 0x99, 0x73, 0x49, 0xb8, 0xf9, 0xfb, 0xb8, 0xb8,
|
||||
0x06, 0xc5, 0x87, 0x44, 0x06, 0xb8, 0xc6, 0x07, 0xbb, 0xfa, 0xb9, 0xc4, 0x07, 0xb9, 0x3a, 0xbb,
|
||||
0x7a, 0x86, 0xb9, 0x0a, 0x30, 0x48, 0x49, 0x76, 0xcd, 0x55, 0x10, 0x45, 0xa8, 0x0e, 0x4e, 0xcd,
|
||||
0x4b, 0x09, 0x4a, 0x4d, 0x4e, 0xcd, 0x2c, 0x4b, 0x15, 0x32, 0xe4, 0x12, 0xc5, 0xd0, 0xe8, 0xef,
|
||||
0xe7, 0x13, 0x29, 0xc0, 0x28, 0x25, 0xd6, 0x35, 0x57, 0x41, 0x08, 0x55, 0x97, 0x7f, 0x5e, 0x4e,
|
||||
0x25, 0xba, 0x5d, 0x50, 0x6b, 0x20, 0xba, 0x98, 0xd0, 0xed, 0x82, 0xda, 0x03, 0xd2, 0xe8, 0xe4,
|
||||
0x7e, 0xe2, 0xa1, 0x1c, 0xc3, 0x85, 0x87, 0x72, 0x0c, 0x2f, 0x1e, 0xc9, 0x31, 0x4c, 0x78, 0x2c,
|
||||
0xc7, 0xb0, 0xe0, 0xb1, 0x1c, 0xe3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x69,
|
||||
0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x17, 0x57, 0xe6, 0x25, 0x97,
|
||||
0x64, 0x64, 0xe6, 0xa5, 0x23, 0xb1, 0x10, 0xa1, 0x92, 0xc4, 0x06, 0x0e, 0x0b, 0x63, 0x40, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0x7b, 0x44, 0x34, 0x9f, 0x2a, 0x01, 0x00, 0x00,
|
||||
0x48, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x48, 0x48, 0x29, 0x17, 0xa5, 0x16,
|
||||
0xe4, 0x17, 0xeb, 0x83, 0x05, 0x93, 0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3, 0xf3, 0xc1, 0x1c, 0x30,
|
||||
0x0b, 0xa2, 0x58, 0xeb, 0x17, 0x23, 0x17, 0x97, 0x1b, 0xd8, 0x84, 0x90, 0xca, 0x82, 0x54, 0x21,
|
||||
0x73, 0x2e, 0x09, 0x37, 0x7f, 0x1f, 0x17, 0xd7, 0xa0, 0xf8, 0x90, 0xc8, 0x00, 0xd7, 0xf8, 0x60,
|
||||
0x57, 0x3f, 0x97, 0xf8, 0x20, 0x57, 0x67, 0x57, 0xcf, 0x30, 0x57, 0x01, 0x06, 0x29, 0xc9, 0xae,
|
||||
0xb9, 0x0a, 0xa2, 0x08, 0xd5, 0xc1, 0xa9, 0x79, 0x29, 0x41, 0xa9, 0xc9, 0xa9, 0x99, 0x65, 0xa9,
|
||||
0x42, 0x86, 0x5c, 0xa2, 0x18, 0x1a, 0xfd, 0xfd, 0x7c, 0x22, 0x05, 0x18, 0xa5, 0xc4, 0xba, 0xe6,
|
||||
0x2a, 0x08, 0xa1, 0xea, 0xf2, 0xcf, 0xcb, 0xa9, 0x44, 0xb7, 0x0b, 0x6a, 0x0d, 0x44, 0x17, 0x13,
|
||||
0xba, 0x5d, 0x50, 0x7b, 0xc0, 0x1a, 0x1d, 0xb9, 0x64, 0xb1, 0x69, 0x74, 0xf5, 0x73, 0x0e, 0x8a,
|
||||
0x0c, 0x08, 0x71, 0x75, 0x11, 0x60, 0x96, 0x92, 0xeb, 0x9a, 0xab, 0x20, 0x85, 0xa1, 0xdb, 0x35,
|
||||
0x2f, 0xb9, 0xa8, 0xb2, 0xa0, 0x24, 0x35, 0x45, 0x8a, 0x65, 0xc5, 0x12, 0x39, 0x06, 0x27, 0xef,
|
||||
0x13, 0x0f, 0xe5, 0x18, 0x2e, 0x3c, 0x94, 0x63, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39,
|
||||
0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x16, 0x3c, 0x96, 0x63, 0xbc, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63,
|
||||
0x39, 0x86, 0x28, 0xcd, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0xfd, 0xe2,
|
||||
0xca, 0xbc, 0xe4, 0x92, 0x8c, 0xcc, 0xbc, 0x74, 0x24, 0x16, 0x22, 0x1e, 0x92, 0xd8, 0xc0, 0x01,
|
||||
0x6a, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xc9, 0x87, 0xbe, 0x2d, 0x9c, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
fmt "fmt"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
_ "github.com/syncthing/syncthing/proto/ext"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
@@ -45,16 +46,25 @@ func (*GUIConfiguration) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_2a9586d611855d64, []int{0}
|
||||
}
|
||||
func (m *GUIConfiguration) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GUIConfiguration.Unmarshal(m, b)
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *GUIConfiguration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_GUIConfiguration.Marshal(b, m, deterministic)
|
||||
if deterministic {
|
||||
return xxx_messageInfo_GUIConfiguration.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *GUIConfiguration) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GUIConfiguration.Merge(m, src)
|
||||
}
|
||||
func (m *GUIConfiguration) XXX_Size() int {
|
||||
return xxx_messageInfo_GUIConfiguration.Size(m)
|
||||
return m.ProtoSize()
|
||||
}
|
||||
func (m *GUIConfiguration) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GUIConfiguration.DiscardUnknown(m)
|
||||
@@ -69,62 +79,203 @@ func init() {
|
||||
func init() { proto.RegisterFile("lib/config/guiconfiguration.proto", fileDescriptor_2a9586d611855d64) }
|
||||
|
||||
var fileDescriptor_2a9586d611855d64 = []byte{
|
||||
// 834 bytes of a gzipped FileDescriptorProto
|
||||
// 837 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0xcd, 0x6e, 0xdb, 0x46,
|
||||
0x10, 0x16, 0x5b, 0x47, 0xb2, 0xb6, 0xae, 0x60, 0xb0, 0x4d, 0xcb, 0x04, 0x8d, 0x56, 0x51, 0xd8,
|
||||
0xc2, 0x01, 0x02, 0x39, 0x71, 0x5a, 0x24, 0xf0, 0xa1, 0x80, 0x1c, 0x20, 0x3f, 0xb0, 0x0b, 0x04,
|
||||
0x74, 0x7d, 0xc9, 0x85, 0x58, 0x91, 0x6b, 0x69, 0x21, 0xfe, 0x95, 0xbb, 0x84, 0xa4, 0x43, 0xfb,
|
||||
0x0c, 0x85, 0x7a, 0x2e, 0xd0, 0x67, 0xe8, 0xa5, 0xaf, 0xd0, 0x9b, 0x74, 0x2a, 0x72, 0x5a, 0x20,
|
||||
0xd2, 0xa5, 0xe0, 0x91, 0xc7, 0x9c, 0x8a, 0x5d, 0xfe, 0x48, 0x94, 0x95, 0x26, 0xb7, 0x9d, 0x6f,
|
||||
0xbe, 0x99, 0x6f, 0x66, 0x38, 0x03, 0x82, 0xdb, 0x0e, 0xe9, 0x1d, 0x5a, 0xbe, 0x77, 0x49, 0xfa,
|
||||
0x87, 0xfd, 0x88, 0xa4, 0xaf, 0x28, 0x44, 0x8c, 0xf8, 0x5e, 0x27, 0x08, 0x7d, 0xe6, 0xab, 0xd5,
|
||||
0x14, 0xbc, 0x79, 0x63, 0x8d, 0x8a, 0x22, 0x36, 0x70, 0x7d, 0x1b, 0xa7, 0x94, 0x9b, 0x75, 0x3c,
|
||||
0x66, 0xe9, 0xb3, 0xfd, 0x7a, 0x0f, 0xec, 0x3f, 0xbb, 0x78, 0xf1, 0x64, 0x3d, 0x91, 0xda, 0x03,
|
||||
0x35, 0xec, 0xa1, 0x9e, 0x83, 0x6d, 0x4d, 0x69, 0x29, 0x07, 0xbb, 0x27, 0xcf, 0x63, 0x0e, 0x73,
|
||||
0x28, 0xe1, 0xf0, 0xf6, 0xd8, 0x75, 0x8e, 0xdb, 0x99, 0x7d, 0x0f, 0x31, 0x16, 0xb6, 0x5b, 0x36,
|
||||
0xbe, 0x44, 0x91, 0xc3, 0x8e, 0xdb, 0x2c, 0x8c, 0x70, 0x3b, 0x9e, 0xe9, 0x7b, 0xeb, 0xfe, 0xb7,
|
||||
0x33, 0x7d, 0x47, 0x38, 0x8c, 0x3c, 0x8b, 0xfa, 0x33, 0xa8, 0x21, 0xdb, 0x0e, 0x31, 0xa5, 0xda,
|
||||
0x47, 0x2d, 0xe5, 0xa0, 0x7e, 0x62, 0x2d, 0x38, 0x04, 0x06, 0x1a, 0x75, 0x53, 0x54, 0x28, 0x66,
|
||||
0x84, 0x84, 0xc3, 0x6f, 0xa4, 0x62, 0x66, 0xaf, 0x89, 0x3d, 0x38, 0x7a, 0xd4, 0xb9, 0xdf, 0xb9,
|
||||
0xdf, 0x79, 0x70, 0xfc, 0xf8, 0xe1, 0xe3, 0x6f, 0xdb, 0x6f, 0x67, 0x7a, 0xa3, 0x0c, 0x4d, 0xe7,
|
||||
0xfa, 0x5a, 0x52, 0x23, 0x4f, 0xa9, 0xfe, 0xa3, 0x80, 0x2f, 0x23, 0x8f, 0x8c, 0x4d, 0xea, 0x5b,
|
||||
0x43, 0xcc, 0xcc, 0x00, 0x87, 0x2e, 0xa1, 0x94, 0xf8, 0x1e, 0xd5, 0x3e, 0x96, 0xf5, 0xfc, 0xae,
|
||||
0x2c, 0x38, 0xd4, 0x0c, 0x34, 0xba, 0xf0, 0xc8, 0xf8, 0x5c, 0xb2, 0x5e, 0xae, 0x48, 0x31, 0x87,
|
||||
0xd7, 0xa3, 0x6d, 0x8e, 0x84, 0xc3, 0xaf, 0x65, 0xb1, 0x5b, 0xbd, 0xf7, 0x7c, 0x97, 0x30, 0xec,
|
||||
0x06, 0x6c, 0x22, 0x46, 0x04, 0xdf, 0xc3, 0x99, 0xce, 0xf5, 0x77, 0x16, 0x60, 0x6c, 0x97, 0x57,
|
||||
0x9f, 0x82, 0x9d, 0x88, 0xe2, 0x50, 0xdb, 0x91, 0x4d, 0x1c, 0xc5, 0x1c, 0x4a, 0x3b, 0xe1, 0xf0,
|
||||
0xf3, 0xb4, 0x2c, 0x8a, 0xc3, 0x72, 0x15, 0x8d, 0x32, 0x64, 0x48, 0xbe, 0xfa, 0x0a, 0xec, 0x06,
|
||||
0x88, 0xd2, 0x91, 0x1f, 0xda, 0xda, 0x35, 0x99, 0xeb, 0xfb, 0x98, 0xc3, 0x02, 0x4b, 0x38, 0xd4,
|
||||
0x64, 0xbe, 0x1c, 0x28, 0xe7, 0x54, 0xaf, 0xc2, 0x46, 0x11, 0xab, 0xba, 0xa0, 0x2e, 0x36, 0xd2,
|
||||
0x14, 0x2b, 0xa9, 0x55, 0x5b, 0xca, 0x41, 0xe3, 0x68, 0xbf, 0x93, 0xae, 0x6a, 0xa7, 0x1b, 0xb1,
|
||||
0xc1, 0x0f, 0xbe, 0x8d, 0x53, 0x39, 0x94, 0x59, 0x85, 0x5c, 0x0e, 0x6c, 0xc8, 0x5d, 0x85, 0x8d,
|
||||
0x22, 0x56, 0xc5, 0xa0, 0x16, 0x51, 0x6c, 0x32, 0x87, 0x6a, 0x35, 0xb9, 0xce, 0x67, 0x0b, 0x0e,
|
||||
0xeb, 0x62, 0xb0, 0x14, 0xff, 0x78, 0x76, 0x1e, 0x73, 0x58, 0x8d, 0xe4, 0x2b, 0xe1, 0xb0, 0x21,
|
||||
0x55, 0x98, 0x43, 0xd3, 0xb5, 0x8e, 0x67, 0xfa, 0x6e, 0x6e, 0x24, 0x33, 0x3d, 0xe3, 0x4d, 0xe7,
|
||||
0xfa, 0x2a, 0xdc, 0x90, 0xa0, 0x43, 0x85, 0x0c, 0x0a, 0x88, 0x39, 0xc4, 0x13, 0x6d, 0x57, 0x0e,
|
||||
0x4c, 0xc8, 0x54, 0xbb, 0x2f, 0x5f, 0x9c, 0xe2, 0x89, 0xd0, 0x40, 0x01, 0x39, 0xc5, 0x93, 0x84,
|
||||
0xc3, 0x2f, 0xd2, 0x4e, 0x02, 0x32, 0xc4, 0x93, 0x72, 0x1f, 0xfb, 0x9b, 0xe0, 0x74, 0xae, 0x67,
|
||||
0x19, 0x8c, 0x2c, 0x5e, 0xfd, 0x4d, 0x01, 0xd7, 0x89, 0x47, 0xb1, 0x15, 0x85, 0xd8, 0x44, 0xb6,
|
||||
0x4b, 0x3c, 0x13, 0x59, 0x96, 0xb8, 0xa3, 0xba, 0x6c, 0xce, 0x8c, 0x39, 0xfc, 0x2c, 0x27, 0x74,
|
||||
0x85, 0xbf, 0x2b, 0xdd, 0x09, 0x87, 0x77, 0xa4, 0xf0, 0x16, 0x5f, 0xb9, 0x8a, 0x5b, 0xff, 0xcb,
|
||||
0x30, 0xb6, 0x25, 0x57, 0x4f, 0xc1, 0x35, 0x36, 0xc0, 0x2e, 0xd6, 0x80, 0x6c, 0xfd, 0xbb, 0x98,
|
||||
0xc3, 0x14, 0x48, 0x38, 0xbc, 0x95, 0xce, 0x54, 0x58, 0x6b, 0xa7, 0x9b, 0x3d, 0xc4, 0xcd, 0xd6,
|
||||
0xb2, 0xb7, 0x91, 0x86, 0xa8, 0x17, 0xa0, 0x6e, 0xe3, 0x5e, 0xd4, 0xef, 0x13, 0xaf, 0xaf, 0x7d,
|
||||
0x22, 0xbb, 0x7a, 0x14, 0x73, 0xb8, 0x02, 0x8b, 0x6d, 0x2e, 0x90, 0xe2, 0x73, 0x35, 0xca, 0x90,
|
||||
0xb1, 0x0a, 0x52, 0xff, 0x52, 0x80, 0x56, 0x4c, 0x8e, 0x0e, 0x49, 0x60, 0x0e, 0x7c, 0xca, 0x4c,
|
||||
0x6b, 0x80, 0xad, 0xa1, 0xb6, 0x27, 0x65, 0x7e, 0x11, 0x77, 0x9d, 0x73, 0xce, 0x87, 0x24, 0x78,
|
||||
0xee, 0x53, 0x26, 0x09, 0xc5, 0x5d, 0x6f, 0xf5, 0x6e, 0xdc, 0xf5, 0x7b, 0x38, 0xc9, 0x4c, 0xdf,
|
||||
0x2e, 0x62, 0x5c, 0x81, 0x9f, 0x08, 0x58, 0xfd, 0x53, 0x01, 0x5f, 0xad, 0xbe, 0xb9, 0xe3, 0xf8,
|
||||
0x23, 0xf3, 0x32, 0x44, 0x2e, 0x36, 0x1d, 0x1f, 0xd9, 0x62, 0x48, 0x9f, 0xca, 0xea, 0x7f, 0x8a,
|
||||
0x39, 0xbc, 0x51, 0x7c, 0x1d, 0x41, 0x7b, 0x2a, 0x58, 0x67, 0x29, 0x29, 0xe1, 0xf0, 0x6e, 0x79,
|
||||
0x01, 0x36, 0x19, 0xe5, 0x2e, 0xee, 0x7c, 0x00, 0xcf, 0x78, 0xb7, 0xdc, 0xc9, 0xb3, 0xbf, 0xdf,
|
||||
0x34, 0x2b, 0xf3, 0x37, 0xcd, 0xca, 0xbf, 0x8b, 0x66, 0xe5, 0xd7, 0x65, 0xb3, 0xf2, 0xc7, 0xb2,
|
||||
0xa9, 0xcc, 0x97, 0xcd, 0xca, 0xeb, 0x65, 0xb3, 0xf2, 0xea, 0x6e, 0x9f, 0xb0, 0x41, 0xd4, 0xeb,
|
||||
0x58, 0xbe, 0x7b, 0x48, 0x27, 0x9e, 0xc5, 0x06, 0xc4, 0xeb, 0xaf, 0xbd, 0x56, 0x7f, 0xaf, 0x5e,
|
||||
0x55, 0xfe, 0xaa, 0x1e, 0xfe, 0x17, 0x00, 0x00, 0xff, 0xff, 0xfa, 0x2b, 0x9a, 0x81, 0xfd, 0x06,
|
||||
0x00, 0x00,
|
||||
0x10, 0x16, 0x5b, 0x47, 0xb2, 0xb6, 0xae, 0x60, 0xb0, 0x4d, 0xcb, 0x04, 0x0d, 0xd7, 0x51, 0xd8,
|
||||
0xc2, 0x01, 0x02, 0x39, 0x71, 0x5a, 0x24, 0xf0, 0xa1, 0x80, 0x1c, 0x20, 0x4d, 0x60, 0x17, 0x08,
|
||||
0xe8, 0xfa, 0x92, 0x0b, 0xb1, 0x22, 0xd7, 0xd2, 0x42, 0xfc, 0x2b, 0x77, 0x09, 0x4b, 0x87, 0xf6,
|
||||
0x19, 0x0a, 0xf5, 0x5c, 0xa0, 0xcf, 0xd0, 0x4b, 0x5f, 0x21, 0x37, 0xe9, 0x54, 0xe4, 0xb4, 0x40,
|
||||
0xa4, 0x1b, 0x8f, 0x3c, 0xe6, 0x54, 0xec, 0xf2, 0x47, 0xa2, 0xac, 0xd4, 0xbd, 0xed, 0x7c, 0xf3,
|
||||
0xcd, 0x7c, 0x33, 0xc3, 0x19, 0x10, 0xdc, 0x75, 0x49, 0xef, 0xc0, 0x0e, 0xfc, 0x0b, 0xd2, 0x3f,
|
||||
0xe8, 0xc7, 0x24, 0x7b, 0xc5, 0x11, 0x62, 0x24, 0xf0, 0x3b, 0x61, 0x14, 0xb0, 0x40, 0xad, 0x67,
|
||||
0xe0, 0xed, 0x5b, 0x2b, 0x54, 0x14, 0xb3, 0x81, 0x17, 0x38, 0x38, 0xa3, 0xdc, 0x6e, 0xe2, 0x11,
|
||||
0xcb, 0x9e, 0xed, 0xb7, 0x3b, 0x60, 0xf7, 0x87, 0xf3, 0x97, 0xcf, 0x56, 0x13, 0xa9, 0x3d, 0xd0,
|
||||
0xc0, 0x3e, 0xea, 0xb9, 0xd8, 0xd1, 0x94, 0x3d, 0x65, 0x7f, 0xfb, 0xf8, 0x45, 0xc2, 0x61, 0x01,
|
||||
0xa5, 0x1c, 0xde, 0x1d, 0x79, 0xee, 0x51, 0x3b, 0xb7, 0x1f, 0x20, 0xc6, 0xa2, 0xf6, 0x9e, 0x83,
|
||||
0x2f, 0x50, 0xec, 0xb2, 0xa3, 0x36, 0x8b, 0x62, 0xdc, 0x4e, 0xa6, 0xc6, 0xce, 0xaa, 0xff, 0xfd,
|
||||
0xd4, 0xd8, 0x12, 0x0e, 0xb3, 0xc8, 0xa2, 0xfe, 0x02, 0x1a, 0xc8, 0x71, 0x22, 0x4c, 0xa9, 0xf6,
|
||||
0xd1, 0x9e, 0xb2, 0xdf, 0x3c, 0xb6, 0xe7, 0x1c, 0x02, 0x13, 0x5d, 0x76, 0x33, 0x54, 0x28, 0xe6,
|
||||
0x84, 0x94, 0xc3, 0x6f, 0xa4, 0x62, 0x6e, 0xaf, 0x88, 0x3d, 0x3a, 0x7c, 0xd2, 0x79, 0xd8, 0x79,
|
||||
0xd8, 0x79, 0x74, 0xf4, 0xf4, 0xf1, 0xd3, 0x6f, 0xdb, 0xef, 0xa7, 0x46, 0xab, 0x0a, 0x4d, 0x66,
|
||||
0xc6, 0x4a, 0x52, 0xb3, 0x48, 0xa9, 0xfe, 0xa3, 0x80, 0x2f, 0x63, 0x9f, 0x8c, 0x2c, 0x1a, 0xd8,
|
||||
0x43, 0xcc, 0xac, 0x10, 0x47, 0x1e, 0xa1, 0x94, 0x04, 0x3e, 0xd5, 0x3e, 0x96, 0xf5, 0xfc, 0xa1,
|
||||
0xcc, 0x39, 0xd4, 0x4c, 0x74, 0x79, 0xee, 0x93, 0xd1, 0x99, 0x64, 0xbd, 0x5a, 0x92, 0x12, 0x0e,
|
||||
0x6f, 0xc6, 0x9b, 0x1c, 0x29, 0x87, 0x5f, 0xcb, 0x62, 0x37, 0x7a, 0x1f, 0x04, 0x1e, 0x61, 0xd8,
|
||||
0x0b, 0xd9, 0x58, 0x8c, 0x08, 0x5e, 0xc3, 0x99, 0xcc, 0x8c, 0x0f, 0x16, 0x60, 0x6e, 0x96, 0x57,
|
||||
0x9f, 0x83, 0xad, 0x98, 0xe2, 0x48, 0xdb, 0x92, 0x4d, 0x1c, 0x26, 0x1c, 0x4a, 0x3b, 0xe5, 0xf0,
|
||||
0xf3, 0xac, 0x2c, 0x8a, 0xa3, 0x6a, 0x15, 0xad, 0x2a, 0x64, 0x4a, 0xbe, 0xfa, 0x1a, 0x6c, 0x87,
|
||||
0x88, 0xd2, 0xcb, 0x20, 0x72, 0xb4, 0x1b, 0x32, 0xd7, 0xf7, 0x09, 0x87, 0x25, 0x96, 0x72, 0xa8,
|
||||
0xc9, 0x7c, 0x05, 0x50, 0xcd, 0xa9, 0x5e, 0x85, 0xcd, 0x32, 0x56, 0xf5, 0x40, 0x53, 0x6c, 0xa4,
|
||||
0x25, 0x56, 0x52, 0xab, 0xef, 0x29, 0xfb, 0xad, 0xc3, 0xdd, 0x4e, 0xb6, 0xaa, 0x9d, 0x6e, 0xcc,
|
||||
0x06, 0x3f, 0x06, 0x0e, 0xce, 0xe4, 0x50, 0x6e, 0x95, 0x72, 0x05, 0xb0, 0x26, 0x77, 0x15, 0x36,
|
||||
0xcb, 0x58, 0x15, 0x83, 0x46, 0x4c, 0xb1, 0xc5, 0x5c, 0xaa, 0x35, 0xe4, 0x3a, 0x9f, 0xce, 0x39,
|
||||
0x6c, 0x8a, 0xc1, 0x52, 0xfc, 0xd3, 0xe9, 0x59, 0xc2, 0x61, 0x3d, 0x96, 0xaf, 0x94, 0xc3, 0x96,
|
||||
0x54, 0x61, 0x2e, 0xcd, 0xd6, 0x3a, 0x99, 0x1a, 0xdb, 0x85, 0x91, 0x4e, 0x8d, 0x9c, 0x37, 0x99,
|
||||
0x19, 0xcb, 0x70, 0x53, 0x82, 0x2e, 0x15, 0x32, 0x28, 0x24, 0xd6, 0x10, 0x8f, 0xb5, 0x6d, 0x39,
|
||||
0x30, 0x21, 0x53, 0xef, 0xbe, 0x7a, 0x79, 0x82, 0xc7, 0x42, 0x03, 0x85, 0xe4, 0x04, 0x8f, 0x53,
|
||||
0x0e, 0xbf, 0xc8, 0x3a, 0x09, 0xc9, 0x10, 0x8f, 0xab, 0x7d, 0xec, 0xae, 0x83, 0x93, 0x99, 0x91,
|
||||
0x67, 0x30, 0xf3, 0x78, 0xf5, 0x77, 0x05, 0xdc, 0x24, 0x3e, 0xc5, 0x76, 0x1c, 0x61, 0x0b, 0x39,
|
||||
0x1e, 0xf1, 0x2d, 0x64, 0xdb, 0xe2, 0x8e, 0x9a, 0xb2, 0x39, 0x2b, 0xe1, 0xf0, 0xb3, 0x82, 0xd0,
|
||||
0x15, 0xfe, 0xae, 0x74, 0xa7, 0x1c, 0xde, 0x93, 0xc2, 0x1b, 0x7c, 0xd5, 0x2a, 0xee, 0xfc, 0x27,
|
||||
0xc3, 0xdc, 0x94, 0x5c, 0x3d, 0x01, 0x37, 0xd8, 0x00, 0x7b, 0x58, 0x03, 0xb2, 0xf5, 0xef, 0x12,
|
||||
0x0e, 0x33, 0x20, 0xe5, 0xf0, 0x4e, 0x36, 0x53, 0x61, 0xad, 0x9c, 0x6e, 0xfe, 0x10, 0x37, 0xdb,
|
||||
0xc8, 0xdf, 0x66, 0x16, 0xa2, 0x9e, 0x83, 0xa6, 0x83, 0x7b, 0x71, 0xbf, 0x4f, 0xfc, 0xbe, 0xf6,
|
||||
0x89, 0xec, 0xea, 0x49, 0xc2, 0xe1, 0x12, 0x2c, 0xb7, 0xb9, 0x44, 0xca, 0xcf, 0xd5, 0xaa, 0x42,
|
||||
0xe6, 0x32, 0x48, 0xfd, 0x5b, 0x01, 0x5a, 0x39, 0x39, 0x3a, 0x24, 0xa1, 0x35, 0x08, 0x28, 0xb3,
|
||||
0xec, 0x01, 0xb6, 0x87, 0xda, 0x8e, 0x94, 0xf9, 0x55, 0xdc, 0x75, 0xc1, 0x39, 0x1b, 0x92, 0xf0,
|
||||
0x45, 0x40, 0x99, 0x24, 0x94, 0x77, 0xbd, 0xd1, 0xbb, 0x76, 0xd7, 0xd7, 0x70, 0xd2, 0xa9, 0xb1,
|
||||
0x59, 0xc4, 0xbc, 0x02, 0x3f, 0x13, 0xb0, 0xfa, 0x97, 0x02, 0xbe, 0x5a, 0x7e, 0x73, 0xd7, 0x0d,
|
||||
0x2e, 0xad, 0x8b, 0x08, 0x79, 0xd8, 0x72, 0x03, 0xe4, 0x88, 0x21, 0x7d, 0x2a, 0xab, 0xff, 0x39,
|
||||
0xe1, 0xf0, 0x56, 0xf9, 0x75, 0x04, 0xed, 0xb9, 0x60, 0x9d, 0x66, 0xa4, 0x94, 0xc3, 0xfb, 0xd5,
|
||||
0x05, 0x58, 0x67, 0x54, 0xbb, 0xb8, 0xf7, 0x3f, 0x78, 0xe6, 0x87, 0xe5, 0x8e, 0x4f, 0xde, 0xbc,
|
||||
0xd3, 0x6b, 0xb3, 0x77, 0x7a, 0xed, 0xcd, 0x5c, 0x57, 0x66, 0x73, 0x5d, 0xf9, 0x6d, 0xa1, 0xd7,
|
||||
0xfe, 0x5c, 0xe8, 0xca, 0x6c, 0xa1, 0xd7, 0xde, 0x2e, 0xf4, 0xda, 0xeb, 0xfb, 0x7d, 0xc2, 0x06,
|
||||
0x71, 0xaf, 0x63, 0x07, 0xde, 0x01, 0x1d, 0xfb, 0x36, 0x1b, 0x10, 0xbf, 0xbf, 0xf2, 0x5a, 0xfe,
|
||||
0xc1, 0x7a, 0x75, 0xf9, 0xbb, 0x7a, 0xfc, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd8, 0x8c, 0xef,
|
||||
0xc0, 0x01, 0x07, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *GUIConfiguration) Marshal() (dAtA []byte, err error) {
|
||||
size := m.ProtoSize()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *GUIConfiguration) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.ProtoSize()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *GUIConfiguration) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.InsecureAllowFrameLoading {
|
||||
i--
|
||||
if m.InsecureAllowFrameLoading {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x68
|
||||
}
|
||||
if m.InsecureSkipHostCheck {
|
||||
i--
|
||||
if m.InsecureSkipHostCheck {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x60
|
||||
}
|
||||
if m.Debugging {
|
||||
i--
|
||||
if m.Debugging {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x58
|
||||
}
|
||||
if len(m.Theme) > 0 {
|
||||
i -= len(m.Theme)
|
||||
copy(dAtA[i:], m.Theme)
|
||||
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.Theme)))
|
||||
i--
|
||||
dAtA[i] = 0x52
|
||||
}
|
||||
if m.InsecureAdminAccess {
|
||||
i--
|
||||
if m.InsecureAdminAccess {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x48
|
||||
}
|
||||
if len(m.APIKey) > 0 {
|
||||
i -= len(m.APIKey)
|
||||
copy(dAtA[i:], m.APIKey)
|
||||
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.APIKey)))
|
||||
i--
|
||||
dAtA[i] = 0x42
|
||||
}
|
||||
if m.RawUseTLS {
|
||||
i--
|
||||
if m.RawUseTLS {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x38
|
||||
}
|
||||
if m.AuthMode != 0 {
|
||||
i = encodeVarintGuiconfiguration(dAtA, i, uint64(m.AuthMode))
|
||||
i--
|
||||
dAtA[i] = 0x30
|
||||
}
|
||||
if len(m.Password) > 0 {
|
||||
i -= len(m.Password)
|
||||
copy(dAtA[i:], m.Password)
|
||||
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.Password)))
|
||||
i--
|
||||
dAtA[i] = 0x2a
|
||||
}
|
||||
if len(m.User) > 0 {
|
||||
i -= len(m.User)
|
||||
copy(dAtA[i:], m.User)
|
||||
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.User)))
|
||||
i--
|
||||
dAtA[i] = 0x22
|
||||
}
|
||||
if len(m.RawUnixSocketPermissions) > 0 {
|
||||
i -= len(m.RawUnixSocketPermissions)
|
||||
copy(dAtA[i:], m.RawUnixSocketPermissions)
|
||||
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.RawUnixSocketPermissions)))
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
if len(m.RawAddress) > 0 {
|
||||
i -= len(m.RawAddress)
|
||||
copy(dAtA[i:], m.RawAddress)
|
||||
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.RawAddress)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if m.Enabled {
|
||||
i--
|
||||
if m.Enabled {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x8
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintGuiconfiguration(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovGuiconfiguration(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *GUIConfiguration) ProtoSize() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
@@ -185,3 +336,471 @@ func sovGuiconfiguration(x uint64) (n int) {
|
||||
func sozGuiconfiguration(x uint64) (n int) {
|
||||
return sovGuiconfiguration(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *GUIConfiguration) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: GUIConfiguration: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: GUIConfiguration: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Enabled", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.Enabled = bool(v != 0)
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field RawAddress", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.RawAddress = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field RawUnixSocketPermissions", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.RawUnixSocketPermissions = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field User", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.User = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 5:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Password", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Password = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 6:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field AuthMode", wireType)
|
||||
}
|
||||
m.AuthMode = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.AuthMode |= AuthMode(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 7:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field RawUseTLS", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.RawUseTLS = bool(v != 0)
|
||||
case 8:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field APIKey", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.APIKey = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 9:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field InsecureAdminAccess", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.InsecureAdminAccess = bool(v != 0)
|
||||
case 10:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Theme", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Theme = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 11:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Debugging", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.Debugging = bool(v != 0)
|
||||
case 12:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field InsecureSkipHostCheck", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.InsecureSkipHostCheck = bool(v != 0)
|
||||
case 13:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field InsecureAllowFrameLoading", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.InsecureAllowFrameLoading = bool(v != 0)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGuiconfiguration(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipGuiconfiguration(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGuiconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupGuiconfiguration
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthGuiconfiguration
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthGuiconfiguration = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowGuiconfiguration = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupGuiconfiguration = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
fmt "fmt"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
_ "github.com/syncthing/syncthing/proto/ext"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
@@ -38,16 +39,25 @@ func (*LDAPConfiguration) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_9681ad7e41c73956, []int{0}
|
||||
}
|
||||
func (m *LDAPConfiguration) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_LDAPConfiguration.Unmarshal(m, b)
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *LDAPConfiguration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_LDAPConfiguration.Marshal(b, m, deterministic)
|
||||
if deterministic {
|
||||
return xxx_messageInfo_LDAPConfiguration.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *LDAPConfiguration) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_LDAPConfiguration.Merge(m, src)
|
||||
}
|
||||
func (m *LDAPConfiguration) XXX_Size() int {
|
||||
return xxx_messageInfo_LDAPConfiguration.Size(m)
|
||||
return m.ProtoSize()
|
||||
}
|
||||
func (m *LDAPConfiguration) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_LDAPConfiguration.DiscardUnknown(m)
|
||||
@@ -64,41 +74,118 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_9681ad7e41c73956 = []byte{
|
||||
// 498 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0x4d, 0x6f, 0xd3, 0x40,
|
||||
0x10, 0xb5, 0x81, 0xba, 0xc4, 0x2a, 0x15, 0x35, 0x50, 0x42, 0x55, 0x79, 0x23, 0xcb, 0x87, 0x20,
|
||||
0xa1, 0x44, 0x2a, 0xb7, 0x72, 0xaa, 0xa9, 0x40, 0x42, 0x08, 0x21, 0x17, 0x7a, 0xe0, 0x12, 0xf9,
|
||||
0x63, 0x9d, 0xac, 0xea, 0xec, 0x5a, 0xbb, 0xeb, 0xaa, 0xe1, 0x57, 0x40, 0x7f, 0x41, 0x6f, 0xfc,
|
||||
0x15, 0x6e, 0xc9, 0x91, 0xd3, 0x4a, 0x4d, 0x2e, 0xc8, 0x47, 0x1f, 0x39, 0xa1, 0xac, 0x9d, 0xc6,
|
||||
0x4e, 0xa3, 0xde, 0x66, 0xde, 0x9b, 0x79, 0xf3, 0x76, 0x47, 0xa3, 0x5b, 0x31, 0xf2, 0xbb, 0x01,
|
||||
0xc1, 0x11, 0xea, 0x77, 0xe3, 0xd0, 0x4b, 0x8a, 0x30, 0xa5, 0x1e, 0x47, 0x04, 0x77, 0x12, 0x4a,
|
||||
0x38, 0x31, 0xb4, 0x02, 0xdc, 0x33, 0x57, 0x6a, 0x39, 0xf5, 0x30, 0x4b, 0x08, 0xe5, 0x45, 0xdd,
|
||||
0x5e, 0x03, 0x5e, 0x94, 0xa1, 0xf5, 0x53, 0xd3, 0x77, 0x3e, 0x1e, 0x1f, 0x7d, 0x7e, 0x5b, 0x95,
|
||||
0x33, 0xbe, 0xea, 0x9b, 0x5e, 0x18, 0x52, 0xc8, 0x58, 0x53, 0x6d, 0xa9, 0xed, 0x86, 0xf3, 0x26,
|
||||
0x13, 0x60, 0x01, 0xe5, 0x02, 0x3c, 0xbf, 0x18, 0xc6, 0x87, 0x56, 0x99, 0xbf, 0x22, 0x43, 0xc4,
|
||||
0xe1, 0x30, 0xe1, 0x23, 0x2b, 0x1b, 0xdb, 0x3b, 0xb7, 0x50, 0x77, 0xd1, 0x68, 0x10, 0x7d, 0xd3,
|
||||
0x47, 0x38, 0xec, 0x85, 0xb8, 0x79, 0x4f, 0xca, 0x9e, 0x4e, 0x05, 0xd0, 0x1c, 0x84, 0xc3, 0xe3,
|
||||
0x4f, 0x99, 0x00, 0x9a, 0x2f, 0xa3, 0x5c, 0x80, 0x5d, 0xa9, 0x5f, 0xa4, 0x75, 0xf9, 0xc7, 0xab,
|
||||
0x60, 0x3e, 0xb6, 0xcb, 0xbe, 0xcb, 0x89, 0x5d, 0x6a, 0xb9, 0x05, 0x82, 0x8d, 0x73, 0xbd, 0x71,
|
||||
0xf3, 0xf6, 0xe6, 0xfd, 0x96, 0xda, 0xde, 0x3e, 0x78, 0xd6, 0x29, 0x3e, 0xa6, 0x33, 0x7f, 0xf5,
|
||||
0x97, 0x05, 0xe9, 0x1c, 0x65, 0x02, 0x2c, 0x6b, 0x73, 0x01, 0x5e, 0x48, 0x0b, 0x37, 0x48, 0xdd,
|
||||
0xc5, 0x93, 0x35, 0xb8, 0xbb, 0x6c, 0x37, 0x7e, 0xa9, 0xfa, 0x53, 0x84, 0x19, 0x0c, 0x52, 0x0a,
|
||||
0x7b, 0xec, 0x0c, 0x25, 0xbd, 0x73, 0x48, 0x51, 0x34, 0x6a, 0x3e, 0x68, 0xa9, 0xed, 0x87, 0x4e,
|
||||
0x9a, 0x09, 0x60, 0x2c, 0xf8, 0x93, 0x33, 0x94, 0x9c, 0x4a, 0x36, 0x17, 0xe0, 0x40, 0x4e, 0xbd,
|
||||
0x4d, 0x55, 0xc6, 0xb7, 0x42, 0x18, 0x79, 0x69, 0xcc, 0x0f, 0xad, 0xc8, 0x8b, 0x19, 0x9c, 0xdb,
|
||||
0xd9, 0xbf, 0xab, 0xe1, 0xdf, 0xd8, 0xde, 0x90, 0x95, 0xee, 0x9a, 0x91, 0xc6, 0x95, 0xaa, 0x6f,
|
||||
0x33, 0xe8, 0xd1, 0x60, 0xd0, 0xf3, 0x3d, 0x06, 0xe7, 0xab, 0xd9, 0x90, 0xab, 0xf9, 0x3e, 0x15,
|
||||
0x60, 0xeb, 0x44, 0x32, 0x8e, 0xc7, 0xa0, 0x5c, 0xd0, 0x16, 0xab, 0xe4, 0xb9, 0x00, 0xfb, 0xd2,
|
||||
0x6d, 0x15, 0xac, 0x7f, 0xd3, 0xee, 0x7a, 0x2a, 0x1f, 0xdb, 0x35, 0xa5, 0xcb, 0x89, 0x5d, 0x9b,
|
||||
0xe4, 0x56, 0x59, 0x6c, 0x10, 0xfd, 0x51, 0xe9, 0x30, 0x42, 0x31, 0x87, 0xb4, 0xa9, 0x49, 0x83,
|
||||
0x1f, 0x96, 0x86, 0xde, 0x49, 0x7c, 0xc5, 0x50, 0x01, 0xae, 0x35, 0xb4, 0x4a, 0xb9, 0x35, 0x1d,
|
||||
0xe7, 0xfd, 0xef, 0x6b, 0x53, 0x99, 0x5c, 0x9b, 0xca, 0xdf, 0xa9, 0xa9, 0xfc, 0x98, 0x99, 0xca,
|
||||
0xd5, 0xcc, 0x54, 0x27, 0x33, 0x53, 0xf9, 0x33, 0x33, 0x95, 0x6f, 0x2f, 0xfb, 0x88, 0x0f, 0x52,
|
||||
0xbf, 0x13, 0x90, 0x61, 0x97, 0x8d, 0x70, 0xc0, 0x07, 0x08, 0xf7, 0x2b, 0xd1, 0xf2, 0xf6, 0x7c,
|
||||
0x4d, 0xde, 0xd8, 0xeb, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xca, 0xa1, 0xc5, 0x0d, 0xbc, 0x03,
|
||||
0x00, 0x00,
|
||||
// 500 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0xbf, 0x6f, 0xd3, 0x40,
|
||||
0x14, 0xb6, 0x81, 0xba, 0xc4, 0x2a, 0x15, 0x35, 0x50, 0x4c, 0x55, 0xf9, 0x22, 0xcb, 0x43, 0x90,
|
||||
0x50, 0x22, 0x95, 0xad, 0x4c, 0x35, 0x15, 0x03, 0x20, 0x84, 0x5c, 0xe8, 0xc0, 0x12, 0xf9, 0xc7,
|
||||
0x39, 0x39, 0xd5, 0x39, 0x5b, 0x77, 0xe7, 0xaa, 0xe1, 0xaf, 0x80, 0xfe, 0x05, 0xdd, 0xf8, 0x57,
|
||||
0xba, 0xc5, 0x23, 0xd3, 0x49, 0x4d, 0x36, 0x8f, 0x1e, 0x99, 0x50, 0xce, 0x4e, 0x63, 0xa7, 0x51,
|
||||
0xb7, 0xf7, 0xbe, 0xef, 0xbd, 0xef, 0x7d, 0x77, 0x4f, 0x4f, 0x35, 0x23, 0xe4, 0xf5, 0xfc, 0x18,
|
||||
0x87, 0x68, 0xd0, 0x8b, 0x02, 0x37, 0x29, 0xc3, 0x94, 0xb8, 0x0c, 0xc5, 0xb8, 0x9b, 0x90, 0x98,
|
||||
0xc5, 0x9a, 0x52, 0x82, 0x7b, 0xc6, 0x4a, 0x2d, 0x23, 0x2e, 0xa6, 0x49, 0x4c, 0x58, 0x59, 0xb7,
|
||||
0xd7, 0x82, 0x17, 0x55, 0x68, 0xfe, 0x56, 0xd4, 0x9d, 0xcf, 0xc7, 0x47, 0x5f, 0xdf, 0xd7, 0xe5,
|
||||
0xb4, 0xef, 0xea, 0xa6, 0x1b, 0x04, 0x04, 0x52, 0xaa, 0xcb, 0x6d, 0xb9, 0xd3, 0xb2, 0xdf, 0xe5,
|
||||
0x1c, 0x2c, 0xa0, 0x82, 0x83, 0x97, 0x17, 0xa3, 0xe8, 0xd0, 0xac, 0xf2, 0x37, 0xf1, 0x08, 0x31,
|
||||
0x38, 0x4a, 0xd8, 0xd8, 0xcc, 0x27, 0xd6, 0xce, 0x1d, 0xd4, 0x59, 0x34, 0x6a, 0xb1, 0xba, 0xe9,
|
||||
0x21, 0x1c, 0xf4, 0x03, 0xac, 0x3f, 0x10, 0xb2, 0xa7, 0x53, 0x0e, 0x14, 0x1b, 0xe1, 0xe0, 0xf8,
|
||||
0x4b, 0xce, 0x81, 0xe2, 0x89, 0xa8, 0xe0, 0x60, 0x57, 0xe8, 0x97, 0x69, 0x53, 0xfe, 0xe9, 0x2a,
|
||||
0x58, 0x4c, 0xac, 0xaa, 0xef, 0x32, 0xb3, 0x2a, 0x2d, 0xa7, 0x44, 0xb0, 0x76, 0xae, 0xb6, 0x6e,
|
||||
0xdf, 0xae, 0x3f, 0x6c, 0xcb, 0x9d, 0xed, 0x83, 0x17, 0xdd, 0xf2, 0x63, 0xba, 0xf3, 0x57, 0x7f,
|
||||
0x5b, 0x90, 0xf6, 0x51, 0xce, 0xc1, 0xb2, 0xb6, 0xe0, 0xe0, 0x95, 0xb0, 0x70, 0x8b, 0x34, 0x5d,
|
||||
0x3c, 0x5b, 0x83, 0x3b, 0xcb, 0x76, 0xed, 0x8f, 0xac, 0x3e, 0x47, 0x98, 0x42, 0x3f, 0x25, 0xb0,
|
||||
0x4f, 0xcf, 0x50, 0xd2, 0x3f, 0x87, 0x04, 0x85, 0x63, 0xfd, 0x51, 0x5b, 0xee, 0x3c, 0xb6, 0xd3,
|
||||
0x9c, 0x03, 0x6d, 0xc1, 0x9f, 0x9c, 0xa1, 0xe4, 0x54, 0xb0, 0x05, 0x07, 0x07, 0x62, 0xea, 0x5d,
|
||||
0xaa, 0x36, 0xbe, 0x1d, 0xc0, 0xd0, 0x4d, 0x23, 0x76, 0x68, 0x86, 0x6e, 0x44, 0xe1, 0xdc, 0xce,
|
||||
0xfe, 0x7d, 0x0d, 0xff, 0x26, 0xd6, 0x86, 0xa8, 0x74, 0xd6, 0x8c, 0xd4, 0xae, 0x64, 0x75, 0x9b,
|
||||
0x42, 0x97, 0xf8, 0xc3, 0xbe, 0xe7, 0x52, 0x38, 0x5f, 0xcd, 0x86, 0x58, 0xcd, 0xcf, 0x29, 0x07,
|
||||
0x5b, 0x27, 0x82, 0xb1, 0x5d, 0x0a, 0xc5, 0x82, 0xb6, 0x68, 0x2d, 0x2f, 0x38, 0xd8, 0x17, 0x6e,
|
||||
0xeb, 0x60, 0xf3, 0x9b, 0x76, 0xd7, 0x53, 0xc5, 0xc4, 0x6a, 0x28, 0x5d, 0x66, 0x56, 0x63, 0x92,
|
||||
0x53, 0x67, 0xb1, 0x16, 0xab, 0x4f, 0x2a, 0x87, 0x21, 0x8a, 0x18, 0x24, 0xba, 0x22, 0x0c, 0x7e,
|
||||
0x5c, 0x1a, 0xfa, 0x20, 0xf0, 0x15, 0x43, 0x25, 0xb8, 0xd6, 0xd0, 0x2a, 0xe5, 0x34, 0x74, 0xec,
|
||||
0x4f, 0xd7, 0x37, 0x86, 0x94, 0xdd, 0x18, 0xd2, 0xf5, 0xd4, 0x90, 0xb3, 0xa9, 0x21, 0xff, 0x9a,
|
||||
0x19, 0xd2, 0xd5, 0xcc, 0x90, 0xb3, 0x99, 0x21, 0xfd, 0x9d, 0x19, 0xd2, 0x8f, 0xd7, 0x03, 0xc4,
|
||||
0x86, 0xa9, 0xd7, 0xf5, 0xe3, 0x51, 0x8f, 0x8e, 0xb1, 0xcf, 0x86, 0x08, 0x0f, 0x6a, 0xd1, 0xf2,
|
||||
0xfe, 0x3c, 0x45, 0xdc, 0xd9, 0xdb, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbf, 0x64, 0x4b, 0x05,
|
||||
0xc0, 0x03, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *LDAPConfiguration) Marshal() (dAtA []byte, err error) {
|
||||
size := m.ProtoSize()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *LDAPConfiguration) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.ProtoSize()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *LDAPConfiguration) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.SearchFilter) > 0 {
|
||||
i -= len(m.SearchFilter)
|
||||
copy(dAtA[i:], m.SearchFilter)
|
||||
i = encodeVarintLdapconfiguration(dAtA, i, uint64(len(m.SearchFilter)))
|
||||
i--
|
||||
dAtA[i] = 0x32
|
||||
}
|
||||
if len(m.SearchBaseDN) > 0 {
|
||||
i -= len(m.SearchBaseDN)
|
||||
copy(dAtA[i:], m.SearchBaseDN)
|
||||
i = encodeVarintLdapconfiguration(dAtA, i, uint64(len(m.SearchBaseDN)))
|
||||
i--
|
||||
dAtA[i] = 0x2a
|
||||
}
|
||||
if m.InsecureSkipVerify {
|
||||
i--
|
||||
if m.InsecureSkipVerify {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x20
|
||||
}
|
||||
if m.Transport != 0 {
|
||||
i = encodeVarintLdapconfiguration(dAtA, i, uint64(m.Transport))
|
||||
i--
|
||||
dAtA[i] = 0x18
|
||||
}
|
||||
if len(m.BindDN) > 0 {
|
||||
i -= len(m.BindDN)
|
||||
copy(dAtA[i:], m.BindDN)
|
||||
i = encodeVarintLdapconfiguration(dAtA, i, uint64(len(m.BindDN)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if len(m.Address) > 0 {
|
||||
i -= len(m.Address)
|
||||
copy(dAtA[i:], m.Address)
|
||||
i = encodeVarintLdapconfiguration(dAtA, i, uint64(len(m.Address)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintLdapconfiguration(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovLdapconfiguration(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *LDAPConfiguration) ProtoSize() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
@@ -136,3 +223,307 @@ func sovLdapconfiguration(x uint64) (n int) {
|
||||
func sozLdapconfiguration(x uint64) (n int) {
|
||||
return sovLdapconfiguration(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *LDAPConfiguration) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: LDAPConfiguration: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: LDAPConfiguration: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Address = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field BindDN", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.BindDN = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Transport", wireType)
|
||||
}
|
||||
m.Transport = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Transport |= LDAPTransport(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 4:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field InsecureSkipVerify", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.InsecureSkipVerify = bool(v != 0)
|
||||
case 5:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field SearchBaseDN", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.SearchBaseDN = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 6:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field SearchFilter", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.SearchFilter = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipLdapconfiguration(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipLdapconfiguration(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowLdapconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupLdapconfiguration
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthLdapconfiguration
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthLdapconfiguration = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowLdapconfiguration = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupLdapconfiguration = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
|
||||
@@ -53,7 +53,7 @@ func init() {
|
||||
func init() { proto.RegisterFile("lib/config/ldaptransport.proto", fileDescriptor_79795fc8505b82bf) }
|
||||
|
||||
var fileDescriptor_79795fc8505b82bf = []byte{
|
||||
// 269 bytes of a gzipped FileDescriptorProto
|
||||
// 273 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcb, 0xc9, 0x4c, 0xd2,
|
||||
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0xcf, 0x49, 0x49, 0x2c, 0x28, 0x29, 0x4a, 0xcc, 0x2b,
|
||||
0x2e, 0xc8, 0x2f, 0x2a, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0xc8, 0x49, 0x29,
|
||||
@@ -66,9 +66,10 @@ var fileDescriptor_79795fc8505b82bf = []byte{
|
||||
0x35, 0x57, 0x41, 0x00, 0x45, 0x7d, 0x88, 0x4f, 0xf0, 0xa5, 0x3e, 0x55, 0x0c, 0x31, 0xa1, 0x00,
|
||||
0x2e, 0x09, 0x34, 0x13, 0x82, 0x43, 0x1c, 0xa1, 0xe6, 0x30, 0x4b, 0x19, 0x75, 0xcd, 0x55, 0x10,
|
||||
0x45, 0xd1, 0x13, 0x5c, 0x92, 0x08, 0x33, 0x0c, 0xbb, 0x84, 0x14, 0xcb, 0x8a, 0x25, 0x72, 0x0c,
|
||||
0x4e, 0xee, 0x27, 0x1e, 0xca, 0x31, 0x5c, 0x78, 0x28, 0xc7, 0xf0, 0xe2, 0x91, 0x1c, 0xc3, 0x84,
|
||||
0xc7, 0x72, 0x0c, 0x0b, 0x1e, 0xcb, 0x31, 0x5e, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43,
|
||||
0x94, 0x66, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x71, 0x65, 0x5e,
|
||||
0x72, 0x49, 0x46, 0x66, 0x5e, 0x3a, 0x12, 0x0b, 0x11, 0x11, 0x49, 0x6c, 0xe0, 0x30, 0x34, 0x06,
|
||||
0x04, 0x00, 0x00, 0xff, 0xff, 0xc8, 0x64, 0xce, 0xb9, 0x9d, 0x01, 0x00, 0x00,
|
||||
0x4e, 0xde, 0x27, 0x1e, 0xca, 0x31, 0x5c, 0x78, 0x28, 0xc7, 0x70, 0xe2, 0x91, 0x1c, 0xe3, 0x85,
|
||||
0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x2c, 0x78, 0x2c, 0xc7, 0x78, 0xe1, 0xb1, 0x1c, 0xc3,
|
||||
0x8d, 0xc7, 0x72, 0x0c, 0x51, 0x9a, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9,
|
||||
0xfa, 0xc5, 0x95, 0x79, 0xc9, 0x25, 0x19, 0x99, 0x79, 0xe9, 0x48, 0x2c, 0x44, 0x64, 0x24, 0xb1,
|
||||
0x81, 0xc3, 0xd1, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xc1, 0x56, 0xde, 0x17, 0xa1, 0x01, 0x00,
|
||||
0x00,
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/upgrade"
|
||||
@@ -24,30 +25,33 @@ import (
|
||||
// config version. The conversion function can be nil in which case we just
|
||||
// update the config version. The order of migrations doesn't matter here,
|
||||
// put the newest on top for readability.
|
||||
var migrations = migrationSet{
|
||||
{32, migrateToConfigV32},
|
||||
{31, migrateToConfigV31},
|
||||
{30, migrateToConfigV30},
|
||||
{29, migrateToConfigV29},
|
||||
{28, migrateToConfigV28},
|
||||
{27, migrateToConfigV27},
|
||||
{26, nil}, // triggers database update
|
||||
{25, migrateToConfigV25},
|
||||
{24, migrateToConfigV24},
|
||||
{23, migrateToConfigV23},
|
||||
{22, migrateToConfigV22},
|
||||
{21, migrateToConfigV21},
|
||||
{20, migrateToConfigV20},
|
||||
{19, nil}, // Triggers a database tweak
|
||||
{18, migrateToConfigV18},
|
||||
{17, nil}, // Fsync = true removed
|
||||
{16, nil}, // Triggers a database tweak
|
||||
{15, migrateToConfigV15},
|
||||
{14, migrateToConfigV14},
|
||||
{13, migrateToConfigV13},
|
||||
{12, migrateToConfigV12},
|
||||
{11, migrateToConfigV11},
|
||||
}
|
||||
var (
|
||||
migrations = migrationSet{
|
||||
{32, migrateToConfigV32},
|
||||
{31, migrateToConfigV31},
|
||||
{30, migrateToConfigV30},
|
||||
{29, migrateToConfigV29},
|
||||
{28, migrateToConfigV28},
|
||||
{27, migrateToConfigV27},
|
||||
{26, nil}, // triggers database update
|
||||
{25, migrateToConfigV25},
|
||||
{24, migrateToConfigV24},
|
||||
{23, migrateToConfigV23},
|
||||
{22, migrateToConfigV22},
|
||||
{21, migrateToConfigV21},
|
||||
{20, migrateToConfigV20},
|
||||
{19, nil}, // Triggers a database tweak
|
||||
{18, migrateToConfigV18},
|
||||
{17, nil}, // Fsync = true removed
|
||||
{16, nil}, // Triggers a database tweak
|
||||
{15, migrateToConfigV15},
|
||||
{14, migrateToConfigV14},
|
||||
{13, migrateToConfigV13},
|
||||
{12, migrateToConfigV12},
|
||||
{11, migrateToConfigV11},
|
||||
}
|
||||
migrationsMut = sync.Mutex{}
|
||||
)
|
||||
|
||||
type migrationSet []migration
|
||||
|
||||
|
||||
@@ -26,7 +26,9 @@ func TestMigrateCrashReporting(t *testing.T) {
|
||||
|
||||
for i, tc := range cases {
|
||||
cfg := Configuration{Version: 28, Options: tc.opts}
|
||||
migrationsMut.Lock()
|
||||
migrations.apply(&cfg)
|
||||
migrationsMut.Unlock()
|
||||
if cfg.Options.CREnabled != tc.enabled {
|
||||
t.Errorf("%d: unexpected result, CREnabled: %v != %v", i, cfg.Options.CREnabled, tc.enabled)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
_ "github.com/golang/protobuf/ptypes/timestamp"
|
||||
github_com_syncthing_syncthing_lib_protocol "github.com/syncthing/syncthing/lib/protocol"
|
||||
_ "github.com/syncthing/syncthing/proto/ext"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
time "time"
|
||||
@@ -40,16 +41,25 @@ func (*ObservedFolder) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_49f68ff7b178722f, []int{0}
|
||||
}
|
||||
func (m *ObservedFolder) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ObservedFolder.Unmarshal(m, b)
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *ObservedFolder) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ObservedFolder.Marshal(b, m, deterministic)
|
||||
if deterministic {
|
||||
return xxx_messageInfo_ObservedFolder.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *ObservedFolder) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ObservedFolder.Merge(m, src)
|
||||
}
|
||||
func (m *ObservedFolder) XXX_Size() int {
|
||||
return xxx_messageInfo_ObservedFolder.Size(m)
|
||||
return m.ProtoSize()
|
||||
}
|
||||
func (m *ObservedFolder) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ObservedFolder.DiscardUnknown(m)
|
||||
@@ -71,16 +81,25 @@ func (*ObservedDevice) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_49f68ff7b178722f, []int{1}
|
||||
}
|
||||
func (m *ObservedDevice) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ObservedDevice.Unmarshal(m, b)
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *ObservedDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ObservedDevice.Marshal(b, m, deterministic)
|
||||
if deterministic {
|
||||
return xxx_messageInfo_ObservedDevice.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *ObservedDevice) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ObservedDevice.Merge(m, src)
|
||||
}
|
||||
func (m *ObservedDevice) XXX_Size() int {
|
||||
return xxx_messageInfo_ObservedDevice.Size(m)
|
||||
return m.ProtoSize()
|
||||
}
|
||||
func (m *ObservedDevice) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ObservedDevice.DiscardUnknown(m)
|
||||
@@ -96,37 +115,148 @@ func init() {
|
||||
func init() { proto.RegisterFile("lib/config/observed.proto", fileDescriptor_49f68ff7b178722f) }
|
||||
|
||||
var fileDescriptor_49f68ff7b178722f = []byte{
|
||||
// 438 bytes of a gzipped FileDescriptorProto
|
||||
// 440 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x93, 0x3f, 0x6f, 0xd4, 0x30,
|
||||
0x00, 0xc5, 0xe3, 0xf4, 0x68, 0x39, 0x53, 0xfe, 0x28, 0xd3, 0x71, 0x43, 0x5c, 0x9d, 0x32, 0x1c,
|
||||
0x02, 0x25, 0xfc, 0x9b, 0x10, 0x42, 0x22, 0x8a, 0x40, 0x27, 0x06, 0xa4, 0x88, 0x89, 0x89, 0x24,
|
||||
0x76, 0x53, 0x4b, 0x49, 0x5c, 0x25, 0x6e, 0x55, 0x36, 0x46, 0xc6, 0x96, 0x4f, 0xc0, 0xc7, 0xe9,
|
||||
0x76, 0x19, 0x11, 0x83, 0x51, 0x9b, 0x05, 0x65, 0x8c, 0xc4, 0x8e, 0x62, 0x27, 0xee, 0x4d, 0x88,
|
||||
0xa9, 0x9b, 0xdf, 0xd3, 0xf3, 0x4f, 0x7e, 0x2f, 0x0a, 0xbc, 0x9f, 0xd1, 0xd8, 0x4b, 0x58, 0xb1,
|
||||
0x4f, 0x53, 0x8f, 0xc5, 0x15, 0x29, 0x8f, 0x09, 0x76, 0x0f, 0x4b, 0xc6, 0x99, 0xb5, 0xad, 0xec,
|
||||
0x39, 0x4a, 0x19, 0x4b, 0x33, 0xe2, 0x49, 0x37, 0x3e, 0xda, 0xf7, 0x38, 0xcd, 0x49, 0xc5, 0xa3,
|
||||
0xfc, 0x50, 0x05, 0xe7, 0x53, 0x72, 0xc2, 0xd5, 0x71, 0xf1, 0x07, 0xc0, 0x3b, 0xef, 0x07, 0xcc,
|
||||
0x1b, 0x96, 0x61, 0x52, 0x5a, 0x9f, 0xe0, 0xa4, 0xbf, 0x30, 0x03, 0x7b, 0x60, 0x79, 0xeb, 0xe9,
|
||||
0xdc, 0x55, 0x34, 0x77, 0xa4, 0xb9, 0x1f, 0x46, 0x9a, 0xff, 0xf8, 0x5c, 0x20, 0xa3, 0x15, 0x48,
|
||||
0xe6, 0x3b, 0x81, 0xee, 0x9e, 0xe4, 0xd9, 0x8b, 0x45, 0x2f, 0x1e, 0x45, 0x9c, 0x97, 0x8b, 0xd3,
|
||||
0x5f, 0x08, 0xb4, 0x6b, 0x67, 0xaa, 0x9d, 0x50, 0x26, 0xad, 0x57, 0xd0, 0xa4, 0x78, 0x66, 0xee,
|
||||
0x81, 0xe5, 0xd4, 0x77, 0x2f, 0x05, 0x32, 0x57, 0x41, 0x2b, 0x90, 0x49, 0x71, 0x27, 0xd0, 0x6d,
|
||||
0xc9, 0xa0, 0x58, 0x11, 0xda, 0xb5, 0xb3, 0x33, 0x9c, 0xbf, 0xd5, 0x8e, 0xb9, 0x0a, 0x42, 0x93,
|
||||
0x62, 0xeb, 0x35, 0xbc, 0x91, 0x45, 0x31, 0xc9, 0x66, 0x5b, 0x12, 0xf1, 0xb0, 0x15, 0x48, 0x19,
|
||||
0x9d, 0x40, 0xf7, 0xe4, 0x7d, 0xa9, 0x34, 0x02, 0x5e, 0xc9, 0x50, 0x05, 0x17, 0x67, 0x5b, 0x57,
|
||||
0xbd, 0x03, 0x72, 0x4c, 0x13, 0x72, 0x0d, 0xbd, 0xcf, 0x80, 0x2e, 0xbe, 0xeb, 0x7f, 0x01, 0x3d,
|
||||
0xe5, 0xa7, 0x40, 0xcf, 0x53, 0xca, 0x0f, 0x8e, 0x62, 0x37, 0x61, 0xb9, 0x57, 0x7d, 0x2e, 0x12,
|
||||
0x7e, 0x40, 0x8b, 0x74, 0xe3, 0xd4, 0x7f, 0x70, 0xf9, 0x88, 0x84, 0x65, 0xae, 0x7a, 0xeb, 0x2a,
|
||||
0xd0, 0xab, 0xdd, 0xc4, 0x83, 0xf3, 0xaf, 0xed, 0xba, 0xb5, 0xa3, 0x73, 0x5f, 0x6b, 0x07, 0x6c,
|
||||
0x6c, 0xf9, 0x12, 0x4e, 0x8a, 0x28, 0x27, 0xc3, 0x94, 0xcb, 0xbe, 0x55, 0xaf, 0x75, 0xab, 0x5e,
|
||||
0x68, 0xde, 0x54, 0xab, 0x50, 0xa6, 0xac, 0x77, 0x70, 0x27, 0xc2, 0xb8, 0x24, 0x55, 0x35, 0x9b,
|
||||
0x48, 0xc0, 0x93, 0x56, 0xa0, 0xd1, 0xea, 0x04, 0xb2, 0x24, 0x63, 0xd0, 0x1a, 0xb3, 0xbb, 0x69,
|
||||
0x84, 0x63, 0xdc, 0x7f, 0x7b, 0x7e, 0x61, 0x1b, 0xf5, 0x85, 0x6d, 0xfc, 0xbe, 0xb4, 0x8d, 0xd3,
|
||||
0xc6, 0x36, 0xbe, 0x37, 0x36, 0xa8, 0x1b, 0xdb, 0xf8, 0xd1, 0xd8, 0xc6, 0xc7, 0x07, 0xff, 0x31,
|
||||
0x93, 0xfa, 0x01, 0xe2, 0x6d, 0x39, 0xd7, 0xb3, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xfb, 0xcb,
|
||||
0x46, 0x92, 0x2c, 0x03, 0x00, 0x00,
|
||||
0x00, 0xc5, 0xe3, 0xf4, 0x68, 0x39, 0x53, 0xfe, 0x28, 0xd3, 0x71, 0x83, 0x5d, 0x9d, 0x32, 0x1c,
|
||||
0x02, 0x25, 0xfc, 0x9b, 0x10, 0x42, 0xe2, 0x74, 0x42, 0x3a, 0x75, 0x40, 0x8a, 0x98, 0x98, 0x48,
|
||||
0x62, 0x37, 0xb5, 0x94, 0x9c, 0xab, 0xc4, 0xad, 0xca, 0xc6, 0xc8, 0xd8, 0xf2, 0x09, 0xf8, 0x38,
|
||||
0xb7, 0x5d, 0x46, 0xc4, 0x60, 0xd4, 0xcb, 0x96, 0x31, 0x12, 0x3b, 0x8a, 0x9d, 0xf8, 0x6e, 0x42,
|
||||
0x4c, 0x6c, 0x7e, 0x4f, 0xcf, 0x3f, 0xf9, 0xbd, 0x28, 0xf0, 0x61, 0xca, 0x22, 0x3f, 0xe6, 0xcb,
|
||||
0x13, 0x96, 0xf8, 0x3c, 0x2a, 0x68, 0x7e, 0x41, 0x89, 0x77, 0x96, 0x73, 0xc1, 0x9d, 0x7d, 0x6d,
|
||||
0x8f, 0x71, 0xc2, 0x79, 0x92, 0x52, 0x5f, 0xb9, 0xd1, 0xf9, 0x89, 0x2f, 0x58, 0x46, 0x0b, 0x11,
|
||||
0x66, 0x67, 0x3a, 0x38, 0x1e, 0xd2, 0x4b, 0xa1, 0x8f, 0x93, 0xdf, 0x00, 0xde, 0x7b, 0xdf, 0x61,
|
||||
0xde, 0xf1, 0x94, 0xd0, 0xdc, 0xf9, 0x04, 0x07, 0xed, 0x85, 0x11, 0x38, 0x02, 0xd3, 0x3b, 0xcf,
|
||||
0xc7, 0x9e, 0xa6, 0x79, 0x3d, 0xcd, 0xfb, 0xd0, 0xd3, 0x66, 0x4f, 0x57, 0x12, 0x5b, 0xb5, 0xc4,
|
||||
0x2a, 0xdf, 0x48, 0x7c, 0xff, 0x32, 0x4b, 0x5f, 0x4d, 0x5a, 0xf1, 0x24, 0x14, 0x22, 0x9f, 0x5c,
|
||||
0xfd, 0xc2, 0xa0, 0x5e, 0xbb, 0x43, 0xe3, 0x04, 0x2a, 0xe9, 0xbc, 0x81, 0x36, 0x23, 0x23, 0xfb,
|
||||
0x08, 0x4c, 0x87, 0x33, 0x6f, 0x23, 0xb1, 0xbd, 0x98, 0xd7, 0x12, 0xdb, 0x8c, 0x34, 0x12, 0xdf,
|
||||
0x55, 0x0c, 0x46, 0x34, 0xa1, 0x5e, 0xbb, 0x07, 0xdd, 0xf9, 0x5b, 0xe9, 0xda, 0x8b, 0x79, 0x60,
|
||||
0x33, 0xe2, 0xbc, 0x85, 0xb7, 0xd2, 0x30, 0xa2, 0xe9, 0x68, 0x4f, 0x21, 0x1e, 0xd7, 0x12, 0x6b,
|
||||
0xa3, 0x91, 0xf8, 0x81, 0xba, 0xaf, 0x94, 0x41, 0xc0, 0xad, 0x0c, 0x74, 0x70, 0x72, 0xbd, 0xb7,
|
||||
0xed, 0x3d, 0xa7, 0x17, 0x2c, 0xa6, 0xff, 0xa1, 0xf7, 0x35, 0x30, 0xc5, 0x0f, 0x67, 0x5f, 0x40,
|
||||
0x4b, 0xf9, 0x29, 0xf1, 0xcb, 0x84, 0x89, 0xd3, 0xf3, 0xc8, 0x8b, 0x79, 0xe6, 0x17, 0x9f, 0x97,
|
||||
0xb1, 0x38, 0x65, 0xcb, 0x64, 0xe7, 0xd4, 0x7e, 0x70, 0xf5, 0x88, 0x98, 0xa7, 0x9e, 0x7e, 0xeb,
|
||||
0x62, 0x6e, 0x56, 0xbb, 0x4d, 0x3a, 0xe7, 0x6f, 0xdb, 0x35, 0x6b, 0xd7, 0xe4, 0xbe, 0x96, 0x2e,
|
||||
0xd8, 0xd9, 0xf2, 0x35, 0x1c, 0x2c, 0xc3, 0x8c, 0x76, 0x53, 0x4e, 0xdb, 0x56, 0xad, 0x36, 0xad,
|
||||
0x5a, 0x61, 0x78, 0x43, 0xa3, 0x02, 0x95, 0x72, 0x8e, 0xe1, 0x41, 0x48, 0x48, 0x4e, 0x8b, 0x62,
|
||||
0x34, 0x50, 0x80, 0x67, 0xb5, 0xc4, 0xbd, 0xd5, 0x48, 0xec, 0x28, 0x46, 0xa7, 0x0d, 0xe6, 0x70,
|
||||
0xd7, 0x08, 0xfa, 0xf8, 0xec, 0x78, 0x75, 0x83, 0xac, 0xf2, 0x06, 0x59, 0xab, 0x0d, 0x02, 0xe5,
|
||||
0x06, 0x81, 0xab, 0x0a, 0x59, 0xdf, 0x2b, 0x04, 0xca, 0x0a, 0x59, 0x3f, 0x2a, 0x64, 0x7d, 0x7c,
|
||||
0xf4, 0x0f, 0x53, 0xe9, 0x9f, 0x20, 0xda, 0x57, 0x93, 0xbd, 0xf8, 0x13, 0x00, 0x00, 0xff, 0xff,
|
||||
0xd0, 0xf0, 0x82, 0x78, 0x30, 0x03, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *ObservedFolder) Marshal() (dAtA []byte, err error) {
|
||||
size := m.ProtoSize()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *ObservedFolder) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.ProtoSize()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *ObservedFolder) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Label) > 0 {
|
||||
i -= len(m.Label)
|
||||
copy(dAtA[i:], m.Label)
|
||||
i = encodeVarintObserved(dAtA, i, uint64(len(m.Label)))
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
if len(m.ID) > 0 {
|
||||
i -= len(m.ID)
|
||||
copy(dAtA[i:], m.ID)
|
||||
i = encodeVarintObserved(dAtA, i, uint64(len(m.ID)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
n1, err1 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):])
|
||||
if err1 != nil {
|
||||
return 0, err1
|
||||
}
|
||||
i -= n1
|
||||
i = encodeVarintObserved(dAtA, i, uint64(n1))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *ObservedDevice) Marshal() (dAtA []byte, err error) {
|
||||
size := m.ProtoSize()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *ObservedDevice) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.ProtoSize()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *ObservedDevice) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Address) > 0 {
|
||||
i -= len(m.Address)
|
||||
copy(dAtA[i:], m.Address)
|
||||
i = encodeVarintObserved(dAtA, i, uint64(len(m.Address)))
|
||||
i--
|
||||
dAtA[i] = 0x22
|
||||
}
|
||||
if len(m.Name) > 0 {
|
||||
i -= len(m.Name)
|
||||
copy(dAtA[i:], m.Name)
|
||||
i = encodeVarintObserved(dAtA, i, uint64(len(m.Name)))
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
{
|
||||
size := m.ID.ProtoSize()
|
||||
i -= size
|
||||
if _, err := m.ID.MarshalTo(dAtA[i:]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i = encodeVarintObserved(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
n2, err2 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):])
|
||||
if err2 != nil {
|
||||
return 0, err2
|
||||
}
|
||||
i -= n2
|
||||
i = encodeVarintObserved(dAtA, i, uint64(n2))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintObserved(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovObserved(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *ObservedFolder) ProtoSize() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
@@ -173,3 +303,420 @@ func sovObserved(x uint64) (n int) {
|
||||
func sozObserved(x uint64) (n int) {
|
||||
return sovObserved(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *ObservedFolder) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: ObservedFolder: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: ObservedFolder: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.ID = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Label", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Label = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipObserved(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *ObservedDevice) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: ObservedDevice: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: ObservedDevice: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := m.ID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Name = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Address = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipObserved(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthObserved
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipObserved(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowObserved
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthObserved
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupObserved
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthObserved
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthObserved = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowObserved = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupObserved = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
|
||||
@@ -147,3 +147,13 @@ func (opts OptionsConfiguration) MaxConcurrentIncomingRequestKiB() int {
|
||||
func (opts OptionsConfiguration) AutoUpgradeEnabled() bool {
|
||||
return opts.AutoUpgradeIntervalH > 0
|
||||
}
|
||||
|
||||
func (opts OptionsConfiguration) FeatureFlag(name string) bool {
|
||||
for _, flag := range opts.FeatureFlags {
|
||||
if flag == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -61,27 +61,27 @@ func init() {
|
||||
func init() { proto.RegisterFile("lib/config/pullorder.proto", fileDescriptor_2fa3f5222a7755bf) }
|
||||
|
||||
var fileDescriptor_2fa3f5222a7755bf = []byte{
|
||||
// 343 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xca, 0xc9, 0x4c, 0xd2,
|
||||
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x2f, 0x28, 0xcd, 0xc9, 0xc9, 0x2f, 0x4a, 0x49, 0x2d,
|
||||
0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x88, 0x4b, 0x29, 0x17, 0xa5, 0x16, 0xe4,
|
||||
0x17, 0xeb, 0x83, 0x05, 0x93, 0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3, 0xf3, 0xc1, 0x1c, 0x30, 0x0b,
|
||||
0xa2, 0x58, 0xeb, 0x32, 0x13, 0x17, 0x67, 0x40, 0x69, 0x4e, 0x8e, 0x3f, 0xc8, 0x00, 0x21, 0x2d,
|
||||
0x2e, 0xc1, 0x80, 0x50, 0x1f, 0x9f, 0x78, 0xff, 0x20, 0x17, 0xd7, 0xa0, 0xf8, 0x20, 0x47, 0x3f,
|
||||
0x17, 0x7f, 0x5f, 0x01, 0x06, 0x29, 0xe1, 0xae, 0xb9, 0x0a, 0xfc, 0x70, 0x55, 0x41, 0x89, 0x79,
|
||||
0x29, 0xf9, 0xb9, 0x42, 0x46, 0x5c, 0xa2, 0x48, 0x6a, 0x1d, 0x7d, 0x02, 0x3c, 0x1c, 0x9d, 0x5c,
|
||||
0x43, 0x3c, 0x9d, 0x05, 0x18, 0xa5, 0xc4, 0xbb, 0xe6, 0x2a, 0x08, 0xc3, 0xd5, 0x3b, 0xe6, 0x14,
|
||||
0x64, 0x24, 0x26, 0xa5, 0x96, 0x64, 0x26, 0x0b, 0x59, 0x72, 0x49, 0x22, 0xe9, 0x09, 0xf6, 0x75,
|
||||
0xf4, 0xf1, 0x71, 0x0d, 0x0e, 0x89, 0x77, 0xf3, 0x0c, 0x0a, 0x0e, 0x11, 0x60, 0x92, 0x92, 0xea,
|
||||
0x9a, 0xab, 0x20, 0x06, 0xd7, 0x17, 0x9c, 0x9b, 0x98, 0x93, 0x93, 0x5a, 0x5c, 0xe2, 0x96, 0x59,
|
||||
0x54, 0x5c, 0x22, 0x64, 0xce, 0x25, 0x81, 0xa4, 0xd5, 0xc7, 0x31, 0xc8, 0x1d, 0xa1, 0x93, 0x59,
|
||||
0x4a, 0xb2, 0x6b, 0xae, 0x82, 0x28, 0x5c, 0xa7, 0x4f, 0x62, 0x51, 0x3a, 0x5c, 0xa3, 0x29, 0x97,
|
||||
0x38, 0x92, 0x46, 0x7f, 0x1f, 0x17, 0x84, 0x3e, 0x16, 0x29, 0x89, 0xae, 0xb9, 0x0a, 0x22, 0x70,
|
||||
0x7d, 0xfe, 0x39, 0x29, 0x38, 0xb4, 0xf9, 0xb9, 0x86, 0x23, 0xb4, 0xb1, 0xa2, 0x69, 0xf3, 0x4b,
|
||||
0x2d, 0x87, 0x69, 0x93, 0x62, 0x59, 0xb1, 0x44, 0x8e, 0xc1, 0xc9, 0xfd, 0xc4, 0x43, 0x39, 0x86,
|
||||
0x0b, 0x0f, 0xe5, 0x18, 0x5e, 0x3c, 0x92, 0x63, 0x98, 0xf0, 0x58, 0x8e, 0x61, 0xc1, 0x63, 0x39,
|
||||
0xc6, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0xd2, 0x4c, 0xcf, 0x2c, 0xc9, 0x28,
|
||||
0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x2f, 0xae, 0xcc, 0x4b, 0x2e, 0xc9, 0xc8, 0xcc, 0x4b, 0x47,
|
||||
0x62, 0x21, 0xe2, 0x36, 0x89, 0x0d, 0x1c, 0x4b, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x34,
|
||||
0x1f, 0xbc, 0x31, 0xf0, 0x01, 0x00, 0x00,
|
||||
// 347 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0xd1, 0xbf, 0x4a, 0xc3, 0x40,
|
||||
0x1c, 0xc0, 0xf1, 0xa4, 0xd6, 0x82, 0xb7, 0x58, 0x53, 0x6b, 0xdb, 0x1b, 0x8e, 0x80, 0x93, 0x1d,
|
||||
0x1a, 0x50, 0x44, 0x1c, 0x53, 0x9b, 0x6a, 0xf1, 0xda, 0x94, 0xa4, 0x22, 0xb8, 0x94, 0x24, 0x4d,
|
||||
0xd3, 0xc0, 0x35, 0x17, 0xf2, 0x07, 0xf1, 0x15, 0x32, 0xf9, 0x02, 0x01, 0x07, 0x07, 0x1f, 0xa5,
|
||||
0x63, 0xc1, 0xc5, 0xb5, 0xcd, 0x8b, 0x88, 0x29, 0x26, 0x41, 0x70, 0xfb, 0xdd, 0x8f, 0xef, 0xe7,
|
||||
0x96, 0x1f, 0x80, 0xc4, 0xd6, 0x05, 0x83, 0x3a, 0x73, 0xdb, 0x12, 0xdc, 0x90, 0x10, 0xea, 0xcd,
|
||||
0x4c, 0xaf, 0xe3, 0x7a, 0x34, 0xa0, 0x5c, 0x65, 0xb7, 0x87, 0xa7, 0x9e, 0xe9, 0x52, 0x5f, 0x48,
|
||||
0x97, 0x7a, 0x38, 0x17, 0x2c, 0x6a, 0xd1, 0xf4, 0x91, 0x4e, 0xbb, 0xb8, 0xfd, 0x59, 0x02, 0x07,
|
||||
0xe3, 0x90, 0x10, 0xf9, 0xe7, 0x03, 0xae, 0x0d, 0x8e, 0xc6, 0x0f, 0x18, 0x4f, 0x65, 0xa5, 0x27,
|
||||
0x29, 0x53, 0x45, 0x1c, 0xf5, 0xe4, 0x61, 0x95, 0x81, 0xb5, 0x28, 0xe6, 0x0f, 0xb3, 0x4a, 0xd1,
|
||||
0x9c, 0x19, 0x5d, 0x72, 0xe7, 0xa0, 0x5e, 0x68, 0x45, 0x3c, 0xbe, 0x13, 0xbb, 0xd2, 0x64, 0x70,
|
||||
0x53, 0x65, 0x61, 0x23, 0x8a, 0xf9, 0x5a, 0xd6, 0x8b, 0xc4, 0x5d, 0x68, 0xba, 0x19, 0xd8, 0x06,
|
||||
0x77, 0x0d, 0x5a, 0x05, 0xa3, 0x0e, 0x45, 0x8c, 0x25, 0x75, 0x32, 0xed, 0x0f, 0x14, 0x75, 0x52,
|
||||
0x2d, 0x41, 0x18, 0xc5, 0xfc, 0x49, 0xe6, 0xd4, 0xa5, 0x46, 0x88, 0xe9, 0x07, 0x7d, 0xdb, 0xf3,
|
||||
0x03, 0xee, 0x0a, 0x34, 0x0b, 0x14, 0x8b, 0xca, 0x6d, 0x2e, 0xf7, 0x60, 0x2b, 0x8a, 0xf9, 0x7a,
|
||||
0x26, 0xb1, 0xe6, 0x59, 0x19, 0xbc, 0x04, 0x8d, 0x02, 0x94, 0x71, 0x2f, 0x77, 0x65, 0xd8, 0x8c,
|
||||
0x62, 0xfe, 0x38, 0x73, 0x32, 0x99, 0xfd, 0xc3, 0x46, 0xd2, 0x63, 0xce, 0xf6, 0xff, 0xb0, 0x91,
|
||||
0xf9, 0xfc, 0xcb, 0x60, 0xf9, 0xe3, 0x1d, 0x31, 0xdd, 0xfb, 0xd5, 0x06, 0x31, 0xeb, 0x0d, 0x62,
|
||||
0x56, 0x5b, 0xc4, 0xae, 0xb7, 0x88, 0x7d, 0x4d, 0x10, 0xf3, 0x96, 0x20, 0x76, 0x9d, 0x20, 0xe6,
|
||||
0x2b, 0x41, 0xcc, 0xd3, 0x99, 0x65, 0x07, 0x8b, 0x50, 0xef, 0x18, 0x74, 0x29, 0xf8, 0x2f, 0x8e,
|
||||
0x11, 0x2c, 0x6c, 0xc7, 0x2a, 0x4c, 0xf9, 0x7d, 0xf5, 0x4a, 0x7a, 0xa9, 0x8b, 0xef, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0x09, 0x68, 0xa0, 0x7d, 0xf4, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
@@ -73,25 +73,36 @@ func (s *Size) ParseDefault(str string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func CheckFreeSpace(req Size, usage fs.Usage) error {
|
||||
val := req.BaseValue()
|
||||
// CheckFreeSpace checks that the free space does not fall below the minimum required free space.
|
||||
func CheckFreeSpace(minFree Size, usage fs.Usage) error {
|
||||
val := minFree.BaseValue()
|
||||
if val <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if req.Percentage() {
|
||||
if minFree.Percentage() {
|
||||
freePct := (float64(usage.Free) / float64(usage.Total)) * 100
|
||||
if freePct < val {
|
||||
return fmt.Errorf("%.1f %% < %v", freePct, req)
|
||||
return fmt.Errorf("%.1f %% < %v", freePct, minFree)
|
||||
}
|
||||
} else if float64(usage.Free) < val {
|
||||
return fmt.Errorf("%sB < %v", formatSI(usage.Free), req)
|
||||
return fmt.Errorf("%sB < %v", formatSI(usage.Free), minFree)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func formatSI(b int64) string {
|
||||
// checkAvailableSpace checks that the free space does not fall below the minimum
|
||||
// required free space, considering additional required space for a future operation.
|
||||
func checkAvailableSpace(req uint64, minFree Size, usage fs.Usage) bool {
|
||||
if usage.Free < req {
|
||||
return false
|
||||
}
|
||||
usage.Free -= req
|
||||
return CheckFreeSpace(minFree, usage) == nil
|
||||
}
|
||||
|
||||
func formatSI(b uint64) string {
|
||||
switch {
|
||||
case b < 1000:
|
||||
return fmt.Sprintf("%d ", b)
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
encoding_binary "encoding/binary"
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
_ "github.com/syncthing/syncthing/proto/ext"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
@@ -34,16 +36,25 @@ func (*Size) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4d75cb8f619bd299, []int{0}
|
||||
}
|
||||
func (m *Size) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Size.Unmarshal(m, b)
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *Size) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Size.Marshal(b, m, deterministic)
|
||||
if deterministic {
|
||||
return xxx_messageInfo_Size.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *Size) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Size.Merge(m, src)
|
||||
}
|
||||
func (m *Size) XXX_Size() int {
|
||||
return xxx_messageInfo_Size.Size(m)
|
||||
return m.ProtoSize()
|
||||
}
|
||||
func (m *Size) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Size.DiscardUnknown(m)
|
||||
@@ -58,7 +69,7 @@ func init() {
|
||||
func init() { proto.RegisterFile("lib/config/size.proto", fileDescriptor_4d75cb8f619bd299) }
|
||||
|
||||
var fileDescriptor_4d75cb8f619bd299 = []byte{
|
||||
// 246 bytes of a gzipped FileDescriptorProto
|
||||
// 251 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcd, 0xc9, 0x4c, 0xd2,
|
||||
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x2f, 0xce, 0xac, 0x4a, 0xd5, 0x2b, 0x28, 0xca, 0x2f,
|
||||
0xc9, 0x17, 0x62, 0x83, 0x08, 0x49, 0x29, 0x17, 0xa5, 0x16, 0xe4, 0x17, 0xeb, 0x83, 0x05, 0x93,
|
||||
@@ -69,14 +80,61 @@ var fileDescriptor_4d75cb8f619bd299 = []byte{
|
||||
0x51, 0x4a, 0x62, 0x49, 0xa2, 0xd2, 0xab, 0xf3, 0x2a, 0x9c, 0x70, 0x5e, 0x10, 0x44, 0x99, 0x90,
|
||||
0x0d, 0x17, 0x4b, 0x69, 0x5e, 0x66, 0x89, 0x04, 0x93, 0x02, 0xa3, 0x06, 0xa7, 0x93, 0xc6, 0xab,
|
||||
0x7b, 0xf2, 0x60, 0x3e, 0x5c, 0x3b, 0x88, 0xa3, 0x93, 0x58, 0x52, 0x52, 0x04, 0xd6, 0x0e, 0xe7,
|
||||
0x05, 0x81, 0x55, 0x59, 0xb1, 0xcc, 0x58, 0x20, 0xcf, 0xe0, 0xe4, 0x7e, 0xe2, 0xa1, 0x1c, 0xc3,
|
||||
0x85, 0x87, 0x72, 0x0c, 0x2f, 0x1e, 0xc9, 0x31, 0x4c, 0x78, 0x2c, 0xc7, 0xb0, 0xe0, 0xb1, 0x1c,
|
||||
0xe3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x69, 0xa6, 0x67, 0x96, 0x64, 0x94,
|
||||
0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x17, 0x57, 0xe6, 0x25, 0x97, 0x64, 0x64, 0xe6, 0xa5, 0x23,
|
||||
0xb1, 0x10, 0x21, 0x93, 0xc4, 0x06, 0xf6, 0x9d, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x67, 0x60,
|
||||
0xd6, 0x9a, 0x2e, 0x01, 0x00, 0x00,
|
||||
0x05, 0x81, 0x55, 0x59, 0xb1, 0xcc, 0x58, 0x20, 0xcf, 0xe0, 0xe4, 0x7d, 0xe2, 0xa1, 0x1c, 0xc3,
|
||||
0x85, 0x87, 0x72, 0x0c, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c,
|
||||
0xc3, 0x82, 0xc7, 0x72, 0x8c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0xa5, 0x99,
|
||||
0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x5f, 0x5c, 0x99, 0x97, 0x5c, 0x92,
|
||||
0x91, 0x99, 0x97, 0x8e, 0xc4, 0x42, 0x84, 0x4e, 0x12, 0x1b, 0xd8, 0x87, 0xc6, 0x80, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0x65, 0x1e, 0xa3, 0x25, 0x32, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *Size) Marshal() (dAtA []byte, err error) {
|
||||
size := m.ProtoSize()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *Size) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.ProtoSize()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *Size) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Unit) > 0 {
|
||||
i -= len(m.Unit)
|
||||
copy(dAtA[i:], m.Unit)
|
||||
i = encodeVarintSize(dAtA, i, uint64(len(m.Unit)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if m.Value != 0 {
|
||||
i -= 8
|
||||
encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Value))))
|
||||
i--
|
||||
dAtA[i] = 0x9
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintSize(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovSize(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *Size) ProtoSize() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
@@ -99,3 +157,183 @@ func sovSize(x uint64) (n int) {
|
||||
func sozSize(x uint64) (n int) {
|
||||
return sovSize(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *Size) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowSize
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Size: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Size: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 1 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
|
||||
}
|
||||
var v uint64
|
||||
if (iNdEx + 8) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
v = uint64(encoding_binary.LittleEndian.Uint64(dAtA[iNdEx:]))
|
||||
iNdEx += 8
|
||||
m.Value = float64(math.Float64frombits(v))
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Unit", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowSize
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthSize
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthSize
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Unit = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipSize(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthSize
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthSize
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipSize(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowSize
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowSize
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowSize
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthSize
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupSize
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthSize
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthSize = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowSize = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupSize = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
|
||||
@@ -9,6 +9,7 @@ package config
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/util"
|
||||
)
|
||||
|
||||
@@ -66,6 +67,10 @@ func TestParseSize(t *testing.T) {
|
||||
// The empty string is a valid zero
|
||||
{"", true, 0, false},
|
||||
{" ", true, 0, false},
|
||||
// Just numbers are fine too
|
||||
{"0", true, 0, false},
|
||||
{"3", true, 3, false},
|
||||
{"34.3", true, 34.3, false},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
@@ -94,7 +99,7 @@ func TestParseSize(t *testing.T) {
|
||||
|
||||
func TestFormatSI(t *testing.T) {
|
||||
cases := []struct {
|
||||
bytes int64
|
||||
bytes uint64
|
||||
result string
|
||||
}{
|
||||
{
|
||||
@@ -130,3 +135,32 @@ func TestFormatSI(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckAvailableSize(t *testing.T) {
|
||||
cases := []struct {
|
||||
req, free, total uint64
|
||||
minFree string
|
||||
ok bool
|
||||
}{
|
||||
{10, 1e8, 1e9, "1%", true},
|
||||
{1e4, 1e3, 1e9, "1%", false},
|
||||
{1e2, 1e3, 1e9, "1%", false},
|
||||
{1e9, 1 << 62, 1 << 63, "1%", true},
|
||||
{10, 1e8, 1e9, "1M", true},
|
||||
{1e4, 1e3, 1e9, "1M", false},
|
||||
{1e2, 1e3, 1e9, "1M", false},
|
||||
{1e9, 1 << 62, 1 << 63, "1M", true},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
minFree, err := ParseSize(tc.minFree)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to parse %v: %v", tc.minFree, err)
|
||||
continue
|
||||
}
|
||||
usage := fs.Usage{Free: tc.free, Total: tc.total}
|
||||
if ok := checkAvailableSpace(tc.req, minFree, usage); ok != tc.ok {
|
||||
t.Errorf("checkAvailableSpace(%v, %v, %v) == %v, expected %v", tc.req, minFree, usage, ok, tc.ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
lib/config/testdata/overridenvalues.xml
vendored
1
lib/config/testdata/overridenvalues.xml
vendored
@@ -45,5 +45,6 @@
|
||||
<stunServer>foo</stunServer>
|
||||
<unackedNotificationID>asdfasdf</unackedNotificationID>
|
||||
<announceLANAddresses>false</announceLANAddresses>
|
||||
<featureFlag>feature</featureFlag>
|
||||
</options>
|
||||
</configuration>
|
||||
|
||||
@@ -52,7 +52,7 @@ func init() {
|
||||
func init() { proto.RegisterFile("lib/config/tuning.proto", fileDescriptor_204cfa1615fdfefd) }
|
||||
|
||||
var fileDescriptor_204cfa1615fdfefd = []byte{
|
||||
// 224 bytes of a gzipped FileDescriptorProto
|
||||
// 228 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcf, 0xc9, 0x4c, 0xd2,
|
||||
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x2f, 0x29, 0xcd, 0xcb, 0xcc, 0x4b, 0xd7, 0x2b, 0x28,
|
||||
0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x08, 0x4a, 0x29, 0x17, 0xa5, 0x16, 0xe4, 0x17, 0xeb, 0x83,
|
||||
@@ -62,9 +62,10 @@ var fileDescriptor_204cfa1615fdfefd = []byte{
|
||||
0xb4, 0x24, 0x5f, 0x48, 0x91, 0x8b, 0x07, 0xaa, 0x20, 0xd8, 0xd7, 0xd1, 0xc7, 0x47, 0x80, 0x51,
|
||||
0x8a, 0xbf, 0x6b, 0xae, 0x02, 0x37, 0x44, 0x45, 0x70, 0x6e, 0x62, 0x4e, 0x0e, 0x92, 0x12, 0x1f,
|
||||
0xc7, 0x20, 0x77, 0x57, 0x01, 0x26, 0x64, 0x25, 0x3e, 0x89, 0x45, 0xe9, 0xa9, 0x52, 0x2c, 0x2b,
|
||||
0x96, 0xc8, 0x31, 0x38, 0xb9, 0x9f, 0x78, 0x28, 0xc7, 0x70, 0xe1, 0xa1, 0x1c, 0xc3, 0x8b, 0x47,
|
||||
0x72, 0x0c, 0x13, 0x1e, 0xcb, 0x31, 0x2c, 0x78, 0x2c, 0xc7, 0x78, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d,
|
||||
0xc7, 0x72, 0x0c, 0x51, 0x9a, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa,
|
||||
0xc5, 0x95, 0x79, 0xc9, 0x25, 0x19, 0x99, 0x79, 0xe9, 0x48, 0x2c, 0x84, 0xcf, 0x93, 0xd8, 0xc0,
|
||||
0xde, 0x30, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xdf, 0xc4, 0xd9, 0x0e, 0x01, 0x00, 0x00,
|
||||
0x96, 0xc8, 0x31, 0x38, 0x79, 0x9f, 0x78, 0x28, 0xc7, 0x70, 0xe1, 0xa1, 0x1c, 0xc3, 0x89, 0x47,
|
||||
0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0xb0, 0xe0, 0xb1, 0x1c, 0xe3, 0x85,
|
||||
0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x69, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9,
|
||||
0x25, 0xe7, 0xe7, 0xea, 0x17, 0x57, 0xe6, 0x25, 0x97, 0x64, 0x64, 0xe6, 0xa5, 0x23, 0xb1, 0x10,
|
||||
0xbe, 0x4f, 0x62, 0x03, 0x7b, 0xc5, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x9f, 0x69, 0xc8, 0xbc,
|
||||
0x12, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
fmt "fmt"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
_ "github.com/syncthing/syncthing/proto/ext"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
@@ -36,16 +37,25 @@ func (*VersioningConfiguration) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_95ba6bdb22ffea81, []int{0}
|
||||
}
|
||||
func (m *VersioningConfiguration) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_VersioningConfiguration.Unmarshal(m, b)
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *VersioningConfiguration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_VersioningConfiguration.Marshal(b, m, deterministic)
|
||||
if deterministic {
|
||||
return xxx_messageInfo_VersioningConfiguration.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *VersioningConfiguration) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_VersioningConfiguration.Merge(m, src)
|
||||
}
|
||||
func (m *VersioningConfiguration) XXX_Size() int {
|
||||
return xxx_messageInfo_VersioningConfiguration.Size(m)
|
||||
return m.ProtoSize()
|
||||
}
|
||||
func (m *VersioningConfiguration) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_VersioningConfiguration.DiscardUnknown(m)
|
||||
@@ -63,33 +73,99 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_95ba6bdb22ffea81 = []byte{
|
||||
// 383 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x52, 0xcf, 0x8b, 0x9b, 0x40,
|
||||
0x18, 0x1d, 0x63, 0x22, 0x64, 0xd2, 0x5f, 0x78, 0xa9, 0x04, 0xea, 0x48, 0xea, 0xc1, 0x5e, 0x34,
|
||||
0x34, 0xb4, 0x94, 0x1c, 0x2d, 0xa5, 0xf4, 0x56, 0x52, 0x28, 0xb4, 0x97, 0x60, 0xec, 0xc4, 0x0c,
|
||||
0x35, 0xa3, 0xe8, 0x18, 0xea, 0xb1, 0x87, 0x42, 0x8f, 0xed, 0xfe, 0x05, 0xfb, 0xe7, 0xe4, 0x96,
|
||||
0x1c, 0xf7, 0x34, 0x90, 0x78, 0x59, 0x3c, 0xe6, 0x98, 0xd3, 0xe2, 0x28, 0xd9, 0xb0, 0xcb, 0xde,
|
||||
0xde, 0x7b, 0xdf, 0x7b, 0xdf, 0x93, 0xcf, 0x81, 0x56, 0x48, 0x66, 0x8e, 0x1f, 0xd1, 0x39, 0x09,
|
||||
0x9c, 0x15, 0x4e, 0x52, 0x12, 0x51, 0x42, 0x83, 0x5a, 0xc8, 0x12, 0x8f, 0x91, 0x88, 0xda, 0x71,
|
||||
0x12, 0xb1, 0x48, 0x55, 0x6a, 0xb1, 0xdf, 0xc5, 0xbf, 0x58, 0x2d, 0x0d, 0xfe, 0xc8, 0xf0, 0xf9,
|
||||
0xd7, 0x53, 0xe8, 0xfd, 0x79, 0x48, 0x35, 0x60, 0x9b, 0xe5, 0x31, 0xd6, 0x24, 0x43, 0xb2, 0xba,
|
||||
0xee, 0xa3, 0x92, 0x23, 0xc1, 0x0f, 0x1c, 0x81, 0x89, 0x40, 0xea, 0x6f, 0x09, 0xc2, 0xd8, 0x4b,
|
||||
0xbc, 0x25, 0x66, 0x38, 0x49, 0xb5, 0x96, 0x21, 0x5b, 0xbd, 0xd7, 0x8e, 0x5d, 0xd7, 0xd8, 0x0f,
|
||||
0xec, 0xb5, 0x3f, 0x9f, 0x12, 0x1f, 0x28, 0x4b, 0x72, 0x77, 0xb8, 0xe6, 0x08, 0xec, 0x39, 0x52,
|
||||
0xc4, 0x20, 0x2d, 0x39, 0x52, 0xc4, 0xd2, 0xb4, 0x6a, 0x3a, 0x6c, 0xcc, 0x86, 0x5d, 0x6c, 0xcd,
|
||||
0xc6, 0x31, 0x39, 0x2b, 0x55, 0x7d, 0xa8, 0xfa, 0x21, 0xf6, 0x68, 0x16, 0x4f, 0x09, 0x65, 0x38,
|
||||
0x59, 0x79, 0xe1, 0x34, 0xd5, 0x64, 0x43, 0xb2, 0x3a, 0xee, 0x9b, 0x92, 0xa3, 0x67, 0xcd, 0xf4,
|
||||
0x53, 0x33, 0xfc, 0x72, 0xe0, 0xe8, 0xc9, 0x0f, 0x3c, 0xf7, 0xb2, 0x90, 0x8d, 0x07, 0xa3, 0xb7,
|
||||
0xc3, 0xe1, 0xe0, 0xc8, 0x91, 0x4c, 0x28, 0x3b, 0x6e, 0xcc, 0x76, 0xc5, 0x27, 0xf7, 0x22, 0xfd,
|
||||
0x6f, 0xf0, 0xe9, 0x9d, 0xaf, 0x56, 0x5f, 0x40, 0xf9, 0x27, 0xce, 0x9b, 0xe3, 0xf4, 0x4a, 0x8e,
|
||||
0x2a, 0x2a, 0x6e, 0x53, 0x01, 0xf5, 0x25, 0xec, 0xac, 0xbc, 0x30, 0xc3, 0x5a, 0x4b, 0x18, 0x1e,
|
||||
0x97, 0x1c, 0xd5, 0x82, 0xb0, 0xd4, 0x70, 0xdc, 0x7a, 0x27, 0x8d, 0xdb, 0x7f, 0xff, 0x9b, 0xc0,
|
||||
0xfd, 0xb8, 0xde, 0xe9, 0x60, 0xbb, 0xd3, 0xc1, 0xf5, 0x5e, 0x07, 0xff, 0x0a, 0x1d, 0x5c, 0x16,
|
||||
0xba, 0xb4, 0x2d, 0x74, 0x70, 0x55, 0xe8, 0xe0, 0xfb, 0xab, 0x80, 0xb0, 0x45, 0x36, 0xb3, 0xfd,
|
||||
0x68, 0xe9, 0xa4, 0x39, 0xf5, 0xd9, 0x82, 0xd0, 0xe0, 0x0c, 0xdd, 0xbe, 0x80, 0x99, 0x22, 0xfe,
|
||||
0xeb, 0xe8, 0x26, 0x00, 0x00, 0xff, 0xff, 0x08, 0x18, 0x19, 0x5e, 0x16, 0x02, 0x00, 0x00,
|
||||
// 385 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x52, 0xbf, 0xcb, 0xd3, 0x40,
|
||||
0x18, 0xbe, 0x6b, 0xfa, 0x05, 0xbe, 0xfb, 0xfc, 0x45, 0x16, 0xc3, 0x07, 0xde, 0x85, 0x9a, 0x21,
|
||||
0x2e, 0x49, 0xf1, 0x43, 0x91, 0x8e, 0x11, 0x07, 0x71, 0x91, 0x0a, 0x82, 0x2e, 0x25, 0x8d, 0xd7,
|
||||
0xf4, 0x30, 0xbd, 0x84, 0xe4, 0x52, 0xcc, 0xe8, 0x20, 0x38, 0xaa, 0x7f, 0x81, 0x7f, 0x4e, 0xb7,
|
||||
0x66, 0x74, 0x3a, 0x68, 0xb3, 0x65, 0xec, 0xd8, 0x49, 0x72, 0x09, 0xb5, 0x28, 0x6e, 0xcf, 0xf3,
|
||||
0xbc, 0xcf, 0xf3, 0x3e, 0xe1, 0xcd, 0x21, 0x27, 0x66, 0x73, 0x2f, 0x4c, 0xf8, 0x82, 0x45, 0xde,
|
||||
0x9a, 0x66, 0x39, 0x4b, 0x38, 0xe3, 0x51, 0x27, 0x14, 0x59, 0x20, 0x58, 0xc2, 0xdd, 0x34, 0x4b,
|
||||
0x44, 0x62, 0xe8, 0x9d, 0x78, 0x7d, 0x49, 0x3f, 0x89, 0x4e, 0x1a, 0x7d, 0xd1, 0xd0, 0xfd, 0xb7,
|
||||
0xa7, 0xd0, 0xf3, 0xf3, 0x90, 0x61, 0xa1, 0xa1, 0x28, 0x53, 0x6a, 0x42, 0x0b, 0x3a, 0x97, 0xfe,
|
||||
0xad, 0x46, 0x12, 0xc5, 0x0f, 0x92, 0x80, 0xa9, 0x42, 0xc6, 0x67, 0x88, 0x50, 0x1a, 0x64, 0xc1,
|
||||
0x8a, 0x0a, 0x9a, 0xe5, 0xe6, 0xc0, 0xd2, 0x9c, 0xab, 0xc7, 0x9e, 0xdb, 0xd5, 0xb8, 0xff, 0xd9,
|
||||
0xeb, 0xbe, 0x3e, 0x25, 0x5e, 0x70, 0x91, 0x95, 0xfe, 0x78, 0x23, 0x09, 0xd8, 0x4b, 0xa2, 0xab,
|
||||
0x41, 0xde, 0x48, 0xa2, 0xab, 0xa5, 0x79, 0xdb, 0x74, 0xd8, 0xda, 0x3d, 0xfb, 0x51, 0xd9, 0xbd,
|
||||
0x63, 0x7a, 0x56, 0x6a, 0x84, 0xc8, 0x08, 0x63, 0x1a, 0xf0, 0x22, 0x9d, 0x31, 0x2e, 0x68, 0xb6,
|
||||
0x0e, 0xe2, 0x59, 0x6e, 0x6a, 0x16, 0x74, 0x2e, 0xfc, 0x27, 0x8d, 0x24, 0xf7, 0xfa, 0xe9, 0xcb,
|
||||
0x7e, 0xf8, 0xe6, 0x20, 0xc9, 0x9d, 0x0f, 0x74, 0x11, 0x14, 0xb1, 0x98, 0x8c, 0x6e, 0x9e, 0x8e,
|
||||
0xc7, 0xa3, 0xa3, 0x24, 0x1a, 0xe3, 0xe2, 0xb8, 0xb5, 0x87, 0x2d, 0x9f, 0xfe, 0x13, 0xb9, 0x7e,
|
||||
0x87, 0xee, 0xfe, 0xf5, 0xd5, 0xc6, 0x03, 0xa4, 0x7d, 0xa4, 0x65, 0x7f, 0x9c, 0xab, 0x46, 0x92,
|
||||
0x96, 0xaa, 0xdb, 0xb4, 0xc0, 0x78, 0x88, 0x2e, 0xd6, 0x41, 0x5c, 0x50, 0x73, 0xa0, 0x0c, 0xb7,
|
||||
0x1b, 0x49, 0x3a, 0x41, 0x59, 0x3a, 0x38, 0x19, 0x3c, 0x83, 0x93, 0xe1, 0xd7, 0xef, 0x36, 0xf0,
|
||||
0x5f, 0x6d, 0x76, 0x18, 0x54, 0x3b, 0x0c, 0x36, 0x7b, 0x0c, 0xab, 0x3d, 0x86, 0xdf, 0x6a, 0x0c,
|
||||
0x7e, 0xd6, 0x18, 0x56, 0x35, 0x06, 0xbf, 0x6a, 0x0c, 0xde, 0x3f, 0x8a, 0x98, 0x58, 0x16, 0x73,
|
||||
0x37, 0x4c, 0x56, 0x5e, 0x5e, 0xf2, 0x50, 0x2c, 0x19, 0x8f, 0xce, 0xd0, 0x9f, 0x57, 0x30, 0xd7,
|
||||
0xd5, 0xbf, 0xbd, 0xf9, 0x1d, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x0d, 0x6f, 0xcc, 0x1a, 0x02, 0x00,
|
||||
0x00,
|
||||
}
|
||||
|
||||
func (m *VersioningConfiguration) Marshal() (dAtA []byte, err error) {
|
||||
size := m.ProtoSize()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *VersioningConfiguration) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.ProtoSize()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *VersioningConfiguration) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.CleanupIntervalS != 0 {
|
||||
i = encodeVarintVersioningconfiguration(dAtA, i, uint64(m.CleanupIntervalS))
|
||||
i--
|
||||
dAtA[i] = 0x18
|
||||
}
|
||||
if len(m.Params) > 0 {
|
||||
for k := range m.Params {
|
||||
v := m.Params[k]
|
||||
baseI := i
|
||||
i -= len(v)
|
||||
copy(dAtA[i:], v)
|
||||
i = encodeVarintVersioningconfiguration(dAtA, i, uint64(len(v)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
i -= len(k)
|
||||
copy(dAtA[i:], k)
|
||||
i = encodeVarintVersioningconfiguration(dAtA, i, uint64(len(k)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
i = encodeVarintVersioningconfiguration(dAtA, i, uint64(baseI-i))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
}
|
||||
if len(m.Type) > 0 {
|
||||
i -= len(m.Type)
|
||||
copy(dAtA[i:], m.Type)
|
||||
i = encodeVarintVersioningconfiguration(dAtA, i, uint64(len(m.Type)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintVersioningconfiguration(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovVersioningconfiguration(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *VersioningConfiguration) ProtoSize() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
@@ -120,3 +196,318 @@ func sovVersioningconfiguration(x uint64) (n int) {
|
||||
func sozVersioningconfiguration(x uint64) (n int) {
|
||||
return sovVersioningconfiguration(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *VersioningConfiguration) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: VersioningConfiguration: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: VersioningConfiguration: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Type = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Params == nil {
|
||||
m.Params = make(map[string]string)
|
||||
}
|
||||
var mapkey string
|
||||
var mapvalue string
|
||||
for iNdEx < postIndex {
|
||||
entryPreIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
if fieldNum == 1 {
|
||||
var stringLenmapkey uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLenmapkey |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLenmapkey := int(stringLenmapkey)
|
||||
if intStringLenmapkey < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
postStringIndexmapkey := iNdEx + intStringLenmapkey
|
||||
if postStringIndexmapkey < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if postStringIndexmapkey > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
|
||||
iNdEx = postStringIndexmapkey
|
||||
} else if fieldNum == 2 {
|
||||
var stringLenmapvalue uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLenmapvalue |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLenmapvalue := int(stringLenmapvalue)
|
||||
if intStringLenmapvalue < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
postStringIndexmapvalue := iNdEx + intStringLenmapvalue
|
||||
if postStringIndexmapvalue < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if postStringIndexmapvalue > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue])
|
||||
iNdEx = postStringIndexmapvalue
|
||||
} else {
|
||||
iNdEx = entryPreIndex
|
||||
skippy, err := skipVersioningconfiguration(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) > postIndex {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
m.Params[mapkey] = mapvalue
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field CleanupIntervalS", wireType)
|
||||
}
|
||||
m.CleanupIntervalS = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.CleanupIntervalS |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipVersioningconfiguration(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipVersioningconfiguration(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowVersioningconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupVersioningconfiguration
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthVersioningconfiguration
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthVersioningconfiguration = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowVersioningconfiguration = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupVersioningconfiguration = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
|
||||
@@ -64,6 +64,7 @@ type Wrapper interface {
|
||||
GUI() GUIConfiguration
|
||||
SetGUI(gui GUIConfiguration) (Waiter, error)
|
||||
LDAP() LDAPConfiguration
|
||||
SetLDAP(ldap LDAPConfiguration) (Waiter, error)
|
||||
|
||||
Options() OptionsConfiguration
|
||||
SetOptions(opts OptionsConfiguration) (Waiter, error)
|
||||
@@ -71,11 +72,14 @@ type Wrapper interface {
|
||||
Folder(id string) (FolderConfiguration, bool)
|
||||
Folders() map[string]FolderConfiguration
|
||||
FolderList() []FolderConfiguration
|
||||
RemoveFolder(id string) (Waiter, error)
|
||||
SetFolder(fld FolderConfiguration) (Waiter, error)
|
||||
SetFolders(folders []FolderConfiguration) (Waiter, error)
|
||||
FolderPasswords(device protocol.DeviceID) map[string]string
|
||||
|
||||
Device(id protocol.DeviceID) (DeviceConfiguration, bool)
|
||||
Devices() map[protocol.DeviceID]DeviceConfiguration
|
||||
DeviceList() []DeviceConfiguration
|
||||
RemoveDevice(id protocol.DeviceID) (Waiter, error)
|
||||
SetDevice(DeviceConfiguration) (Waiter, error)
|
||||
SetDevices([]DeviceConfiguration) (Waiter, error)
|
||||
@@ -230,6 +234,13 @@ func (w *wrapper) Devices() map[protocol.DeviceID]DeviceConfiguration {
|
||||
return deviceMap
|
||||
}
|
||||
|
||||
// DeviceList returns a slice of devices.
|
||||
func (w *wrapper) DeviceList() []DeviceConfiguration {
|
||||
w.mut.Lock()
|
||||
defer w.mut.Unlock()
|
||||
return w.cfg.Copy().Devices
|
||||
}
|
||||
|
||||
// SetDevices adds new devices to the configuration, or overwrites existing
|
||||
// devices with the same ID.
|
||||
func (w *wrapper) SetDevices(devs []DeviceConfiguration) (Waiter, error) {
|
||||
@@ -327,6 +338,30 @@ func (w *wrapper) SetFolders(folders []FolderConfiguration) (Waiter, error) {
|
||||
return w.replaceLocked(newCfg)
|
||||
}
|
||||
|
||||
// RemoveFolder removes the folder from the configuration
|
||||
func (w *wrapper) RemoveFolder(id string) (Waiter, error) {
|
||||
w.mut.Lock()
|
||||
defer w.mut.Unlock()
|
||||
|
||||
newCfg := w.cfg.Copy()
|
||||
for i := range newCfg.Folders {
|
||||
if newCfg.Folders[i].ID == id {
|
||||
newCfg.Folders = append(newCfg.Folders[:i], newCfg.Folders[i+1:]...)
|
||||
return w.replaceLocked(newCfg)
|
||||
}
|
||||
}
|
||||
|
||||
return noopWaiter{}, nil
|
||||
}
|
||||
|
||||
// FolderPasswords returns the folder passwords set for this device, for
|
||||
// folders that have an encryption password set.
|
||||
func (w *wrapper) FolderPasswords(device protocol.DeviceID) map[string]string {
|
||||
w.mut.Lock()
|
||||
defer w.mut.Unlock()
|
||||
return w.cfg.FolderPasswords(device)
|
||||
}
|
||||
|
||||
// Options returns the current options configuration object.
|
||||
func (w *wrapper) Options() OptionsConfiguration {
|
||||
w.mut.Lock()
|
||||
@@ -349,6 +384,14 @@ func (w *wrapper) LDAP() LDAPConfiguration {
|
||||
return w.cfg.LDAP.Copy()
|
||||
}
|
||||
|
||||
func (w *wrapper) SetLDAP(ldap LDAPConfiguration) (Waiter, error) {
|
||||
w.mut.Lock()
|
||||
defer w.mut.Unlock()
|
||||
newCfg := w.cfg.Copy()
|
||||
newCfg.LDAP = ldap.Copy()
|
||||
return w.replaceLocked(newCfg)
|
||||
}
|
||||
|
||||
// GUI returns the current GUI configuration object.
|
||||
func (w *wrapper) GUI() GUIConfiguration {
|
||||
w.mut.Lock()
|
||||
|
||||
@@ -160,7 +160,7 @@ func (t *quicListener) URI() *url.URL {
|
||||
}
|
||||
|
||||
func (t *quicListener) WANAddresses() []*url.URL {
|
||||
uris := t.LANAddresses()
|
||||
uris := []*url.URL{t.uri}
|
||||
t.mut.Lock()
|
||||
if t.address != nil {
|
||||
uris = append(uris, t.address)
|
||||
|
||||
@@ -324,7 +324,13 @@ func (s *service) handle(ctx context.Context) {
|
||||
isLAN := s.isLAN(c.RemoteAddr())
|
||||
rd, wr := s.limiter.getLimiters(remoteID, c, isLAN)
|
||||
|
||||
protoConn := protocol.NewConnection(remoteID, rd, wr, s.model, c.String(), deviceCfg.Compression)
|
||||
var protoConn protocol.Connection
|
||||
passwords := s.cfg.FolderPasswords(remoteID)
|
||||
if len(passwords) > 0 {
|
||||
protoConn = protocol.NewEncryptedConnection(passwords, remoteID, rd, wr, s.model, c.String(), deviceCfg.Compression)
|
||||
} else {
|
||||
protoConn = protocol.NewConnection(remoteID, rd, wr, s.model, c.String(), deviceCfg.Compression)
|
||||
}
|
||||
modelConn := completeConn{c, protoConn}
|
||||
|
||||
l.Infof("Established secure connection to %s at %s", remoteID, c)
|
||||
|
||||
@@ -202,9 +202,9 @@ type genericListener interface {
|
||||
|
||||
type Model interface {
|
||||
protocol.Model
|
||||
AddConnection(conn Connection, hello protocol.HelloResult)
|
||||
AddConnection(conn Connection, hello protocol.Hello)
|
||||
Connection(remoteID protocol.DeviceID) (Connection, bool)
|
||||
OnHello(protocol.DeviceID, net.Addr, protocol.HelloResult) error
|
||||
OnHello(protocol.DeviceID, net.Addr, protocol.Hello) error
|
||||
GetHello(protocol.DeviceID) protocol.HelloIntf
|
||||
}
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ func (t *tcpListener) URI() *url.URL {
|
||||
}
|
||||
|
||||
func (t *tcpListener) WANAddresses() []*url.URL {
|
||||
uris := t.LANAddresses()
|
||||
uris := []*url.URL{t.uri}
|
||||
t.mut.RLock()
|
||||
if t.mapping != nil {
|
||||
addrs := t.mapping.ExternalAddresses()
|
||||
|
||||
@@ -131,24 +131,14 @@ const (
|
||||
)
|
||||
|
||||
func Open(path string, tuning Tuning) (Backend, error) {
|
||||
if os.Getenv("USE_BADGER") != "" {
|
||||
l.Warnln("Using experimental badger db")
|
||||
if err := maybeCopyDatabase(path, strings.Replace(path, locations.BadgerDir, locations.LevelDBDir, 1), OpenBadger, OpenLevelDBRO); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return OpenBadger(path)
|
||||
}
|
||||
|
||||
if err := maybeCopyDatabase(path, strings.Replace(path, locations.LevelDBDir, locations.BadgerDir, 1), OpenLevelDBAuto, OpenBadger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return OpenLevelDB(path, tuning)
|
||||
}
|
||||
|
||||
func OpenMemory() Backend {
|
||||
if os.Getenv("USE_BADGER") != "" {
|
||||
return OpenBadgerMemory()
|
||||
}
|
||||
return OpenLevelDBMemory()
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/db/backend"
|
||||
@@ -25,7 +24,7 @@ func genBlocks(n int) []protocol.BlockInfo {
|
||||
for j := range h {
|
||||
h[j] = byte(i + j)
|
||||
}
|
||||
b[i].Size = int32(i)
|
||||
b[i].Size = i
|
||||
b[i].Hash = h
|
||||
}
|
||||
return b
|
||||
@@ -801,11 +800,6 @@ func TestFlushRecursion(t *testing.T) {
|
||||
// Verify that a commit hook can write to the transaction without
|
||||
// causing another flush and thus recursion.
|
||||
|
||||
// Badger doesn't work like this.
|
||||
if os.Getenv("USE_BADGER") != "" {
|
||||
t.Skip("Not supported on Badger")
|
||||
}
|
||||
|
||||
db := NewLowlevel(backend.OpenMemory())
|
||||
defer db.Close()
|
||||
|
||||
|
||||
@@ -10,8 +10,10 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/dchest/siphash"
|
||||
@@ -455,7 +457,7 @@ func (db *Lowlevel) checkGlobals(folder []byte) error {
|
||||
for dbi.Next() {
|
||||
var vl VersionList
|
||||
if err := vl.Unmarshal(dbi.Value()); err != nil || vl.Empty() {
|
||||
if err := t.Delete(dbi.Key()); err != nil {
|
||||
if err := t.Delete(dbi.Key()); err != nil && !backend.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
@@ -484,7 +486,7 @@ func (db *Lowlevel) checkGlobals(folder []byte) error {
|
||||
}
|
||||
|
||||
if newVL.Empty() {
|
||||
if err := t.Delete(dbi.Key()); err != nil {
|
||||
if err := t.Delete(dbi.Key()); err != nil && !backend.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
} else if changed {
|
||||
@@ -815,13 +817,15 @@ func (db *Lowlevel) getMetaAndCheck(folder string) *metadataTracker {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil && !backend.IsClosed(err) {
|
||||
panic(err)
|
||||
l.Warnf("Fatal error: %v", err)
|
||||
obfuscateAndPanic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
var fixed int
|
||||
fixed, err = db.checkLocalNeed([]byte(folder))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("checking local need: %w", err)
|
||||
return nil
|
||||
}
|
||||
if fixed != 0 {
|
||||
@@ -830,11 +834,13 @@ func (db *Lowlevel) getMetaAndCheck(folder string) *metadataTracker {
|
||||
|
||||
meta, err := db.recalcMeta(folder)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("recalculating metadata: %w", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
fixed, err = db.repairSequenceGCLocked(folder, meta)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("repairing sequences: %w", err)
|
||||
return nil
|
||||
}
|
||||
if fixed != 0 {
|
||||
@@ -875,7 +881,7 @@ func (db *Lowlevel) recalcMeta(folderStr string) (*metadataTracker, error) {
|
||||
|
||||
meta := newMetadataTracker(db.keyer)
|
||||
if err := db.checkGlobals(folder); err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("checking globals: %w", err)
|
||||
}
|
||||
|
||||
t, err := db.newReadWriteTransaction(meta.CommitHook(folder))
|
||||
@@ -940,14 +946,16 @@ func (db *Lowlevel) verifyLocalSequence(curSeq int64, folder string) bool {
|
||||
|
||||
t, err := db.newReadOnlyTransaction()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
l.Warnf("Fatal error: %v", err)
|
||||
obfuscateAndPanic(err)
|
||||
}
|
||||
ok := true
|
||||
if err := t.withHaveSequence([]byte(folder), curSeq+1, func(fi protocol.FileIntf) bool {
|
||||
ok = false // we got something, which we should not have
|
||||
return false
|
||||
}); err != nil && !backend.IsClosed(err) {
|
||||
panic(err)
|
||||
l.Warnf("Fatal error: %v", err)
|
||||
obfuscateAndPanic(err)
|
||||
}
|
||||
t.close()
|
||||
|
||||
@@ -1094,7 +1102,7 @@ func (db *Lowlevel) checkLocalNeed(folder []byte) (int, error) {
|
||||
f := fi.(FileInfoTruncated)
|
||||
for !needDone && needName < f.Name {
|
||||
repaired++
|
||||
if err = t.Delete(dbi.Key()); err != nil {
|
||||
if err = t.Delete(dbi.Key()); err != nil && !backend.IsNotFound(err) {
|
||||
return false
|
||||
}
|
||||
l.Debugln("check local need: removing", needName)
|
||||
@@ -1121,7 +1129,7 @@ func (db *Lowlevel) checkLocalNeed(folder []byte) (int, error) {
|
||||
|
||||
for !needDone {
|
||||
repaired++
|
||||
if err := t.Delete(dbi.Key()); err != nil {
|
||||
if err := t.Delete(dbi.Key()); err != nil && !backend.IsNotFound(err) {
|
||||
return 0, err
|
||||
}
|
||||
l.Debugln("check local need: removing", needName)
|
||||
@@ -1157,3 +1165,9 @@ func (db *Lowlevel) needsRepairPath() string {
|
||||
func unchanged(nf, ef protocol.FileIntf) bool {
|
||||
return ef.FileVersion().Equal(nf.FileVersion()) && ef.IsInvalid() == nf.IsInvalid() && ef.FileLocalFlags() == nf.FileLocalFlags()
|
||||
}
|
||||
|
||||
var ldbPathRe = regexp.MustCompile(`(open|write|read) .+[\\/].+[\\/]index[^\\/]+[\\/][^\\/]+: `)
|
||||
|
||||
func obfuscateAndPanic(err error) {
|
||||
panic(ldbPathRe.ReplaceAllString(err.Error(), "$1 x: "))
|
||||
}
|
||||
|
||||
@@ -28,8 +28,12 @@ import (
|
||||
// 10-11: v1.6.0
|
||||
// 12-13: v1.7.0
|
||||
// 14: v1.9.0
|
||||
//
|
||||
// dbMigrationVersion is for migrations that do not change the schema and thus
|
||||
// do not put restrictions on downgrades (e.g. for repairs after a bugfix).
|
||||
const (
|
||||
dbVersion = 14
|
||||
dbMigrationVersion = 15
|
||||
dbMinSyncthingVersion = "v1.9.0"
|
||||
)
|
||||
|
||||
@@ -46,6 +50,8 @@ func (e *databaseDowngradeError) Error() string {
|
||||
return fmt.Sprintf("Syncthing %s required", e.minSyncthingVersion)
|
||||
}
|
||||
|
||||
// UpdateSchema updates a possibly outdated database to the current schema and
|
||||
// also does repairs where necessary.
|
||||
func UpdateSchema(db *Lowlevel) error {
|
||||
updater := &schemaUpdater{db}
|
||||
return updater.updateSchema()
|
||||
@@ -77,33 +83,44 @@ func (db *schemaUpdater) updateSchema() error {
|
||||
return err
|
||||
}
|
||||
|
||||
if prevVersion == dbVersion {
|
||||
prevMigration, _, err := miscDB.Int64("dbMigrationVersion")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Cover versions before adding `dbMigrationVersion` (== 0) and possible future weirdness.
|
||||
if prevMigration < prevVersion {
|
||||
prevMigration = prevVersion
|
||||
}
|
||||
|
||||
if prevVersion == dbVersion && prevMigration >= dbMigrationVersion {
|
||||
return nil
|
||||
}
|
||||
|
||||
type migration struct {
|
||||
schemaVersion int64
|
||||
migration func(prevVersion int) error
|
||||
schemaVersion int64
|
||||
migrationVersion int64
|
||||
migration func(prevSchema int) error
|
||||
}
|
||||
var migrations = []migration{
|
||||
{1, db.updateSchema0to1},
|
||||
{2, db.updateSchema1to2},
|
||||
{3, db.updateSchema2to3},
|
||||
{5, db.updateSchemaTo5},
|
||||
{6, db.updateSchema5to6},
|
||||
{7, db.updateSchema6to7},
|
||||
{9, db.updateSchemaTo9},
|
||||
{10, db.updateSchemaTo10},
|
||||
{11, db.updateSchemaTo11},
|
||||
{13, db.updateSchemaTo13},
|
||||
{14, db.updateSchemaTo14},
|
||||
{1, 1, db.updateSchema0to1},
|
||||
{2, 2, db.updateSchema1to2},
|
||||
{3, 3, db.updateSchema2to3},
|
||||
{5, 5, db.updateSchemaTo5},
|
||||
{6, 6, db.updateSchema5to6},
|
||||
{7, 7, db.updateSchema6to7},
|
||||
{9, 9, db.updateSchemaTo9},
|
||||
{10, 10, db.updateSchemaTo10},
|
||||
{11, 11, db.updateSchemaTo11},
|
||||
{13, 13, db.updateSchemaTo13},
|
||||
{14, 14, db.updateSchemaTo14},
|
||||
{14, 15, db.migration15},
|
||||
}
|
||||
|
||||
for _, m := range migrations {
|
||||
if prevVersion < m.schemaVersion {
|
||||
l.Infof("Migrating database to schema version %d...", m.schemaVersion)
|
||||
if prevMigration < m.migrationVersion {
|
||||
l.Infof("Running database migration %d...", m.migrationVersion)
|
||||
if err := m.migration(int(prevVersion)); err != nil {
|
||||
return fmt.Errorf("failed migrating to version %v: %w", m.schemaVersion, err)
|
||||
return fmt.Errorf("failed to do migration %v: %w", m.migrationVersion, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,6 +131,9 @@ func (db *schemaUpdater) updateSchema() error {
|
||||
if err := miscDB.PutString("dbMinSyncthingVersion", dbMinSyncthingVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := miscDB.PutInt64("dbMigrationVersion", dbMigrationVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
l.Infoln("Compacting database after migration...")
|
||||
return db.Compact()
|
||||
@@ -198,7 +218,7 @@ func (db *schemaUpdater) updateSchema0to1(_ int) error {
|
||||
// probably can't happen
|
||||
continue
|
||||
}
|
||||
if f.Type == protocol.FileInfoTypeDeprecatedSymlinkDirectory || f.Type == protocol.FileInfoTypeDeprecatedSymlinkFile {
|
||||
if f.Type == protocol.FileInfoTypeSymlinkDirectory || f.Type == protocol.FileInfoTypeSymlinkFile {
|
||||
f.Type = protocol.FileInfoTypeSymlink
|
||||
bs, err := f.Marshal()
|
||||
if err != nil {
|
||||
@@ -749,6 +769,15 @@ func (db *schemaUpdater) updateSchemaTo14(_ int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *schemaUpdater) migration15(_ int) error {
|
||||
for _, folder := range db.ListFolders() {
|
||||
if _, err := db.recalcMeta(folder); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *schemaUpdater) rewriteGlobals(t readWriteTransaction) error {
|
||||
it, err := t.NewPrefixIterator([]byte{KeyTypeGlobal})
|
||||
if err != nil {
|
||||
|
||||
@@ -532,5 +532,5 @@ func fatalError(err error, opStr string, db *Lowlevel) {
|
||||
}
|
||||
}
|
||||
l.Warnf("Fatal error: %v: %v", opStr, err)
|
||||
panic(err)
|
||||
obfuscateAndPanic(err)
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func genBlocks(n int) []protocol.BlockInfo {
|
||||
for j := range h {
|
||||
h[j] = byte(i + j)
|
||||
}
|
||||
b[i].Size = int32(i)
|
||||
b[i].Size = i
|
||||
b[i].Hash = h
|
||||
}
|
||||
return b
|
||||
@@ -227,7 +227,8 @@ func TestGlobalSet(t *testing.T) {
|
||||
t.Errorf("Global incorrect;\n A: %v !=\n E: %v", g, expectedGlobal)
|
||||
}
|
||||
|
||||
globalFiles, globalDirectories, globalDeleted, globalBytes := int32(0), int32(0), int32(0), int64(0)
|
||||
var globalFiles, globalDirectories, globalDeleted int
|
||||
var globalBytes int64
|
||||
for _, f := range g {
|
||||
if f.IsInvalid() {
|
||||
continue
|
||||
@@ -263,7 +264,8 @@ func TestGlobalSet(t *testing.T) {
|
||||
t.Errorf("Have incorrect (local);\n A: %v !=\n E: %v", h, localTot)
|
||||
}
|
||||
|
||||
haveFiles, haveDirectories, haveDeleted, haveBytes := int32(0), int32(0), int32(0), int64(0)
|
||||
var haveFiles, haveDirectories, haveDeleted int
|
||||
var haveBytes int64
|
||||
for _, f := range h {
|
||||
if f.IsInvalid() {
|
||||
continue
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
// 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/.
|
||||
|
||||
//go:generate go run ../../proto/scripts/protofmt.go structs.proto
|
||||
//go:generate protoc -I ../../ -I ../../proto -I . --gogofast_out=Mlib/protocol/bep.proto=github.com/syncthing/syncthing/lib/protocol:. structs.proto
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
@@ -26,7 +23,7 @@ func (f FileInfoTruncated) String() string {
|
||||
case protocol.FileInfoTypeFile:
|
||||
return fmt.Sprintf("File{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, Length:%d, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, BlockSize:%d}",
|
||||
f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.Size, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.RawBlockSize)
|
||||
case protocol.FileInfoTypeSymlink, protocol.FileInfoTypeDeprecatedSymlinkDirectory, protocol.FileInfoTypeDeprecatedSymlinkFile:
|
||||
case protocol.FileInfoTypeSymlink, protocol.FileInfoTypeSymlinkDirectory, protocol.FileInfoTypeSymlinkFile:
|
||||
return fmt.Sprintf("Symlink{Name:%q, Type:%v, Sequence:%d, Version:%v, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, SymlinkTarget:%q}",
|
||||
f.Name, f.Type, f.Sequence, f.Version, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.SymlinkTarget)
|
||||
default:
|
||||
@@ -64,7 +61,7 @@ func (f FileInfoTruncated) IsDirectory() bool {
|
||||
|
||||
func (f FileInfoTruncated) IsSymlink() bool {
|
||||
switch f.Type {
|
||||
case protocol.FileInfoTypeSymlink, protocol.FileInfoTypeDeprecatedSymlinkDirectory, protocol.FileInfoTypeDeprecatedSymlinkFile:
|
||||
case protocol.FileInfoTypeSymlink, protocol.FileInfoTypeSymlinkDirectory, protocol.FileInfoTypeSymlinkFile:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
@@ -183,7 +180,7 @@ func (c Counts) Add(other Counts) Counts {
|
||||
}
|
||||
}
|
||||
|
||||
func (c Counts) TotalItems() int32 {
|
||||
func (c Counts) TotalItems() int {
|
||||
return c.Files + c.Directories + c.Symlinks + c.Deleted
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: structs.proto
|
||||
// source: lib/db/structs.proto
|
||||
|
||||
package db
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
github_com_syncthing_syncthing_lib_protocol "github.com/syncthing/syncthing/lib/protocol"
|
||||
protocol "github.com/syncthing/syncthing/lib/protocol"
|
||||
_ "github.com/syncthing/syncthing/proto/ext"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
@@ -26,17 +27,17 @@ var _ = math.Inf
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type FileVersion struct {
|
||||
Version protocol.Vector `protobuf:"bytes,1,opt,name=version,proto3" json:"version"`
|
||||
Deleted bool `protobuf:"varint,2,opt,name=deleted,proto3" json:"deleted,omitempty"`
|
||||
Devices [][]byte `protobuf:"bytes,3,rep,name=devices,proto3" json:"devices,omitempty"`
|
||||
InvalidDevices [][]byte `protobuf:"bytes,4,rep,name=invalid_devices,json=invalidDevices,proto3" json:"invalid_devices,omitempty"`
|
||||
Version protocol.Vector `protobuf:"bytes,1,opt,name=version,proto3" json:"version" xml:"version"`
|
||||
Deleted bool `protobuf:"varint,2,opt,name=deleted,proto3" json:"deleted" xml:"deleted"`
|
||||
Devices [][]byte `protobuf:"bytes,3,rep,name=devices,proto3" json:"devices" xml:"device"`
|
||||
InvalidDevices [][]byte `protobuf:"bytes,4,rep,name=invalid_devices,json=invalidDevices,proto3" json:"invalidDevices" xml:"invalidDevice"`
|
||||
}
|
||||
|
||||
func (m *FileVersion) Reset() { *m = FileVersion{} }
|
||||
func (m *FileVersion) String() string { return proto.CompactTextString(m) }
|
||||
func (*FileVersion) ProtoMessage() {}
|
||||
func (*FileVersion) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e774e8f5f348d14d, []int{0}
|
||||
return fileDescriptor_5465d80e8cba02e3, []int{0}
|
||||
}
|
||||
func (m *FileVersion) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -66,13 +67,13 @@ func (m *FileVersion) XXX_DiscardUnknown() {
|
||||
var xxx_messageInfo_FileVersion proto.InternalMessageInfo
|
||||
|
||||
type VersionList struct {
|
||||
RawVersions []FileVersion `protobuf:"bytes,1,rep,name=versions,proto3" json:"versions"`
|
||||
RawVersions []FileVersion `protobuf:"bytes,1,rep,name=versions,proto3" json:"versions" xml:"version"`
|
||||
}
|
||||
|
||||
func (m *VersionList) Reset() { *m = VersionList{} }
|
||||
func (*VersionList) ProtoMessage() {}
|
||||
func (*VersionList) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e774e8f5f348d14d, []int{1}
|
||||
return fileDescriptor_5465d80e8cba02e3, []int{1}
|
||||
}
|
||||
func (m *VersionList) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -103,31 +104,32 @@ var xxx_messageInfo_VersionList proto.InternalMessageInfo
|
||||
|
||||
// Must be the same as FileInfo but without the blocks field
|
||||
type FileInfoTruncated struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Size int64 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"`
|
||||
ModifiedS int64 `protobuf:"varint,5,opt,name=modified_s,json=modifiedS,proto3" json:"modified_s,omitempty"`
|
||||
ModifiedBy github_com_syncthing_syncthing_lib_protocol.ShortID `protobuf:"varint,12,opt,name=modified_by,json=modifiedBy,proto3,customtype=github.com/syncthing/syncthing/lib/protocol.ShortID" json:"modified_by"`
|
||||
Version protocol.Vector `protobuf:"bytes,9,opt,name=version,proto3" json:"version"`
|
||||
Sequence int64 `protobuf:"varint,10,opt,name=sequence,proto3" json:"sequence,omitempty"`
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name" xml:"name"`
|
||||
Size int64 `protobuf:"varint,3,opt,name=size,proto3" json:"size" xml:"size"`
|
||||
ModifiedS int64 `protobuf:"varint,5,opt,name=modified_s,json=modifiedS,proto3" json:"modifiedS" xml:"modifiedS"`
|
||||
ModifiedBy github_com_syncthing_syncthing_lib_protocol.ShortID `protobuf:"varint,12,opt,name=modified_by,json=modifiedBy,proto3,customtype=github.com/syncthing/syncthing/lib/protocol.ShortID" json:"modifiedBy" xml:"modifiedBy"`
|
||||
Version protocol.Vector `protobuf:"bytes,9,opt,name=version,proto3" json:"version" xml:"version"`
|
||||
Sequence int64 `protobuf:"varint,10,opt,name=sequence,proto3" json:"sequence" xml:"sequence"`
|
||||
// repeated BlockInfo Blocks = 16
|
||||
SymlinkTarget string `protobuf:"bytes,17,opt,name=symlink_target,json=symlinkTarget,proto3" json:"symlink_target,omitempty"`
|
||||
BlocksHash []byte `protobuf:"bytes,18,opt,name=blocks_hash,json=blocksHash,proto3" json:"blocks_hash,omitempty"`
|
||||
Type protocol.FileInfoType `protobuf:"varint,2,opt,name=type,proto3,enum=protocol.FileInfoType" json:"type,omitempty"`
|
||||
Permissions uint32 `protobuf:"varint,4,opt,name=permissions,proto3" json:"permissions,omitempty"`
|
||||
ModifiedNs int32 `protobuf:"varint,11,opt,name=modified_ns,json=modifiedNs,proto3" json:"modified_ns,omitempty"`
|
||||
RawBlockSize int32 `protobuf:"varint,13,opt,name=block_size,json=blockSize,proto3" json:"block_size,omitempty"`
|
||||
SymlinkTarget string `protobuf:"bytes,17,opt,name=symlink_target,json=symlinkTarget,proto3" json:"symlinkTarget" xml:"symlinkTarget"`
|
||||
BlocksHash []byte `protobuf:"bytes,18,opt,name=blocks_hash,json=blocksHash,proto3" json:"blocksHash" xml:"blocksHash"`
|
||||
Encrypted []byte `protobuf:"bytes,19,opt,name=encrypted,proto3" json:"encrypted" xml:"encrypted"`
|
||||
Type protocol.FileInfoType `protobuf:"varint,2,opt,name=type,proto3,enum=protocol.FileInfoType" json:"type" xml:"type"`
|
||||
Permissions uint32 `protobuf:"varint,4,opt,name=permissions,proto3" json:"permissions" xml:"permissions"`
|
||||
ModifiedNs int `protobuf:"varint,11,opt,name=modified_ns,json=modifiedNs,proto3,casttype=int" json:"modifiedNs" xml:"modifiedNs"`
|
||||
RawBlockSize int `protobuf:"varint,13,opt,name=block_size,json=blockSize,proto3,casttype=int" json:"blockSize" xml:"blockSize"`
|
||||
// see bep.proto
|
||||
LocalFlags uint32 `protobuf:"varint,1000,opt,name=local_flags,json=localFlags,proto3" json:"local_flags,omitempty"`
|
||||
VersionHash []byte `protobuf:"bytes,1001,opt,name=version_hash,json=versionHash,proto3" json:"version_hash,omitempty"`
|
||||
Deleted bool `protobuf:"varint,6,opt,name=deleted,proto3" json:"deleted,omitempty"`
|
||||
RawInvalid bool `protobuf:"varint,7,opt,name=invalid,proto3" json:"invalid,omitempty"`
|
||||
NoPermissions bool `protobuf:"varint,8,opt,name=no_permissions,json=noPermissions,proto3" json:"no_permissions,omitempty"`
|
||||
LocalFlags uint32 `protobuf:"varint,1000,opt,name=local_flags,json=localFlags,proto3" json:"localFlags" xml:"localFlags"`
|
||||
VersionHash []byte `protobuf:"bytes,1001,opt,name=version_hash,json=versionHash,proto3" json:"versionHash" xml:"versionHash"`
|
||||
Deleted bool `protobuf:"varint,6,opt,name=deleted,proto3" json:"deleted" xml:"deleted"`
|
||||
RawInvalid bool `protobuf:"varint,7,opt,name=invalid,proto3" json:"invalid" xml:"invalid"`
|
||||
NoPermissions bool `protobuf:"varint,8,opt,name=no_permissions,json=noPermissions,proto3" json:"noPermissions" xml:"noPermissions"`
|
||||
}
|
||||
|
||||
func (m *FileInfoTruncated) Reset() { *m = FileInfoTruncated{} }
|
||||
func (*FileInfoTruncated) ProtoMessage() {}
|
||||
func (*FileInfoTruncated) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e774e8f5f348d14d, []int{2}
|
||||
return fileDescriptor_5465d80e8cba02e3, []int{2}
|
||||
}
|
||||
func (m *FileInfoTruncated) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -158,14 +160,14 @@ var xxx_messageInfo_FileInfoTruncated proto.InternalMessageInfo
|
||||
|
||||
// BlockList is the structure used to store block lists
|
||||
type BlockList struct {
|
||||
Blocks []protocol.BlockInfo `protobuf:"bytes,1,rep,name=Blocks,proto3" json:"Blocks"`
|
||||
Blocks []protocol.BlockInfo `protobuf:"bytes,1,rep,name=blocks,proto3" json:"blocks" xml:"block"`
|
||||
}
|
||||
|
||||
func (m *BlockList) Reset() { *m = BlockList{} }
|
||||
func (m *BlockList) String() string { return proto.CompactTextString(m) }
|
||||
func (*BlockList) ProtoMessage() {}
|
||||
func (*BlockList) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e774e8f5f348d14d, []int{3}
|
||||
return fileDescriptor_5465d80e8cba02e3, []int{3}
|
||||
}
|
||||
func (m *BlockList) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -197,15 +199,15 @@ var xxx_messageInfo_BlockList proto.InternalMessageInfo
|
||||
// IndirectionHashesOnly is used to only unmarshal the indirection hashes
|
||||
// from a FileInfo
|
||||
type IndirectionHashesOnly struct {
|
||||
BlocksHash []byte `protobuf:"bytes,18,opt,name=blocks_hash,json=blocksHash,proto3" json:"blocks_hash,omitempty"`
|
||||
VersionHash []byte `protobuf:"bytes,1001,opt,name=version_hash,json=versionHash,proto3" json:"version_hash,omitempty"`
|
||||
BlocksHash []byte `protobuf:"bytes,18,opt,name=blocks_hash,json=blocksHash,proto3" json:"blocksHash" xml:"blocksHash"`
|
||||
VersionHash []byte `protobuf:"bytes,1001,opt,name=version_hash,json=versionHash,proto3" json:"versionHash" xml:"versionHash"`
|
||||
}
|
||||
|
||||
func (m *IndirectionHashesOnly) Reset() { *m = IndirectionHashesOnly{} }
|
||||
func (m *IndirectionHashesOnly) String() string { return proto.CompactTextString(m) }
|
||||
func (*IndirectionHashesOnly) ProtoMessage() {}
|
||||
func (*IndirectionHashesOnly) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e774e8f5f348d14d, []int{4}
|
||||
return fileDescriptor_5465d80e8cba02e3, []int{4}
|
||||
}
|
||||
func (m *IndirectionHashesOnly) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -237,20 +239,20 @@ var xxx_messageInfo_IndirectionHashesOnly proto.InternalMessageInfo
|
||||
// For each folder and device we keep one of these to track the current
|
||||
// counts and sequence. We also keep one for the global state of the folder.
|
||||
type Counts struct {
|
||||
Files int32 `protobuf:"varint,1,opt,name=files,proto3" json:"files,omitempty"`
|
||||
Directories int32 `protobuf:"varint,2,opt,name=directories,proto3" json:"directories,omitempty"`
|
||||
Symlinks int32 `protobuf:"varint,3,opt,name=symlinks,proto3" json:"symlinks,omitempty"`
|
||||
Deleted int32 `protobuf:"varint,4,opt,name=deleted,proto3" json:"deleted,omitempty"`
|
||||
Bytes int64 `protobuf:"varint,5,opt,name=bytes,proto3" json:"bytes,omitempty"`
|
||||
Sequence int64 `protobuf:"varint,6,opt,name=sequence,proto3" json:"sequence,omitempty"`
|
||||
DeviceID []byte `protobuf:"bytes,17,opt,name=deviceID,proto3" json:"deviceID,omitempty"`
|
||||
LocalFlags uint32 `protobuf:"varint,18,opt,name=localFlags,proto3" json:"localFlags,omitempty"`
|
||||
Files int `protobuf:"varint,1,opt,name=files,proto3,casttype=int" json:"files" xml:"files"`
|
||||
Directories int `protobuf:"varint,2,opt,name=directories,proto3,casttype=int" json:"directories" xml:"directories"`
|
||||
Symlinks int `protobuf:"varint,3,opt,name=symlinks,proto3,casttype=int" json:"symlinks" xml:"symlinks"`
|
||||
Deleted int `protobuf:"varint,4,opt,name=deleted,proto3,casttype=int" json:"deleted" xml:"deleted"`
|
||||
Bytes int64 `protobuf:"varint,5,opt,name=bytes,proto3" json:"bytes" xml:"bytes"`
|
||||
Sequence int64 `protobuf:"varint,6,opt,name=sequence,proto3" json:"sequence" xml:"sequence"`
|
||||
DeviceID []byte `protobuf:"bytes,17,opt,name=device_id,json=deviceId,proto3" json:"deviceId" xml:"deviceId"`
|
||||
LocalFlags uint32 `protobuf:"varint,18,opt,name=local_flags,json=localFlags,proto3" json:"localFlags" xml:"localFlags"`
|
||||
}
|
||||
|
||||
func (m *Counts) Reset() { *m = Counts{} }
|
||||
func (*Counts) ProtoMessage() {}
|
||||
func (*Counts) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e774e8f5f348d14d, []int{5}
|
||||
return fileDescriptor_5465d80e8cba02e3, []int{5}
|
||||
}
|
||||
func (m *Counts) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -280,15 +282,15 @@ func (m *Counts) XXX_DiscardUnknown() {
|
||||
var xxx_messageInfo_Counts proto.InternalMessageInfo
|
||||
|
||||
type CountsSet struct {
|
||||
Counts []Counts `protobuf:"bytes,1,rep,name=counts,proto3" json:"counts"`
|
||||
Created int64 `protobuf:"varint,2,opt,name=created,proto3" json:"created,omitempty"`
|
||||
Counts []Counts `protobuf:"bytes,1,rep,name=counts,proto3" json:"counts" xml:"count"`
|
||||
Created int64 `protobuf:"varint,2,opt,name=created,proto3" json:"created" xml:"created"`
|
||||
}
|
||||
|
||||
func (m *CountsSet) Reset() { *m = CountsSet{} }
|
||||
func (m *CountsSet) String() string { return proto.CompactTextString(m) }
|
||||
func (*CountsSet) ProtoMessage() {}
|
||||
func (*CountsSet) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e774e8f5f348d14d, []int{6}
|
||||
return fileDescriptor_5465d80e8cba02e3, []int{6}
|
||||
}
|
||||
func (m *CountsSet) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -318,17 +320,17 @@ func (m *CountsSet) XXX_DiscardUnknown() {
|
||||
var xxx_messageInfo_CountsSet proto.InternalMessageInfo
|
||||
|
||||
type FileVersionDeprecated struct {
|
||||
Version protocol.Vector `protobuf:"bytes,1,opt,name=version,proto3" json:"version"`
|
||||
Device []byte `protobuf:"bytes,2,opt,name=device,proto3" json:"device,omitempty"`
|
||||
Invalid bool `protobuf:"varint,3,opt,name=invalid,proto3" json:"invalid,omitempty"`
|
||||
Deleted bool `protobuf:"varint,4,opt,name=deleted,proto3" json:"deleted,omitempty"`
|
||||
Version protocol.Vector `protobuf:"bytes,1,opt,name=version,proto3" json:"version" xml:"version"`
|
||||
Device []byte `protobuf:"bytes,2,opt,name=device,proto3" json:"device" xml:"device"`
|
||||
Invalid bool `protobuf:"varint,3,opt,name=invalid,proto3" json:"invalid" xml:"invalid"`
|
||||
Deleted bool `protobuf:"varint,4,opt,name=deleted,proto3" json:"deleted" xml:"deleted"`
|
||||
}
|
||||
|
||||
func (m *FileVersionDeprecated) Reset() { *m = FileVersionDeprecated{} }
|
||||
func (m *FileVersionDeprecated) String() string { return proto.CompactTextString(m) }
|
||||
func (*FileVersionDeprecated) ProtoMessage() {}
|
||||
func (*FileVersionDeprecated) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e774e8f5f348d14d, []int{7}
|
||||
return fileDescriptor_5465d80e8cba02e3, []int{7}
|
||||
}
|
||||
func (m *FileVersionDeprecated) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -358,13 +360,13 @@ func (m *FileVersionDeprecated) XXX_DiscardUnknown() {
|
||||
var xxx_messageInfo_FileVersionDeprecated proto.InternalMessageInfo
|
||||
|
||||
type VersionListDeprecated struct {
|
||||
Versions []FileVersionDeprecated `protobuf:"bytes,1,rep,name=versions,proto3" json:"versions"`
|
||||
Versions []FileVersionDeprecated `protobuf:"bytes,1,rep,name=versions,proto3" json:"versions" xml:"version"`
|
||||
}
|
||||
|
||||
func (m *VersionListDeprecated) Reset() { *m = VersionListDeprecated{} }
|
||||
func (*VersionListDeprecated) ProtoMessage() {}
|
||||
func (*VersionListDeprecated) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_e774e8f5f348d14d, []int{8}
|
||||
return fileDescriptor_5465d80e8cba02e3, []int{8}
|
||||
}
|
||||
func (m *VersionListDeprecated) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -405,64 +407,91 @@ func init() {
|
||||
proto.RegisterType((*VersionListDeprecated)(nil), "db.VersionListDeprecated")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("structs.proto", fileDescriptor_e774e8f5f348d14d) }
|
||||
func init() { proto.RegisterFile("lib/db/structs.proto", fileDescriptor_5465d80e8cba02e3) }
|
||||
|
||||
var fileDescriptor_e774e8f5f348d14d = []byte{
|
||||
// 863 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x4f, 0x8f, 0xdb, 0x54,
|
||||
0x10, 0x8f, 0x9b, 0xff, 0xe3, 0x64, 0xdb, 0xbe, 0x76, 0x57, 0x66, 0x25, 0x1c, 0x2b, 0x08, 0x61,
|
||||
0x71, 0x48, 0x60, 0x7b, 0xa3, 0x12, 0x42, 0x61, 0x55, 0x11, 0x09, 0x51, 0xf4, 0xb6, 0xf4, 0x80,
|
||||
0x2a, 0x45, 0xb6, 0xf3, 0x92, 0x3c, 0xd5, 0xf1, 0x0b, 0x7e, 0xce, 0xae, 0xd2, 0x4f, 0xc1, 0x05,
|
||||
0x89, 0x03, 0x87, 0x5e, 0xf8, 0x2e, 0x7b, 0xec, 0x11, 0x71, 0x88, 0x20, 0x7b, 0x01, 0x3e, 0x05,
|
||||
0x7a, 0xf3, 0x9e, 0x1d, 0x6f, 0x38, 0xd0, 0xde, 0x66, 0x7e, 0x33, 0xcf, 0x33, 0xf3, 0x9b, 0x9f,
|
||||
0x07, 0xba, 0x32, 0x4b, 0xd7, 0x51, 0x26, 0x07, 0xab, 0x54, 0x64, 0x82, 0xdc, 0x99, 0x86, 0xa7,
|
||||
0x1f, 0xa4, 0x6c, 0x25, 0xe4, 0x10, 0x81, 0x70, 0x3d, 0x1b, 0xce, 0xc5, 0x5c, 0xa0, 0x83, 0x96,
|
||||
0x4e, 0x3c, 0x3d, 0x89, 0x79, 0xa8, 0x53, 0x22, 0x11, 0x0f, 0x43, 0xb6, 0xd2, 0x78, 0xff, 0x17,
|
||||
0x0b, 0xec, 0x27, 0x3c, 0x66, 0xcf, 0x59, 0x2a, 0xb9, 0x48, 0xc8, 0x27, 0xd0, 0xbc, 0xd4, 0xa6,
|
||||
0x63, 0x79, 0x96, 0x6f, 0x9f, 0xdd, 0x1b, 0xe4, 0xaf, 0x06, 0xcf, 0x59, 0x94, 0x89, 0x74, 0x54,
|
||||
0xbb, 0xde, 0xf6, 0x2a, 0x34, 0x4f, 0x23, 0x0e, 0x34, 0xa7, 0x2c, 0x66, 0x19, 0x9b, 0x3a, 0x77,
|
||||
0x3c, 0xcb, 0x6f, 0xd1, 0xdc, 0xd5, 0x91, 0x4b, 0x1e, 0x31, 0xe9, 0x54, 0xbd, 0xaa, 0xdf, 0xa1,
|
||||
0xb9, 0x4b, 0x3e, 0x82, 0xbb, 0x3c, 0xb9, 0x0c, 0x62, 0x3e, 0x9d, 0xe4, 0x19, 0x35, 0xcc, 0x38,
|
||||
0x32, 0xf0, 0xb9, 0x46, 0xfb, 0xdf, 0x81, 0x6d, 0x3a, 0xfb, 0x9a, 0xcb, 0x8c, 0x7c, 0x01, 0x2d,
|
||||
0x53, 0x56, 0x3a, 0x96, 0x57, 0xf5, 0xed, 0xb3, 0xbb, 0x83, 0x69, 0x38, 0x28, 0x0d, 0x30, 0x7a,
|
||||
0xa0, 0xba, 0xdb, 0x6d, 0x7b, 0x36, 0x0d, 0xae, 0x0c, 0x26, 0x69, 0xf1, 0xea, 0xb3, 0xda, 0xcf,
|
||||
0xaf, 0x7b, 0x95, 0xfe, 0xaf, 0x75, 0xb8, 0xaf, 0x1e, 0x8d, 0x93, 0x99, 0x78, 0x96, 0xae, 0x93,
|
||||
0x28, 0x50, 0xfd, 0x12, 0xa8, 0x25, 0xc1, 0x92, 0xe1, 0xe0, 0x6d, 0x8a, 0xb6, 0xc2, 0x24, 0x7f,
|
||||
0xc5, 0x9c, 0xaa, 0x67, 0xf9, 0x55, 0x8a, 0x36, 0x79, 0x1f, 0x60, 0x29, 0xa6, 0x7c, 0xc6, 0xd9,
|
||||
0x74, 0x22, 0x9d, 0x3a, 0x46, 0xda, 0x39, 0x72, 0x41, 0x5e, 0x80, 0x5d, 0x84, 0xc3, 0x8d, 0xd3,
|
||||
0xf1, 0x2c, 0xbf, 0x36, 0x7a, 0xac, 0xda, 0xfa, 0x7d, 0xdb, 0x7b, 0x34, 0xe7, 0xd9, 0x62, 0x1d,
|
||||
0x0e, 0x22, 0xb1, 0x1c, 0xca, 0x4d, 0x12, 0x65, 0x0b, 0x9e, 0xcc, 0x4b, 0x56, 0x79, 0x4d, 0x83,
|
||||
0x8b, 0x85, 0x48, 0xb3, 0xf1, 0x39, 0x2d, 0xca, 0x8d, 0x36, 0xe5, 0x05, 0xb5, 0xdf, 0x6e, 0x41,
|
||||
0xa7, 0xd0, 0x92, 0xec, 0x87, 0x35, 0x4b, 0x22, 0xe6, 0x00, 0x36, 0x5b, 0xf8, 0xe4, 0x43, 0x38,
|
||||
0x92, 0x9b, 0x65, 0xcc, 0x93, 0x97, 0x93, 0x2c, 0x48, 0xe7, 0x2c, 0x73, 0xee, 0xe3, 0xf0, 0x5d,
|
||||
0x83, 0x3e, 0x43, 0x90, 0xf4, 0xc0, 0x0e, 0x63, 0x11, 0xbd, 0x94, 0x93, 0x45, 0x20, 0x17, 0x0e,
|
||||
0xf1, 0x2c, 0xbf, 0x43, 0x41, 0x43, 0x5f, 0x05, 0x72, 0x41, 0x3e, 0x86, 0x5a, 0xb6, 0x59, 0x31,
|
||||
0x54, 0xc0, 0xd1, 0xd9, 0xc9, 0xbe, 0xa5, 0x82, 0xe5, 0xcd, 0x8a, 0x51, 0xcc, 0x21, 0x1e, 0xd8,
|
||||
0x2b, 0x96, 0x2e, 0xb9, 0xd4, 0x7b, 0xac, 0x79, 0x96, 0xdf, 0xa5, 0x65, 0x48, 0x95, 0x2b, 0x18,
|
||||
0x4c, 0xa4, 0x63, 0x7b, 0x96, 0x5f, 0xdf, 0x93, 0xf0, 0x8d, 0x24, 0x43, 0xd0, 0xc5, 0x27, 0xb8,
|
||||
0x9b, 0xae, 0x8a, 0x8f, 0xee, 0xed, 0xb6, 0xbd, 0x0e, 0x0d, 0xae, 0x46, 0x2a, 0x70, 0xc1, 0x5f,
|
||||
0x31, 0xda, 0x0e, 0x73, 0x53, 0xd5, 0x8c, 0x45, 0x14, 0xc4, 0x93, 0x59, 0x1c, 0xcc, 0xa5, 0xf3,
|
||||
0x57, 0x13, 0x8b, 0x02, 0x62, 0x4f, 0x14, 0x44, 0xfa, 0xd0, 0x31, 0x84, 0xe9, 0x19, 0xff, 0x6e,
|
||||
0xe2, 0x90, 0xb6, 0x01, 0x71, 0xca, 0x92, 0xd4, 0x1b, 0xb7, 0xa5, 0xee, 0x43, 0xd3, 0x28, 0xd7,
|
||||
0x51, 0xef, 0x5a, 0xa3, 0xa3, 0xdd, 0xb6, 0x07, 0x34, 0xb8, 0x1a, 0x6b, 0x94, 0xe6, 0x61, 0xc5,
|
||||
0x78, 0x22, 0x26, 0x65, 0x02, 0x5a, 0xf8, 0xa9, 0x6e, 0x22, 0xbe, 0xdd, 0x83, 0x46, 0xa7, 0x9f,
|
||||
0x43, 0x1b, 0xc7, 0x41, 0xf1, 0x7f, 0x0a, 0x0d, 0x74, 0x72, 0xe9, 0x3f, 0xd8, 0xb3, 0x8c, 0xb8,
|
||||
0xa2, 0xd9, 0xec, 0xde, 0x24, 0xf6, 0x5f, 0xc0, 0xf1, 0x38, 0x99, 0xf2, 0x94, 0x45, 0x99, 0x99,
|
||||
0x81, 0xc9, 0xa7, 0x49, 0xbc, 0xf9, 0xff, 0x85, 0xbe, 0x05, 0x1d, 0xfd, 0x7f, 0x2c, 0x68, 0x7c,
|
||||
0x29, 0xd6, 0x49, 0x26, 0xc9, 0x43, 0xa8, 0xcf, 0x78, 0xcc, 0x24, 0xfe, 0x3b, 0x75, 0xaa, 0x1d,
|
||||
0xc5, 0xba, 0x2e, 0x2e, 0x52, 0xce, 0x24, 0x8a, 0xa3, 0x4e, 0xcb, 0x10, 0x6a, 0x53, 0x2b, 0x4d,
|
||||
0xe2, 0x2f, 0x56, 0xa7, 0x85, 0x5f, 0x66, 0xbb, 0x86, 0xa1, 0x82, 0xed, 0x87, 0x50, 0x0f, 0x37,
|
||||
0x19, 0xcb, 0xff, 0x3d, 0xed, 0xdc, 0xd2, 0x79, 0xe3, 0x40, 0xe7, 0xa7, 0xd0, 0xd2, 0x87, 0x66,
|
||||
0x7c, 0x8e, 0x0a, 0xef, 0xd0, 0xc2, 0x27, 0x2e, 0x94, 0x74, 0x80, 0x54, 0xdc, 0x52, 0x86, 0x59,
|
||||
0xc5, 0x53, 0x68, 0xeb, 0x59, 0x2f, 0x58, 0x46, 0x7c, 0x68, 0x44, 0xe8, 0x98, 0x55, 0x80, 0xba,
|
||||
0x42, 0x3a, 0x9c, 0x6f, 0x40, 0xc7, 0xd5, 0x10, 0x51, 0xca, 0x82, 0xfc, 0x3a, 0x56, 0x69, 0xee,
|
||||
0xf6, 0x7f, 0xb2, 0xe0, 0xb8, 0x74, 0xb8, 0xce, 0xd9, 0x2a, 0x65, 0xfa, 0x0e, 0xbd, 0xfb, 0x0d,
|
||||
0x3e, 0x81, 0x86, 0x1e, 0x07, 0x8b, 0x74, 0xa8, 0xf1, 0x54, 0xf5, 0x5c, 0x96, 0x55, 0x2d, 0xd8,
|
||||
0x5c, 0x86, 0x07, 0xe4, 0xee, 0xa5, 0xdc, 0xff, 0x1e, 0x8e, 0x4b, 0x27, 0xb7, 0xd4, 0xd6, 0xe3,
|
||||
0xff, 0x1c, 0xdf, 0xf7, 0x0e, 0x8e, 0xef, 0x3e, 0xd9, 0x34, 0x78, 0x70, 0x77, 0x47, 0xde, 0xf5,
|
||||
0x9f, 0x6e, 0xe5, 0x7a, 0xe7, 0x5a, 0x6f, 0x76, 0xae, 0xf5, 0xc7, 0xce, 0xad, 0xfc, 0x78, 0xe3,
|
||||
0x56, 0x5e, 0xdf, 0xb8, 0xd6, 0x9b, 0x1b, 0xb7, 0xf2, 0xdb, 0x8d, 0x5b, 0x09, 0x1b, 0x38, 0xe9,
|
||||
0xa3, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x47, 0xe4, 0x5e, 0xea, 0xe8, 0x06, 0x00, 0x00,
|
||||
var fileDescriptor_5465d80e8cba02e3 = []byte{
|
||||
// 1289 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcf, 0x6f, 0xdc, 0x44,
|
||||
0x14, 0x5e, 0x67, 0x7f, 0x64, 0x77, 0x76, 0x93, 0x36, 0x2e, 0xad, 0x4c, 0x81, 0x9d, 0x65, 0x9a,
|
||||
0x4a, 0x0b, 0x48, 0x1b, 0x29, 0x55, 0x2b, 0x54, 0x09, 0xaa, 0xba, 0x51, 0xdb, 0x54, 0xa5, 0x45,
|
||||
0x93, 0xaa, 0x20, 0x2e, 0xab, 0xb5, 0x77, 0x92, 0x58, 0x75, 0xec, 0xc5, 0xe3, 0x34, 0xdd, 0xde,
|
||||
0xb8, 0x20, 0x71, 0x43, 0x15, 0x07, 0x84, 0x10, 0xea, 0x89, 0x3f, 0x81, 0xbf, 0xa1, 0xc7, 0x1c,
|
||||
0x11, 0x07, 0x4b, 0x4d, 0x2e, 0xb0, 0xc7, 0x3d, 0x21, 0x4e, 0x68, 0xde, 0x8c, 0xc7, 0xb3, 0x8d,
|
||||
0x8a, 0xda, 0x92, 0x9b, 0xdf, 0xf7, 0xbe, 0xf7, 0x6c, 0xbf, 0xf9, 0xde, 0x9b, 0x87, 0xde, 0x0a,
|
||||
0x03, 0x6f, 0x65, 0xe8, 0xad, 0xf0, 0x34, 0xd9, 0xf5, 0x53, 0xde, 0x1b, 0x25, 0x71, 0x1a, 0xdb,
|
||||
0x73, 0x43, 0xef, 0xec, 0xb9, 0x84, 0x8d, 0x62, 0xbe, 0x02, 0x80, 0xb7, 0xbb, 0xb9, 0xb2, 0x15,
|
||||
0x6f, 0xc5, 0x60, 0xc0, 0x93, 0x24, 0x9e, 0x3d, 0x23, 0xc2, 0xe1, 0xd1, 0x8f, 0xc3, 0x15, 0x8f,
|
||||
0x8d, 0x14, 0xde, 0x60, 0x8f, 0x52, 0xf9, 0x48, 0x7e, 0x99, 0x43, 0xcd, 0xeb, 0x41, 0xc8, 0xee,
|
||||
0xb3, 0x84, 0x07, 0x71, 0x64, 0xdf, 0x46, 0xf3, 0x0f, 0xe5, 0xa3, 0x63, 0x75, 0xac, 0x6e, 0x73,
|
||||
0xf5, 0x64, 0x2f, 0x4f, 0xd0, 0xbb, 0xcf, 0xfc, 0x34, 0x4e, 0xdc, 0xce, 0xb3, 0x0c, 0x97, 0x26,
|
||||
0x19, 0xce, 0x89, 0xd3, 0x0c, 0x2f, 0x3c, 0xda, 0x09, 0x2f, 0x13, 0x65, 0x13, 0x9a, 0x7b, 0xec,
|
||||
0x4b, 0x68, 0x7e, 0xc8, 0x42, 0x96, 0xb2, 0xa1, 0x33, 0xd7, 0xb1, 0xba, 0x75, 0xf7, 0x5d, 0x11,
|
||||
0xa7, 0x20, 0x1d, 0xa7, 0x6c, 0x42, 0x73, 0x8f, 0x7d, 0x51, 0xc4, 0x3d, 0x0c, 0x7c, 0xc6, 0x9d,
|
||||
0x72, 0xa7, 0xdc, 0x6d, 0xb9, 0xef, 0xc8, 0x38, 0x80, 0xa6, 0x19, 0x6e, 0xa9, 0x38, 0x61, 0x43,
|
||||
0x18, 0x38, 0x6c, 0x8a, 0x4e, 0x04, 0xd1, 0xc3, 0x41, 0x18, 0x0c, 0xfb, 0x79, 0x78, 0x05, 0xc2,
|
||||
0x3f, 0x98, 0x64, 0x78, 0x51, 0xb9, 0xd6, 0x74, 0x96, 0x53, 0x90, 0x65, 0x06, 0x26, 0xf4, 0x05,
|
||||
0x1a, 0xf9, 0xc6, 0x42, 0x4d, 0x55, 0x9c, 0xdb, 0x01, 0x4f, 0xed, 0x10, 0xd5, 0xd5, 0xdf, 0x71,
|
||||
0xc7, 0xea, 0x94, 0xbb, 0xcd, 0xd5, 0x13, 0xbd, 0xa1, 0xd7, 0x33, 0x6a, 0xe8, 0x5e, 0x11, 0x05,
|
||||
0x3a, 0xc8, 0x70, 0x93, 0x0e, 0xf6, 0x14, 0xc6, 0x27, 0x19, 0xd6, 0x71, 0x47, 0x0a, 0xf6, 0x64,
|
||||
0x7f, 0xd9, 0xe4, 0x52, 0xcd, 0xbc, 0x5c, 0xf9, 0xf1, 0x29, 0x2e, 0x91, 0xbf, 0x11, 0x5a, 0x12,
|
||||
0x2f, 0x58, 0x8f, 0x36, 0xe3, 0x7b, 0xc9, 0x6e, 0xe4, 0x0f, 0x44, 0x91, 0x3e, 0x44, 0x95, 0x68,
|
||||
0xb0, 0xc3, 0xe0, 0x9c, 0x1a, 0xee, 0x99, 0x49, 0x86, 0xc1, 0x9e, 0x66, 0x18, 0x41, 0x76, 0x61,
|
||||
0x10, 0x0a, 0x98, 0xe0, 0xf2, 0xe0, 0x31, 0x73, 0xca, 0x1d, 0xab, 0x5b, 0x96, 0x5c, 0x61, 0x6b,
|
||||
0xae, 0x30, 0x08, 0x05, 0xcc, 0xbe, 0x82, 0xd0, 0x4e, 0x3c, 0x0c, 0x36, 0x03, 0x36, 0xec, 0x73,
|
||||
0xa7, 0x0a, 0x11, 0x9d, 0x49, 0x86, 0x1b, 0x39, 0xba, 0x31, 0xcd, 0xf0, 0x09, 0x08, 0xd3, 0x08,
|
||||
0xa1, 0x85, 0xd7, 0xfe, 0xcd, 0x42, 0x4d, 0x9d, 0xc1, 0x1b, 0x3b, 0xad, 0x8e, 0xd5, 0xad, 0xb8,
|
||||
0x3f, 0x58, 0xa2, 0x2c, 0x7f, 0x64, 0xf8, 0xc2, 0x56, 0x90, 0x6e, 0xef, 0x7a, 0x3d, 0x3f, 0xde,
|
||||
0x59, 0xe1, 0xe3, 0xc8, 0x4f, 0xb7, 0x83, 0x68, 0xcb, 0x78, 0x32, 0x45, 0xdb, 0xdb, 0xd8, 0x8e,
|
||||
0x93, 0x74, 0x7d, 0x6d, 0x92, 0x61, 0xfd, 0x51, 0xee, 0x78, 0x9a, 0xe1, 0x93, 0x33, 0xef, 0x77,
|
||||
0xc7, 0xe4, 0xa7, 0xfd, 0xe5, 0x37, 0x49, 0x4c, 0x8d, 0xb4, 0xa6, 0xf8, 0x1b, 0xff, 0x5f, 0xfc,
|
||||
0x97, 0x51, 0x9d, 0xb3, 0xaf, 0x77, 0x59, 0xe4, 0x33, 0x07, 0x41, 0x15, 0xdb, 0x42, 0x05, 0x39,
|
||||
0x36, 0xcd, 0xf0, 0xa2, 0xac, 0xbd, 0x02, 0x08, 0xd5, 0x3e, 0xfb, 0x2e, 0x5a, 0xe4, 0xe3, 0x9d,
|
||||
0x30, 0x88, 0x1e, 0xf4, 0xd3, 0x41, 0xb2, 0xc5, 0x52, 0x67, 0x09, 0x4e, 0xb9, 0x3b, 0xc9, 0xf0,
|
||||
0x82, 0xf2, 0xdc, 0x03, 0x87, 0xd6, 0xf1, 0x0c, 0x4a, 0xe8, 0x2c, 0xcb, 0xbe, 0x86, 0x9a, 0x5e,
|
||||
0x18, 0xfb, 0x0f, 0x78, 0x7f, 0x7b, 0xc0, 0xb7, 0x1d, 0xbb, 0x63, 0x75, 0x5b, 0x2e, 0x11, 0x65,
|
||||
0x95, 0xf0, 0xcd, 0x01, 0xdf, 0xd6, 0x65, 0x2d, 0x20, 0x42, 0x0d, 0xbf, 0xfd, 0x29, 0x6a, 0xb0,
|
||||
0xc8, 0x4f, 0xc6, 0x23, 0xd1, 0xd0, 0xa7, 0x20, 0x05, 0x08, 0x43, 0x83, 0x5a, 0x18, 0x1a, 0x21,
|
||||
0xb4, 0xf0, 0xda, 0x2e, 0xaa, 0xa4, 0xe3, 0x11, 0x83, 0x59, 0xb0, 0xb8, 0x7a, 0xa6, 0x28, 0xae,
|
||||
0x16, 0xf7, 0x78, 0xc4, 0xa4, 0x3a, 0x05, 0x4f, 0xab, 0x53, 0x18, 0x84, 0x02, 0x66, 0x5f, 0x47,
|
||||
0xcd, 0x11, 0x4b, 0x76, 0x02, 0x2e, 0x5b, 0xb0, 0xd2, 0xb1, 0xba, 0x0b, 0xee, 0xf2, 0x24, 0xc3,
|
||||
0x26, 0x3c, 0xcd, 0xf0, 0x12, 0x44, 0x1a, 0x18, 0xa1, 0x26, 0xc3, 0xbe, 0x65, 0x68, 0x34, 0xe2,
|
||||
0x4e, 0xb3, 0x63, 0x75, 0xab, 0x30, 0x27, 0xb4, 0x20, 0xee, 0xf0, 0x23, 0x3a, 0xbb, 0xc3, 0xc9,
|
||||
0x3f, 0x19, 0x2e, 0x07, 0x51, 0x4a, 0x0d, 0x9a, 0xbd, 0x89, 0x64, 0x95, 0xfa, 0xd0, 0x63, 0x0b,
|
||||
0x90, 0xea, 0xc6, 0x41, 0x86, 0x5b, 0x74, 0xb0, 0xe7, 0x0a, 0xc7, 0x46, 0xf0, 0x98, 0x89, 0x42,
|
||||
0x79, 0xb9, 0xa1, 0x0b, 0xa5, 0x91, 0x3c, 0xf1, 0x93, 0xfd, 0xe5, 0x99, 0x30, 0x5a, 0x04, 0xd9,
|
||||
0x6b, 0xa8, 0x19, 0xc6, 0xfe, 0x20, 0xec, 0x6f, 0x86, 0x83, 0x2d, 0xee, 0xfc, 0x39, 0x0f, 0x3f,
|
||||
0x0f, 0xa7, 0x08, 0xf8, 0x75, 0x01, 0xeb, 0x8f, 0x2e, 0x20, 0x42, 0x0d, 0xbf, 0x7d, 0x13, 0xb5,
|
||||
0x94, 0x44, 0xa5, 0x16, 0xfe, 0x9a, 0x87, 0x93, 0x84, 0x1a, 0x2a, 0x87, 0x52, 0xc3, 0x92, 0xa9,
|
||||
0x6c, 0x29, 0x07, 0x93, 0x61, 0x8e, 0xf7, 0xda, 0xeb, 0x8c, 0x77, 0x8a, 0xe6, 0xd5, 0x94, 0x75,
|
||||
0xe6, 0x21, 0xee, 0xe3, 0x83, 0x0c, 0x23, 0x3a, 0xd8, 0x5b, 0x97, 0xa8, 0xc8, 0xa2, 0x08, 0x3a,
|
||||
0x8b, 0xb2, 0xc5, 0xac, 0x34, 0x98, 0x34, 0xe7, 0x89, 0x8e, 0x89, 0xe2, 0xbe, 0x29, 0x8d, 0x3a,
|
||||
0xa4, 0x86, 0x8e, 0x89, 0xe2, 0xcf, 0x67, 0xc4, 0x21, 0x3b, 0x66, 0x06, 0x25, 0x74, 0x96, 0xa5,
|
||||
0x46, 0xef, 0x17, 0xa8, 0x01, 0x47, 0x01, 0xb3, 0xff, 0x16, 0xaa, 0xc9, 0x6e, 0x50, 0x93, 0xff,
|
||||
0x54, 0xa1, 0x60, 0x20, 0x09, 0x09, 0xbb, 0xef, 0xa9, 0x09, 0xa1, 0xa8, 0xd3, 0x0c, 0x37, 0x8b,
|
||||
0x93, 0x26, 0x54, 0xc1, 0xe4, 0x57, 0x0b, 0x9d, 0x5e, 0x8f, 0x86, 0x41, 0xc2, 0xfc, 0x54, 0xd5,
|
||||
0x93, 0xf1, 0xbb, 0x51, 0x38, 0x3e, 0x9e, 0x56, 0x3d, 0xb6, 0x43, 0x26, 0x3f, 0x57, 0x50, 0xed,
|
||||
0x5a, 0xbc, 0x1b, 0xa5, 0xdc, 0xbe, 0x88, 0xaa, 0x9b, 0x41, 0xc8, 0x38, 0x5c, 0x39, 0x55, 0x17,
|
||||
0x4f, 0x32, 0x2c, 0x01, 0xfd, 0x93, 0x60, 0xe9, 0x1e, 0x91, 0x4e, 0xfb, 0x33, 0xd4, 0x94, 0xff,
|
||||
0x19, 0x27, 0x01, 0xe3, 0xd0, 0xfd, 0x55, 0xf7, 0x23, 0xf1, 0x25, 0x06, 0xac, 0xbf, 0xc4, 0xc0,
|
||||
0x74, 0x22, 0x93, 0x68, 0x5f, 0x45, 0x75, 0x35, 0xdb, 0x38, 0xdc, 0x67, 0x55, 0xf7, 0x3c, 0xcc,
|
||||
0x55, 0x85, 0x15, 0x73, 0x55, 0x01, 0x3a, 0x8b, 0xa6, 0xd8, 0x9f, 0x14, 0xc2, 0xad, 0x40, 0x86,
|
||||
0x73, 0xff, 0x25, 0xdc, 0x3c, 0x5e, 0xeb, 0xb7, 0x87, 0xaa, 0xde, 0x38, 0x65, 0xf9, 0xe5, 0xe8,
|
||||
0x88, 0x3a, 0x00, 0x50, 0x1c, 0xb6, 0xb0, 0x08, 0x95, 0xe8, 0xcc, 0x4d, 0x50, 0x7b, 0xcd, 0x9b,
|
||||
0x60, 0x03, 0x35, 0xe4, 0x2e, 0xd3, 0x0f, 0x86, 0x70, 0x09, 0xb4, 0xdc, 0x4b, 0x07, 0x19, 0xae,
|
||||
0xcb, 0xfd, 0x04, 0x6e, 0xc6, 0xba, 0x24, 0xac, 0x0f, 0x75, 0xa2, 0x1c, 0x10, 0xdd, 0xa2, 0x99,
|
||||
0x54, 0xf3, 0x84, 0xc4, 0xcc, 0x41, 0x62, 0xbf, 0xc9, 0x1c, 0x51, 0x0d, 0xf2, 0xad, 0x85, 0x1a,
|
||||
0x52, 0x1e, 0x1b, 0x2c, 0xb5, 0xaf, 0xa2, 0x9a, 0x0f, 0x86, 0xea, 0x10, 0x24, 0x76, 0x23, 0xe9,
|
||||
0x2e, 0x1a, 0x43, 0x32, 0x74, 0xad, 0xc0, 0x24, 0x54, 0xc1, 0x62, 0xa8, 0xf8, 0x09, 0x1b, 0xe4,
|
||||
0x3b, 0x63, 0x59, 0x0e, 0x15, 0x05, 0xe9, 0xb3, 0x51, 0x36, 0xa1, 0xb9, 0x87, 0x7c, 0x37, 0x87,
|
||||
0x4e, 0x1b, 0x5b, 0xd8, 0x1a, 0x1b, 0x25, 0x4c, 0x2e, 0x4a, 0xc7, 0xbb, 0xd3, 0xae, 0xa2, 0x9a,
|
||||
0xac, 0x23, 0x7c, 0x5e, 0xcb, 0x3d, 0x2b, 0x7e, 0x49, 0x22, 0x47, 0x36, 0x53, 0x85, 0x8b, 0x7f,
|
||||
0xca, 0x07, 0x5e, 0xb9, 0x18, 0x94, 0x2f, 0x1b, 0x71, 0xc5, 0x50, 0xbb, 0x34, 0xab, 0xd3, 0x57,
|
||||
0x1d, 0xb0, 0x64, 0x0f, 0x9d, 0x36, 0x76, 0x56, 0xa3, 0x14, 0x5f, 0x1e, 0xd9, 0x5e, 0xdf, 0x7e,
|
||||
0x61, 0x7b, 0x2d, 0xc8, 0xee, 0xfb, 0xaa, 0x28, 0x2f, 0x5f, 0x5c, 0x5f, 0xdc, 0x54, 0xdd, 0x1b,
|
||||
0xcf, 0x9e, 0xb7, 0x4b, 0xfb, 0xcf, 0xdb, 0xa5, 0x67, 0x07, 0x6d, 0x6b, 0xff, 0xa0, 0x6d, 0x7d,
|
||||
0x7f, 0xd8, 0x2e, 0x3d, 0x3d, 0x6c, 0x5b, 0xfb, 0x87, 0xed, 0xd2, 0xef, 0x87, 0xed, 0xd2, 0x57,
|
||||
0xe7, 0x5f, 0x61, 0x49, 0x1b, 0x7a, 0x5e, 0x0d, 0x4e, 0xe8, 0xc2, 0xbf, 0x01, 0x00, 0x00, 0xff,
|
||||
0xff, 0xfc, 0x01, 0x79, 0xc2, 0x02, 0x0d, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *FileVersion) Marshal() (dAtA []byte, err error) {
|
||||
@@ -599,6 +628,15 @@ func (m *FileInfoTruncated) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i--
|
||||
dAtA[i] = 0xc0
|
||||
}
|
||||
if len(m.Encrypted) > 0 {
|
||||
i -= len(m.Encrypted)
|
||||
copy(dAtA[i:], m.Encrypted)
|
||||
i = encodeVarintStructs(dAtA, i, uint64(len(m.Encrypted)))
|
||||
i--
|
||||
dAtA[i] = 0x1
|
||||
i--
|
||||
dAtA[i] = 0x9a
|
||||
}
|
||||
if len(m.BlocksHash) > 0 {
|
||||
i -= len(m.BlocksHash)
|
||||
copy(dAtA[i:], m.BlocksHash)
|
||||
@@ -1098,6 +1136,10 @@ func (m *FileInfoTruncated) ProtoSize() (n int) {
|
||||
if l > 0 {
|
||||
n += 2 + l + sovStructs(uint64(l))
|
||||
}
|
||||
l = len(m.Encrypted)
|
||||
if l > 0 {
|
||||
n += 2 + l + sovStructs(uint64(l))
|
||||
}
|
||||
if m.LocalFlags != 0 {
|
||||
n += 2 + sovStructs(uint64(m.LocalFlags))
|
||||
}
|
||||
@@ -1754,7 +1796,7 @@ func (m *FileInfoTruncated) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.ModifiedNs |= int32(b&0x7F) << shift
|
||||
m.ModifiedNs |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
@@ -1792,7 +1834,7 @@ func (m *FileInfoTruncated) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.RawBlockSize |= int32(b&0x7F) << shift
|
||||
m.RawBlockSize |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
@@ -1863,6 +1905,40 @@ func (m *FileInfoTruncated) Unmarshal(dAtA []byte) error {
|
||||
m.BlocksHash = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 19:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Encrypted", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowStructs
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthStructs
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Encrypted = append(m.Encrypted[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.Encrypted == nil {
|
||||
m.Encrypted = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 1000:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field LocalFlags", wireType)
|
||||
@@ -2191,7 +2267,7 @@ func (m *Counts) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Files |= int32(b&0x7F) << shift
|
||||
m.Files |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
@@ -2210,7 +2286,7 @@ func (m *Counts) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Directories |= int32(b&0x7F) << shift
|
||||
m.Directories |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
@@ -2229,7 +2305,7 @@ func (m *Counts) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Symlinks |= int32(b&0x7F) << shift
|
||||
m.Symlinks |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
@@ -2248,7 +2324,7 @@ func (m *Counts) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Deleted |= int32(b&0x7F) << shift
|
||||
m.Deleted |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
|
||||
@@ -859,7 +859,7 @@ func (t readWriteTransaction) removeFromGlobal(gk, keyBuf, folder, device, file
|
||||
continue
|
||||
}
|
||||
if fv, have := fl.Get(dev[:]); Need(removedFV, have, fv.Version) {
|
||||
meta.removeNeeded(deviceID, f)
|
||||
meta.removeNeeded(dev, f)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"github.com/syncthing/syncthing/lib/util"
|
||||
)
|
||||
|
||||
type EventType int
|
||||
type EventType int64
|
||||
|
||||
const (
|
||||
Starting EventType = 1 << iota
|
||||
@@ -52,6 +52,7 @@ const (
|
||||
FolderWatchStateChanged
|
||||
ListenAddressesChanged
|
||||
LoginAttempt
|
||||
Failure
|
||||
|
||||
AllEvents = (1 << iota) - 1
|
||||
)
|
||||
@@ -121,6 +122,8 @@ func (t EventType) String() string {
|
||||
return "LoginAttempt"
|
||||
case FolderWatchStateChanged:
|
||||
return "FolderWatchStateChanged"
|
||||
case Failure:
|
||||
return "Failure"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
@@ -200,6 +203,8 @@ func UnmarshalEventType(s string) EventType {
|
||||
return LoginAttempt
|
||||
case "FolderWatchStateChanged":
|
||||
return FolderWatchStateChanged
|
||||
case "Failure":
|
||||
return Failure
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -19,8 +19,11 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidFilename = errors.New("filename is invalid")
|
||||
ErrNotRelative = errors.New("not a relative path")
|
||||
errInvalidFilenameEmpty = errors.New("name is invalid, must not be empty")
|
||||
errInvalidFilenameWindowsSpacePeriod = errors.New("name is invalid, must not end in space or period on Windows")
|
||||
errInvalidFilenameWindowsReservedName = errors.New("name is invalid, contains Windows reserved name (NUL, COM1, etc.)")
|
||||
errInvalidFilenameWindowsReservedChar = errors.New("name is invalid, contains Windows reserved character (?, *, etc.)")
|
||||
errNotRelative = errors.New("not a relative path")
|
||||
)
|
||||
|
||||
func WithJunctionsAsDirs() Option {
|
||||
@@ -95,7 +98,7 @@ func (f *BasicFilesystem) rooted(rel string) (string, error) {
|
||||
func rooted(rel, root string) (string, error) {
|
||||
// The root must not be empty.
|
||||
if root == "" {
|
||||
return "", ErrInvalidFilename
|
||||
return "", errInvalidFilenameEmpty
|
||||
}
|
||||
|
||||
var err error
|
||||
@@ -292,8 +295,8 @@ func (f *BasicFilesystem) Usage(name string) (Usage, error) {
|
||||
return Usage{}, err
|
||||
}
|
||||
return Usage{
|
||||
Free: int64(u.Free),
|
||||
Total: int64(u.Total),
|
||||
Free: u.Free,
|
||||
Total: u.Total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -4,40 +4,20 @@
|
||||
// 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 linux,!ppc,!ppc64,!ppc64le
|
||||
// +build linux
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
"io"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCopyRangeImplementation(CopyRangeMethodIoctl, copyRangeImplementationForBasicFile(copyRangeIoctl))
|
||||
}
|
||||
|
||||
const FICLONE = 0x40049409
|
||||
const FICLONERANGE = 0x4020940d
|
||||
|
||||
/*
|
||||
http://man7.org/linux/man-pages/man2/ioctl_ficlonerange.2.html
|
||||
|
||||
struct file_clone_range {
|
||||
__s64 src_fd;
|
||||
__u64 src_offset;
|
||||
__u64 src_length;
|
||||
__u64 dest_offset;
|
||||
};
|
||||
*/
|
||||
type fileCloneRange struct {
|
||||
srcFd int64
|
||||
srcOffset uint64
|
||||
srcLength uint64
|
||||
dstOffset uint64
|
||||
}
|
||||
|
||||
func copyRangeIoctl(src, dst basicFile, srcOffset, dstOffset, size int64) error {
|
||||
fi, err := src.Stat()
|
||||
if err != nil {
|
||||
@@ -56,38 +36,20 @@ func copyRangeIoctl(src, dst basicFile, srcOffset, dstOffset, size int64) error
|
||||
|
||||
if srcOffset == 0 && dstOffset == 0 && size == 0 {
|
||||
// Optimization for whole file copies.
|
||||
var errNo syscall.Errno
|
||||
_, err := withFileDescriptors(src, dst, func(srcFd, dstFd uintptr) (int, error) {
|
||||
_, _, errNo = syscall.Syscall(syscall.SYS_IOCTL, dstFd, FICLONE, srcFd)
|
||||
return 0, nil
|
||||
return 0, unix.IoctlFileClone(int(dstFd), int(srcFd))
|
||||
})
|
||||
// Failure in withFileDescriptors
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if errNo != 0 {
|
||||
return errNo
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var errNo syscall.Errno
|
||||
_, err = withFileDescriptors(src, dst, func(srcFd, dstFd uintptr) (int, error) {
|
||||
params := fileCloneRange{
|
||||
srcFd: int64(srcFd),
|
||||
srcOffset: uint64(srcOffset),
|
||||
srcLength: uint64(size),
|
||||
dstOffset: uint64(dstOffset),
|
||||
}
|
||||
_, _, errNo = syscall.Syscall(syscall.SYS_IOCTL, dstFd, FICLONERANGE, uintptr(unsafe.Pointer(¶ms)))
|
||||
return 0, nil
|
||||
})
|
||||
// Failure in withFileDescriptors
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if errNo != 0 {
|
||||
return errNo
|
||||
}
|
||||
return nil
|
||||
|
||||
_, err = withFileDescriptors(src, dst, func(srcFd, dstFd uintptr) (int, error) {
|
||||
params := unix.FileCloneRange{
|
||||
Src_fd: int64(srcFd),
|
||||
Src_offset: uint64(srcOffset),
|
||||
Src_length: uint64(size),
|
||||
Dest_offset: uint64(dstOffset),
|
||||
}
|
||||
return 0, unix.IoctlFileCloneRange(int(dstFd), ¶ms)
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ package fs
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
@@ -60,28 +61,30 @@ func init() {
|
||||
func init() { proto.RegisterFile("lib/fs/copyrangemethod.proto", fileDescriptor_78e1061c3022e87e) }
|
||||
|
||||
var fileDescriptor_78e1061c3022e87e = []byte{
|
||||
// 357 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0xbf, 0x4e, 0xc2, 0x40,
|
||||
0x00, 0xc6, 0x0b, 0xa8, 0x43, 0x17, 0x9b, 0xc6, 0x04, 0x53, 0xc8, 0x59, 0x25, 0x2e, 0x0e, 0x30,
|
||||
0x18, 0x27, 0x5d, 0x8e, 0xf6, 0x0a, 0x0d, 0x47, 0x21, 0x50, 0x83, 0xba, 0x34, 0xfd, 0x07, 0x6d,
|
||||
0x3c, 0xda, 0x86, 0x1e, 0x89, 0xbc, 0x42, 0x27, 0x5f, 0xa0, 0x89, 0x9b, 0xaf, 0xe2, 0xc8, 0xe8,
|
||||
0x8a, 0x5d, 0x7c, 0x0c, 0x43, 0x59, 0x4c, 0x61, 0xbb, 0xfb, 0xbe, 0xfc, 0x7e, 0xf9, 0x92, 0x3b,
|
||||
0xb6, 0x4e, 0x7c, 0xab, 0x35, 0x8d, 0x5b, 0x76, 0x18, 0xad, 0x16, 0x66, 0x30, 0x73, 0xe7, 0x2e,
|
||||
0xf5, 0x42, 0xa7, 0x19, 0x2d, 0x42, 0x1a, 0xf2, 0xe5, 0x69, 0x7c, 0xf3, 0x59, 0x61, 0x4f, 0xa5,
|
||||
0x30, 0x5a, 0x8d, 0xb6, 0x6d, 0x3f, 0x6f, 0xf9, 0x7b, 0x56, 0x90, 0x06, 0xc3, 0x67, 0x63, 0x04,
|
||||
0xb5, 0x0e, 0x32, 0xfa, 0x48, 0xef, 0x0e, 0x64, 0x63, 0xac, 0x43, 0x4d, 0x86, 0x23, 0x99, 0x63,
|
||||
0x84, 0x5a, 0x92, 0x8a, 0xd5, 0x02, 0x34, 0xa6, 0x66, 0xe0, 0x98, 0x0b, 0x87, 0xbf, 0x63, 0xab,
|
||||
0xfb, 0xb0, 0x3a, 0x90, 0x74, 0xcc, 0x95, 0x84, 0xf3, 0x24, 0x15, 0xcf, 0x0a, 0xa4, 0x1a, 0xda,
|
||||
0x94, 0xf0, 0x1d, 0xf6, 0x72, 0x1f, 0xcb, 0x13, 0x45, 0xc5, 0x68, 0x17, 0x73, 0x65, 0x41, 0x4c,
|
||||
0x52, 0xb1, 0x5e, 0x10, 0x6c, 0xaf, 0x8a, 0x4f, 0xdc, 0x3c, 0xe2, 0x1f, 0xd8, 0xda, 0x81, 0xf1,
|
||||
0x48, 0x93, 0x73, 0x11, 0x57, 0x39, 0xbc, 0xde, 0x0d, 0x9c, 0xad, 0x82, 0xc7, 0x6c, 0x63, 0x9f,
|
||||
0x96, 0x1f, 0x87, 0x58, 0x95, 0xa0, 0x8e, 0x0c, 0xf4, 0xa4, 0x23, 0x4d, 0x1f, 0x73, 0x47, 0x42,
|
||||
0x23, 0x49, 0xc5, 0x8b, 0x82, 0x45, 0x5e, 0x46, 0xc4, 0xb7, 0x4d, 0xea, 0xa2, 0x37, 0xea, 0x06,
|
||||
0x34, 0xe6, 0x7b, 0x87, 0x6c, 0x10, 0x63, 0x63, 0xa2, 0xea, 0x5d, 0x43, 0x81, 0x18, 0xb7, 0xa1,
|
||||
0xd4, 0xe3, 0x8e, 0x85, 0xab, 0x24, 0x15, 0x41, 0xc1, 0x06, 0x09, 0x99, 0xf8, 0xd4, 0x53, 0x4c,
|
||||
0x42, 0x2c, 0xd3, 0x7e, 0x6d, 0x4b, 0x5f, 0x1b, 0xc0, 0xac, 0x37, 0x80, 0xf9, 0xfd, 0x01, 0xcc,
|
||||
0x7b, 0x06, 0x98, 0x8f, 0x0c, 0x94, 0xd6, 0x19, 0x60, 0xbe, 0x33, 0xc0, 0xbc, 0x5c, 0xcf, 0x7c,
|
||||
0xea, 0x2d, 0xad, 0xa6, 0x1d, 0xce, 0x5b, 0xf1, 0x2a, 0xb0, 0xa9, 0xe7, 0x07, 0xb3, 0x7f, 0xa7,
|
||||
0xdd, 0x47, 0xb0, 0x4e, 0xf2, 0x97, 0xbf, 0xfd, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x06, 0xa6, 0xad,
|
||||
0xd0, 0x19, 0x02, 0x00, 0x00,
|
||||
// 391 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0xbd, 0x8e, 0xd3, 0x40,
|
||||
0x14, 0x85, 0xed, 0xdd, 0x85, 0xc2, 0x0d, 0x96, 0x85, 0xb4, 0x68, 0x76, 0x35, 0x18, 0x22, 0x1a,
|
||||
0x8a, 0x75, 0x81, 0xa8, 0xa0, 0x99, 0xb5, 0xc7, 0x59, 0x6b, 0x27, 0x4e, 0x94, 0x18, 0x05, 0x68,
|
||||
0x2c, 0xff, 0xc5, 0xb6, 0x98, 0x78, 0x2c, 0x7b, 0x22, 0x91, 0x57, 0x70, 0xc5, 0x0b, 0x58, 0xa2,
|
||||
0xa0, 0xa0, 0xe1, 0x3d, 0x52, 0xa6, 0xa4, 0x4d, 0xfc, 0x22, 0x28, 0x93, 0x06, 0x39, 0xe9, 0xee,
|
||||
0x3d, 0x9a, 0xef, 0xd3, 0x91, 0xe6, 0x2a, 0xb7, 0x34, 0x0f, 0x8d, 0x45, 0x6d, 0x44, 0xac, 0x5c,
|
||||
0x57, 0x41, 0x91, 0x26, 0xcb, 0x84, 0x67, 0x2c, 0xbe, 0x2b, 0x2b, 0xc6, 0x99, 0x76, 0xb1, 0xa8,
|
||||
0xc1, 0xa0, 0x4a, 0x4a, 0x56, 0x1b, 0x22, 0x08, 0x57, 0x0b, 0x23, 0x65, 0x29, 0x13, 0x8b, 0x98,
|
||||
0x8e, 0x0f, 0xdf, 0xfe, 0xb9, 0x54, 0x9e, 0x99, 0xac, 0x5c, 0x4f, 0x0f, 0x8a, 0x91, 0x50, 0x68,
|
||||
0x1f, 0x14, 0x60, 0x8e, 0x27, 0x5f, 0xfc, 0x29, 0x72, 0x87, 0xd8, 0x1f, 0x61, 0xef, 0x61, 0x6c,
|
||||
0xf9, 0x33, 0x0f, 0xb9, 0x16, 0x9a, 0x5a, 0xaa, 0x04, 0x6e, 0x9a, 0x56, 0xbf, 0xee, 0x41, 0x33,
|
||||
0x1e, 0x14, 0x71, 0x50, 0xc5, 0xda, 0x7b, 0xe5, 0xfa, 0x14, 0x76, 0xc6, 0xa6, 0x47, 0x54, 0x19,
|
||||
0xbc, 0x68, 0x5a, 0xfd, 0x79, 0x8f, 0x74, 0x58, 0xc4, 0xa9, 0x36, 0x54, 0x5e, 0x9d, 0x62, 0x22,
|
||||
0xb1, 0x1d, 0x82, 0x8f, 0xb1, 0x7a, 0x01, 0xf4, 0xa6, 0xd5, 0x6f, 0x7b, 0x82, 0xc3, 0x6a, 0xe7,
|
||||
0x34, 0x11, 0x91, 0xf6, 0x51, 0xb9, 0x39, 0x53, 0x1e, 0xbb, 0x96, 0x10, 0xa9, 0x97, 0xe7, 0xdb,
|
||||
0x27, 0x45, 0x7c, 0x50, 0x68, 0x44, 0x19, 0x9c, 0xd2, 0xd6, 0xa7, 0x09, 0x71, 0x4c, 0xe4, 0x61,
|
||||
0x1f, 0x7f, 0xf6, 0xb0, 0xeb, 0xcd, 0xd4, 0x2b, 0x30, 0x68, 0x5a, 0xfd, 0x65, 0xcf, 0x62, 0xad,
|
||||
0x4a, 0x9a, 0x47, 0x01, 0x4f, 0xf0, 0x77, 0x9e, 0x14, 0xbc, 0xd6, 0x1e, 0xcf, 0xd9, 0x10, 0x21,
|
||||
0xfe, 0xdc, 0xf1, 0x1e, 0x7c, 0x1b, 0x11, 0x72, 0x8f, 0xcc, 0x47, 0xf5, 0x09, 0x78, 0xdd, 0xb4,
|
||||
0x3a, 0xec, 0xd9, 0x10, 0xa5, 0xf3, 0x9c, 0x67, 0x76, 0x40, 0x69, 0x18, 0x44, 0xdf, 0xc0, 0xd5,
|
||||
0xef, 0x5f, 0x50, 0xba, 0x1f, 0x6e, 0x76, 0x50, 0xda, 0xee, 0xa0, 0xb4, 0xd9, 0x43, 0x79, 0xbb,
|
||||
0x87, 0xf2, 0x8f, 0x0e, 0x4a, 0x3f, 0x3b, 0x28, 0x6f, 0x3b, 0x28, 0xfd, 0xed, 0xa0, 0xf4, 0xf5,
|
||||
0x4d, 0x9a, 0xf3, 0x6c, 0x15, 0xde, 0x45, 0x6c, 0x69, 0xd4, 0xeb, 0x22, 0xe2, 0x59, 0x5e, 0xa4,
|
||||
0xff, 0x4d, 0xc7, 0xbb, 0x09, 0x9f, 0x8a, 0xff, 0x7f, 0xf7, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xb6,
|
||||
0x5d, 0x2e, 0x16, 0x48, 0x02, 0x00, 0x00,
|
||||
}
|
||||
|
||||
@@ -91,8 +91,8 @@ func (fm FileMode) String() string {
|
||||
|
||||
// Usage represents filesystem space usage
|
||||
type Usage struct {
|
||||
Free int64
|
||||
Total int64
|
||||
Free uint64
|
||||
Total uint64
|
||||
}
|
||||
|
||||
type Matcher interface {
|
||||
@@ -234,7 +234,7 @@ func Canonicalize(file string) (string, error) {
|
||||
// The relative path may pretend to be an absolute path within
|
||||
// the root, but the double path separator on Windows implies
|
||||
// something else and is out of spec.
|
||||
return "", ErrNotRelative
|
||||
return "", errNotRelative
|
||||
}
|
||||
|
||||
// The relative path should be clean from internal dotdots and similar
|
||||
@@ -244,10 +244,10 @@ func Canonicalize(file string) (string, error) {
|
||||
// It is not acceptable to attempt to traverse upwards.
|
||||
switch file {
|
||||
case "..":
|
||||
return "", ErrNotRelative
|
||||
return "", errNotRelative
|
||||
}
|
||||
if strings.HasPrefix(file, ".."+pathSep) {
|
||||
return "", ErrNotRelative
|
||||
return "", errNotRelative
|
||||
}
|
||||
|
||||
if strings.HasPrefix(file, pathSep) {
|
||||
|
||||
@@ -5,6 +5,7 @@ package fs
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
@@ -48,18 +49,20 @@ func init() {
|
||||
func init() { proto.RegisterFile("lib/fs/types.proto", fileDescriptor_b556f45c4309ad5d) }
|
||||
|
||||
var fileDescriptor_b556f45c4309ad5d = []byte{
|
||||
// 194 bytes of a gzipped FileDescriptorProto
|
||||
// 228 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xca, 0xc9, 0x4c, 0xd2,
|
||||
0x4f, 0x2b, 0xd6, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62,
|
||||
0x4a, 0x2b, 0xd6, 0x2a, 0xe3, 0xe2, 0x73, 0xcb, 0xcc, 0x49, 0x2d, 0xae, 0x2c, 0x2e, 0x49, 0xcd,
|
||||
0x0d, 0xa9, 0x2c, 0x48, 0x15, 0x32, 0xe2, 0x12, 0x75, 0xf3, 0xf4, 0x71, 0x0d, 0x8e, 0x0c, 0x0e,
|
||||
0x71, 0xf5, 0x8d, 0x0f, 0x89, 0x0c, 0x70, 0x8d, 0x77, 0x72, 0x0c, 0xf6, 0x74, 0x16, 0x60, 0x90,
|
||||
0x12, 0xef, 0x9a, 0xab, 0x20, 0x8c, 0xaa, 0xdc, 0x29, 0xb1, 0x38, 0x33, 0x59, 0xc8, 0x80, 0x4b,
|
||||
0x04, 0x5d, 0x8f, 0x9b, 0xa3, 0xb7, 0xab, 0x00, 0xa3, 0x94, 0x58, 0xd7, 0x5c, 0x05, 0x21, 0x54,
|
||||
0x2d, 0x6e, 0x89, 0xd9, 0xa9, 0x4e, 0xce, 0x27, 0x1e, 0xca, 0x31, 0x5c, 0x78, 0x28, 0xc7, 0xf0,
|
||||
0xe2, 0x91, 0x1c, 0xc3, 0x84, 0xc7, 0x72, 0x0c, 0x0b, 0x1e, 0xcb, 0x31, 0x5e, 0x78, 0x2c, 0xc7,
|
||||
0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x6a, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e,
|
||||
0xae, 0x7e, 0x71, 0x65, 0x5e, 0x72, 0x49, 0x46, 0x66, 0x5e, 0x3a, 0x12, 0x0b, 0xe2, 0x99, 0x24,
|
||||
0x36, 0xb0, 0x3f, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x86, 0xe8, 0x6b, 0xac, 0xdd, 0x00,
|
||||
0x00, 0x00,
|
||||
0x4a, 0x2b, 0x96, 0x52, 0x2e, 0x4a, 0x2d, 0xc8, 0x2f, 0xd6, 0x07, 0x0b, 0x24, 0x95, 0xa6, 0xe9,
|
||||
0xa7, 0xe7, 0xa7, 0xe7, 0x83, 0x39, 0x60, 0x16, 0x44, 0xa1, 0x56, 0x0d, 0x17, 0x9f, 0x5b, 0x66,
|
||||
0x4e, 0x6a, 0x71, 0x65, 0x71, 0x49, 0x6a, 0x6e, 0x48, 0x65, 0x41, 0xaa, 0x90, 0x11, 0x97, 0xa8,
|
||||
0x9b, 0xa7, 0x8f, 0x6b, 0x70, 0x64, 0x70, 0x88, 0xab, 0x6f, 0x7c, 0x48, 0x64, 0x80, 0x6b, 0xbc,
|
||||
0x93, 0x63, 0xb0, 0xa7, 0xb3, 0x00, 0x83, 0x94, 0x78, 0xd7, 0x5c, 0x05, 0x61, 0x54, 0xe5, 0x4e,
|
||||
0x89, 0xc5, 0x99, 0xc9, 0x42, 0x06, 0x5c, 0x22, 0xe8, 0x7a, 0xdc, 0x1c, 0xbd, 0x5d, 0x05, 0x18,
|
||||
0xa5, 0xc4, 0xba, 0xe6, 0x2a, 0x08, 0xa1, 0x6a, 0x71, 0x4b, 0xcc, 0x4e, 0x95, 0x62, 0x59, 0xb1,
|
||||
0x44, 0x8e, 0xc1, 0xc9, 0xfd, 0xc4, 0x43, 0x39, 0x86, 0x0b, 0x0f, 0xe5, 0x18, 0x4e, 0x3c, 0x92,
|
||||
0x63, 0xbc, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x05, 0x8f, 0xe5, 0x18, 0x2f, 0x3c,
|
||||
0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x35, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f,
|
||||
0x39, 0x3f, 0x57, 0xbf, 0xb8, 0x32, 0x2f, 0xb9, 0x24, 0x23, 0x33, 0x2f, 0x1d, 0x89, 0x05, 0xf1,
|
||||
0x7b, 0x12, 0x1b, 0xd8, 0x37, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x2c, 0x30, 0x9a, 0x86,
|
||||
0x0c, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -15,8 +14,6 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
var errNoHome = errors.New("no home directory found - set $HOME (or the platform equivalent)")
|
||||
|
||||
func ExpandTilde(path string) (string, error) {
|
||||
if path == "~" {
|
||||
return getHomeDir()
|
||||
@@ -47,28 +44,52 @@ func getHomeDir() (string, error) {
|
||||
return os.UserHomeDir()
|
||||
}
|
||||
|
||||
var windowsDisallowedCharacters = string([]rune{
|
||||
'<', '>', ':', '"', '|', '?', '*',
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
|
||||
31,
|
||||
})
|
||||
var (
|
||||
windowsDisallowedCharacters = string([]rune{
|
||||
'<', '>', ':', '"', '|', '?', '*',
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
|
||||
31,
|
||||
})
|
||||
windowsDisallowedNames = []string{"CON", "PRN", "AUX", "NUL",
|
||||
"COM0", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
|
||||
"LPT0", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
|
||||
}
|
||||
)
|
||||
|
||||
func WindowsInvalidFilename(name string) bool {
|
||||
// None of the path components should end in space
|
||||
func WindowsInvalidFilename(name string) error {
|
||||
// None of the path components should end in space or period, or be a
|
||||
// reserved name. COM0 and LPT0 are missing from the Microsoft docs,
|
||||
// but Windows Explorer treats them as invalid too.
|
||||
// (https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file)
|
||||
for _, part := range strings.Split(name, `\`) {
|
||||
if len(part) == 0 {
|
||||
continue
|
||||
}
|
||||
if part[len(part)-1] == ' ' {
|
||||
// Names ending in space are not valid.
|
||||
return true
|
||||
switch part[len(part)-1] {
|
||||
case ' ', '.':
|
||||
// Names ending in space or period are not valid.
|
||||
return errInvalidFilenameWindowsSpacePeriod
|
||||
}
|
||||
upperCased := strings.ToUpper(part)
|
||||
for _, disallowed := range windowsDisallowedNames {
|
||||
if upperCased == disallowed {
|
||||
return errInvalidFilenameWindowsReservedName
|
||||
}
|
||||
if strings.HasPrefix(upperCased, disallowed+".") {
|
||||
// nul.txt.jpg is also disallowed
|
||||
return errInvalidFilenameWindowsReservedName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The path must not contain any disallowed characters
|
||||
return strings.ContainsAny(name, windowsDisallowedCharacters)
|
||||
if strings.ContainsAny(name, windowsDisallowedCharacters) {
|
||||
return errInvalidFilenameWindowsReservedChar
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsParent compares paths purely lexicographically, meaning it returns false
|
||||
|
||||
@@ -44,3 +44,29 @@ func TestCommonPrefix(t *testing.T) {
|
||||
test(`Audrius`, `Audrius`, `Audrius`)
|
||||
test(`.`, `.`, `.`)
|
||||
}
|
||||
|
||||
func TestWindowsInvalidFilename(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
err error
|
||||
}{
|
||||
{`asdf.txt`, nil},
|
||||
{`nul`, errInvalidFilenameWindowsReservedName},
|
||||
{`nul.txt`, errInvalidFilenameWindowsReservedName},
|
||||
{`nul.jpg.txt`, errInvalidFilenameWindowsReservedName},
|
||||
{`some.nul.jpg`, nil},
|
||||
{`foo>bar.txt`, errInvalidFilenameWindowsReservedChar},
|
||||
{`foo \bar.txt`, errInvalidFilenameWindowsSpacePeriod},
|
||||
{`foo.\bar.txt`, errInvalidFilenameWindowsSpacePeriod},
|
||||
{`foo.d\bar.txt`, nil},
|
||||
{`foo.d\bar .txt`, nil},
|
||||
{`foo.d\bar. txt`, nil},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
err := WindowsInvalidFilename(tc.name)
|
||||
if err != tc.err {
|
||||
t.Errorf("For %q, got %v, expected %v", tc.name, err, tc.err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,11 +53,6 @@ const (
|
||||
var baseDirs = make(map[BaseDirEnum]string, 3)
|
||||
|
||||
func init() {
|
||||
if os.Getenv("USE_BADGER") != "" {
|
||||
// XXX: Replace the leveldb name with the badger name.
|
||||
locationTemplates[Database] = strings.Replace(locationTemplates[Database], LevelDBDir, BadgerDir, 1)
|
||||
}
|
||||
|
||||
userHome := userHomeDir()
|
||||
config := defaultConfigDir(userHome)
|
||||
baseDirs[UserHomeBaseDir] = userHome
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
// FileInfo.Blocks that the remote device already has, and version represents
|
||||
// the version of the file that the remote device is downloading.
|
||||
type deviceFolderFileDownloadState struct {
|
||||
blockIndexes []int32
|
||||
blockIndexes []int
|
||||
version protocol.Vector
|
||||
blockSize int
|
||||
}
|
||||
@@ -30,7 +30,7 @@ type deviceFolderDownloadState struct {
|
||||
|
||||
// Has returns whether a block at that specific index, and that specific version of the file
|
||||
// is currently available on the remote device for pulling from a temporary file.
|
||||
func (p *deviceFolderDownloadState) Has(file string, version protocol.Vector, index int32) bool {
|
||||
func (p *deviceFolderDownloadState) Has(file string, version protocol.Vector, index int) bool {
|
||||
p.mut.RLock()
|
||||
defer p.mut.RUnlock()
|
||||
|
||||
@@ -56,9 +56,9 @@ func (p *deviceFolderDownloadState) Update(updates []protocol.FileDownloadProgre
|
||||
|
||||
for _, update := range updates {
|
||||
local, ok := p.files[update.Name]
|
||||
if update.UpdateType == protocol.UpdateTypeForget && ok && local.version.Equal(update.Version) {
|
||||
if update.UpdateType == protocol.FileDownloadProgressUpdateTypeForget && ok && local.version.Equal(update.Version) {
|
||||
delete(p.files, update.Name)
|
||||
} else if update.UpdateType == protocol.UpdateTypeAppend {
|
||||
} else if update.UpdateType == protocol.FileDownloadProgressUpdateTypeAppend {
|
||||
if !ok {
|
||||
local = deviceFolderFileDownloadState{
|
||||
blockIndexes: update.BlockIndexes,
|
||||
@@ -137,7 +137,7 @@ func (t *deviceDownloadState) Update(folder string, updates []protocol.FileDownl
|
||||
|
||||
// Has returns whether block at that specific index, and that specific version of the file
|
||||
// is currently available on the remote device for pulling from a temporary file.
|
||||
func (t *deviceDownloadState) Has(folder, file string, version protocol.Vector, index int32) bool {
|
||||
func (t *deviceDownloadState) Has(folder, file string, version protocol.Vector, index int) bool {
|
||||
if t == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -17,16 +17,16 @@ func TestDeviceDownloadState(t *testing.T) {
|
||||
v2 := (protocol.Vector{}).Update(1)
|
||||
|
||||
// file 1 version 1 part 1
|
||||
f1v1p1 := protocol.FileDownloadProgressUpdate{UpdateType: protocol.UpdateTypeAppend, Name: "f1", Version: v1, BlockIndexes: []int32{0, 1, 2}}
|
||||
f1v1p2 := protocol.FileDownloadProgressUpdate{UpdateType: protocol.UpdateTypeAppend, Name: "f1", Version: v1, BlockIndexes: []int32{3, 4, 5}}
|
||||
f1v1del := protocol.FileDownloadProgressUpdate{UpdateType: protocol.UpdateTypeForget, Name: "f1", Version: v1, BlockIndexes: nil}
|
||||
f1v2p1 := protocol.FileDownloadProgressUpdate{UpdateType: protocol.UpdateTypeAppend, Name: "f1", Version: v2, BlockIndexes: []int32{10, 11, 12}}
|
||||
f1v2p2 := protocol.FileDownloadProgressUpdate{UpdateType: protocol.UpdateTypeAppend, Name: "f1", Version: v2, BlockIndexes: []int32{13, 14, 15}}
|
||||
f1v2del := protocol.FileDownloadProgressUpdate{UpdateType: protocol.UpdateTypeForget, Name: "f1", Version: v2, BlockIndexes: nil}
|
||||
f1v1p1 := protocol.FileDownloadProgressUpdate{UpdateType: protocol.FileDownloadProgressUpdateTypeAppend, Name: "f1", Version: v1, BlockIndexes: []int{0, 1, 2}}
|
||||
f1v1p2 := protocol.FileDownloadProgressUpdate{UpdateType: protocol.FileDownloadProgressUpdateTypeAppend, Name: "f1", Version: v1, BlockIndexes: []int{3, 4, 5}}
|
||||
f1v1del := protocol.FileDownloadProgressUpdate{UpdateType: protocol.FileDownloadProgressUpdateTypeForget, Name: "f1", Version: v1, BlockIndexes: nil}
|
||||
f1v2p1 := protocol.FileDownloadProgressUpdate{UpdateType: protocol.FileDownloadProgressUpdateTypeAppend, Name: "f1", Version: v2, BlockIndexes: []int{10, 11, 12}}
|
||||
f1v2p2 := protocol.FileDownloadProgressUpdate{UpdateType: protocol.FileDownloadProgressUpdateTypeAppend, Name: "f1", Version: v2, BlockIndexes: []int{13, 14, 15}}
|
||||
f1v2del := protocol.FileDownloadProgressUpdate{UpdateType: protocol.FileDownloadProgressUpdateTypeForget, Name: "f1", Version: v2, BlockIndexes: nil}
|
||||
|
||||
f2v1p1 := protocol.FileDownloadProgressUpdate{UpdateType: protocol.UpdateTypeAppend, Name: "f2", Version: v1, BlockIndexes: []int32{20, 21, 22}}
|
||||
f2v1p2 := protocol.FileDownloadProgressUpdate{UpdateType: protocol.UpdateTypeAppend, Name: "f2", Version: v1, BlockIndexes: []int32{23, 24, 25}}
|
||||
f2v1del := protocol.FileDownloadProgressUpdate{UpdateType: protocol.UpdateTypeForget, Name: "f2", Version: v1, BlockIndexes: nil}
|
||||
f2v1p1 := protocol.FileDownloadProgressUpdate{UpdateType: protocol.FileDownloadProgressUpdateTypeAppend, Name: "f2", Version: v1, BlockIndexes: []int{20, 21, 22}}
|
||||
f2v1p2 := protocol.FileDownloadProgressUpdate{UpdateType: protocol.FileDownloadProgressUpdateTypeAppend, Name: "f2", Version: v1, BlockIndexes: []int{23, 24, 25}}
|
||||
f2v1del := protocol.FileDownloadProgressUpdate{UpdateType: protocol.FileDownloadProgressUpdateTypeForget, Name: "f2", Version: v1, BlockIndexes: nil}
|
||||
|
||||
tests := []struct {
|
||||
updates []protocol.FileDownloadProgressUpdate
|
||||
|
||||
@@ -35,6 +35,7 @@ type fakeConnection struct {
|
||||
indexFn func(context.Context, string, []protocol.FileInfo)
|
||||
requestFn func(ctx context.Context, folder, name string, offset int64, size int, hash []byte, fromTemporary bool) ([]byte, error)
|
||||
closeFn func(error)
|
||||
clusterConfigFn func(protocol.ClusterConfig)
|
||||
mut sync.Mutex
|
||||
}
|
||||
|
||||
@@ -82,7 +83,7 @@ func (f *fakeConnection) IndexUpdate(ctx context.Context, folder string, fs []pr
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fakeConnection) Request(ctx context.Context, folder, name string, offset int64, size int, hash []byte, weakHash uint32, fromTemporary bool) ([]byte, error) {
|
||||
func (f *fakeConnection) Request(ctx context.Context, folder, name string, blockNo int, offset int64, size int, hash []byte, weakHash uint32, fromTemporary bool) ([]byte, error) {
|
||||
f.mut.Lock()
|
||||
defer f.mut.Unlock()
|
||||
if f.requestFn != nil {
|
||||
@@ -91,7 +92,13 @@ func (f *fakeConnection) Request(ctx context.Context, folder, name string, offse
|
||||
return f.fileData[name], nil
|
||||
}
|
||||
|
||||
func (f *fakeConnection) ClusterConfig(protocol.ClusterConfig) {}
|
||||
func (f *fakeConnection) ClusterConfig(cc protocol.ClusterConfig) {
|
||||
f.mut.Lock()
|
||||
defer f.mut.Unlock()
|
||||
if f.clusterConfigFn != nil {
|
||||
f.clusterConfigFn(cc)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *fakeConnection) Ping() bool {
|
||||
f.mut.Lock()
|
||||
@@ -129,7 +136,7 @@ func (f *fakeConnection) addFileLocked(name string, flags uint32, ftype protocol
|
||||
Permissions: flags,
|
||||
Version: version,
|
||||
Sequence: time.Now().UnixNano(),
|
||||
RawBlockSize: int32(blockSize),
|
||||
RawBlockSize: blockSize,
|
||||
Blocks: blocks,
|
||||
})
|
||||
} else {
|
||||
@@ -196,7 +203,7 @@ func (f *fakeConnection) sendIndexUpdate() {
|
||||
|
||||
func addFakeConn(m *model, dev protocol.DeviceID) *fakeConnection {
|
||||
fc := &fakeConnection{id: dev, model: m}
|
||||
m.AddConnection(fc, protocol.HelloResult{})
|
||||
m.AddConnection(fc, protocol.Hello{})
|
||||
|
||||
m.ClusterConfig(dev, protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
|
||||
@@ -49,14 +49,13 @@ type folder struct {
|
||||
fset *db.FileSet
|
||||
ignores *ignore.Matcher
|
||||
modTimeWindow time.Duration
|
||||
ctx context.Context
|
||||
ctx context.Context // used internally, only accessible on serve lifetime
|
||||
done chan struct{} // used externally, accessible regardless of serve
|
||||
|
||||
scanInterval time.Duration
|
||||
scanTimer *time.Timer
|
||||
scanDelay chan time.Duration
|
||||
initialScanFinished chan struct{}
|
||||
scanErrors []FileError
|
||||
scanErrorsMut sync.Mutex
|
||||
versionCleanupInterval time.Duration
|
||||
versionCleanupTimer *time.Timer
|
||||
|
||||
@@ -64,6 +63,10 @@ type folder struct {
|
||||
pullPause time.Duration
|
||||
pullFailTimer *time.Timer
|
||||
|
||||
scanErrors []FileError
|
||||
pullErrors []FileError
|
||||
errorsMut sync.Mutex
|
||||
|
||||
doInSyncChan chan syncRequest
|
||||
|
||||
forcedRescanRequested chan struct{}
|
||||
@@ -101,17 +104,19 @@ func newFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg conf
|
||||
fset: fset,
|
||||
ignores: ignores,
|
||||
modTimeWindow: cfg.ModTimeWindow(),
|
||||
done: make(chan struct{}),
|
||||
|
||||
scanInterval: time.Duration(cfg.RescanIntervalS) * time.Second,
|
||||
scanTimer: time.NewTimer(0), // The first scan should be done immediately.
|
||||
scanDelay: make(chan time.Duration),
|
||||
initialScanFinished: make(chan struct{}),
|
||||
scanErrorsMut: sync.NewMutex(),
|
||||
versionCleanupInterval: time.Duration(cfg.Versioning.CleanupIntervalS) * time.Second,
|
||||
versionCleanupTimer: time.NewTimer(time.Duration(cfg.Versioning.CleanupIntervalS) * time.Second),
|
||||
|
||||
pullScheduled: make(chan struct{}, 1), // This needs to be 1-buffered so that we queue a pull if we're busy when it comes.
|
||||
|
||||
errorsMut: sync.NewMutex(),
|
||||
|
||||
doInSyncChan: make(chan syncRequest),
|
||||
|
||||
forcedRescanRequested: make(chan struct{}, 1),
|
||||
@@ -162,6 +167,7 @@ func (f *folder) serve(ctx context.Context) {
|
||||
for {
|
||||
select {
|
||||
case <-f.ctx.Done():
|
||||
close(f.done)
|
||||
return
|
||||
|
||||
case <-f.pullScheduled:
|
||||
@@ -215,7 +221,10 @@ func (f *folder) Override() {}
|
||||
func (f *folder) Revert() {}
|
||||
|
||||
func (f *folder) DelayScan(next time.Duration) {
|
||||
f.Delay(next)
|
||||
select {
|
||||
case f.scanDelay <- next:
|
||||
case <-f.done:
|
||||
}
|
||||
}
|
||||
|
||||
func (f *folder) ignoresUpdated() {
|
||||
@@ -255,8 +264,8 @@ func (f *folder) doInSync(fn func() error) error {
|
||||
select {
|
||||
case f.doInSyncChan <- req:
|
||||
return <-req.err
|
||||
case <-f.ctx.Done():
|
||||
return f.ctx.Err()
|
||||
case <-f.done:
|
||||
return context.Canceled
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,10 +280,6 @@ func (f *folder) Reschedule() {
|
||||
f.scanTimer.Reset(interval)
|
||||
}
|
||||
|
||||
func (f *folder) Delay(next time.Duration) {
|
||||
f.scanDelay <- next
|
||||
}
|
||||
|
||||
func (f *folder) getHealthErrorAndLoadIgnores() error {
|
||||
if err := f.getHealthErrorWithoutIgnores(); err != nil {
|
||||
return err
|
||||
@@ -333,6 +338,10 @@ func (f *folder) pull() (success bool) {
|
||||
})
|
||||
snap.Release()
|
||||
if abort {
|
||||
// Clears pull failures on items that were needed before, but aren't anymore.
|
||||
f.errorsMut.Lock()
|
||||
f.pullErrors = nil
|
||||
f.errorsMut.Unlock()
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -450,7 +459,8 @@ func (f *folder) scanSubdirs(subDirs []string) error {
|
||||
scanCtx, scanCancel := context.WithCancel(f.ctx)
|
||||
defer scanCancel()
|
||||
mtimefs := f.fset.MtimeFS()
|
||||
fchan := scanner.Walk(scanCtx, scanner.Config{
|
||||
|
||||
scanConfig := scanner.Config{
|
||||
Folder: f.ID,
|
||||
Subs: subDirs,
|
||||
Matcher: f.ignores,
|
||||
@@ -465,7 +475,13 @@ func (f *folder) scanSubdirs(subDirs []string) error {
|
||||
LocalFlags: f.localFlags,
|
||||
ModTimeWindow: f.modTimeWindow,
|
||||
EventLogger: f.evLogger,
|
||||
})
|
||||
}
|
||||
var fchan chan scanner.ScanResult
|
||||
if f.Type == config.FolderTypeReceiveEncrypted {
|
||||
fchan = scanner.WalkWithoutHashing(scanCtx, scanConfig)
|
||||
} else {
|
||||
fchan = scanner.Walk(scanCtx, scanConfig)
|
||||
}
|
||||
|
||||
batch := newFileInfoBatch(func(fs []protocol.FileInfo) error {
|
||||
if err := f.getHealthErrorWithoutIgnores(); err != nil {
|
||||
@@ -476,19 +492,25 @@ func (f *folder) scanSubdirs(subDirs []string) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
// Schedule a pull after scanning, but only if we actually detected any
|
||||
// changes.
|
||||
changes := 0
|
||||
defer func() {
|
||||
if changes > 0 {
|
||||
f.SchedulePull()
|
||||
}
|
||||
}()
|
||||
|
||||
var batchAppend func(protocol.FileInfo, *db.Snapshot)
|
||||
// Resolve items which are identical with the global state.
|
||||
if f.localFlags&protocol.FlagLocalReceiveOnly == 0 {
|
||||
batchAppend = func(fi protocol.FileInfo, _ *db.Snapshot) {
|
||||
batch.append(fi)
|
||||
}
|
||||
} else {
|
||||
switch f.Type {
|
||||
case config.FolderTypeReceiveOnly:
|
||||
batchAppend = func(fi protocol.FileInfo, snap *db.Snapshot) {
|
||||
switch gf, ok := snap.GetGlobal(fi.Name); {
|
||||
case !ok:
|
||||
case gf.IsEquivalentOptional(fi, f.modTimeWindow, false, false, protocol.FlagLocalReceiveOnly):
|
||||
// What we have locally is equivalent to the global file.
|
||||
fi.Version = fi.Version.Merge(gf.Version)
|
||||
fi.Version = gf.Version
|
||||
fallthrough
|
||||
case fi.IsDeleted() && (gf.IsReceiveOnlyChanged() || gf.IsDeleted()):
|
||||
// Our item is deleted and the global item is our own
|
||||
@@ -500,16 +522,28 @@ func (f *folder) scanSubdirs(subDirs []string) error {
|
||||
}
|
||||
batch.append(fi)
|
||||
}
|
||||
}
|
||||
|
||||
// Schedule a pull after scanning, but only if we actually detected any
|
||||
// changes.
|
||||
changes := 0
|
||||
defer func() {
|
||||
if changes > 0 {
|
||||
f.SchedulePull()
|
||||
case config.FolderTypeReceiveEncrypted:
|
||||
batchAppend = func(fi protocol.FileInfo, _ *db.Snapshot) {
|
||||
// This is a "virtual" parent directory of encrypted files.
|
||||
// We don't track it, but check if anything still exists
|
||||
// within and delete it otherwise.
|
||||
if fi.IsDirectory() && protocol.IsEncryptedParent(fi.Name) {
|
||||
if names, err := mtimefs.DirNames(fi.Name); err == nil && len(names) == 0 {
|
||||
mtimefs.Remove(fi.Name)
|
||||
}
|
||||
changes--
|
||||
return
|
||||
}
|
||||
// Any local change must not be sent as index entry to
|
||||
// remotes and show up as an error in the UI.
|
||||
fi.LocalFlags = protocol.FlagLocalReceiveOnly
|
||||
batch.append(fi)
|
||||
}
|
||||
}()
|
||||
default:
|
||||
batchAppend = func(fi protocol.FileInfo, _ *db.Snapshot) {
|
||||
batch.append(fi)
|
||||
}
|
||||
}
|
||||
|
||||
f.clearScanErrors(subDirs)
|
||||
alreadyUsed := make(map[string]struct{})
|
||||
@@ -520,13 +554,20 @@ func (f *folder) scanSubdirs(subDirs []string) error {
|
||||
}
|
||||
|
||||
if err := batch.flushIfFull(); err != nil {
|
||||
// Prevent a race between the scan aborting due to context
|
||||
// cancellation and releasing the snapshot in defer here.
|
||||
scanCancel()
|
||||
for range fchan {
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
batchAppend(res.File, snap)
|
||||
changes++
|
||||
|
||||
if f.localFlags&protocol.FlagLocalReceiveOnly == 0 {
|
||||
switch f.Type {
|
||||
case config.FolderTypeReceiveOnly, config.FolderTypeReceiveEncrypted:
|
||||
default:
|
||||
if nf, ok := f.findRename(snap, mtimefs, res.File, alreadyUsed); ok {
|
||||
batchAppend(nf, snap)
|
||||
changes++
|
||||
@@ -634,7 +675,7 @@ func (f *folder) scanSubdirs(subDirs []string) error {
|
||||
l.Debugln("marking file as deleted", nf)
|
||||
batchAppend(nf, snap)
|
||||
changes++
|
||||
case file.IsDeleted() && file.IsReceiveOnlyChanged() && f.localFlags&protocol.FlagLocalReceiveOnly != 0 && len(snap.Availability(file.Name)) == 0:
|
||||
case file.IsDeleted() && file.IsReceiveOnlyChanged() && f.Type == config.FolderTypeReceiveOnly && len(snap.Availability(file.Name)) == 0:
|
||||
file.Version = protocol.Vector{}
|
||||
file.LocalFlags &^= protocol.FlagLocalReceiveOnly
|
||||
l.Debugln("marking deleted item that doesn't exist anywhere as not receive-only", file)
|
||||
@@ -860,11 +901,13 @@ func (f *folder) monitorWatch(ctx context.Context) {
|
||||
f.setWatchError(err, next)
|
||||
// This error was previously a panic and should never occur, so generate
|
||||
// a warning, but don't do it repetitively.
|
||||
if !warnedOutside {
|
||||
if _, ok := err.(*fs.ErrWatchEventOutsideRoot); ok {
|
||||
var errOutside *fs.ErrWatchEventOutsideRoot
|
||||
if errors.As(err, &errOutside) {
|
||||
if !warnedOutside {
|
||||
l.Warnln(err)
|
||||
warnedOutside = true
|
||||
}
|
||||
f.evLogger.Log(events.Failure, "watching for changes encountered an event outside of the filesystem root")
|
||||
}
|
||||
aggrCancel()
|
||||
errChan = nil
|
||||
@@ -911,7 +954,7 @@ func (f *folder) scanOnWatchErr() {
|
||||
err := f.watchErr
|
||||
f.watchMut.Unlock()
|
||||
if err != nil {
|
||||
f.Delay(0)
|
||||
f.DelayScan(0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -960,18 +1003,18 @@ func (f *folder) String() string {
|
||||
}
|
||||
|
||||
func (f *folder) newScanError(path string, err error) {
|
||||
f.scanErrorsMut.Lock()
|
||||
f.errorsMut.Lock()
|
||||
l.Infof("Scanner (folder %s, item %q): %v", f.Description(), path, err)
|
||||
f.scanErrors = append(f.scanErrors, FileError{
|
||||
Err: err.Error(),
|
||||
Path: path,
|
||||
})
|
||||
f.scanErrorsMut.Unlock()
|
||||
f.errorsMut.Unlock()
|
||||
}
|
||||
|
||||
func (f *folder) clearScanErrors(subDirs []string) {
|
||||
f.scanErrorsMut.Lock()
|
||||
defer f.scanErrorsMut.Unlock()
|
||||
f.errorsMut.Lock()
|
||||
defer f.errorsMut.Unlock()
|
||||
if len(subDirs) == 0 {
|
||||
f.scanErrors = nil
|
||||
return
|
||||
@@ -990,9 +1033,14 @@ outer:
|
||||
}
|
||||
|
||||
func (f *folder) Errors() []FileError {
|
||||
f.scanErrorsMut.Lock()
|
||||
defer f.scanErrorsMut.Unlock()
|
||||
return append([]FileError{}, f.scanErrors...)
|
||||
f.errorsMut.Lock()
|
||||
defer f.errorsMut.Unlock()
|
||||
scanLen := len(f.scanErrors)
|
||||
errors := make([]FileError, scanLen+len(f.pullErrors))
|
||||
copy(errors[:scanLen], f.scanErrors)
|
||||
copy(errors[scanLen:], f.pullErrors)
|
||||
sort.Sort(fileErrorList(errors))
|
||||
return errors
|
||||
}
|
||||
|
||||
// ScheduleForceRescan marks the file such that it gets rehashed on next scan, and schedules a scan.
|
||||
|
||||
111
lib/model/folder_recvenc.go
Normal file
111
lib/model/folder_recvenc.go
Normal file
@@ -0,0 +1,111 @@
|
||||
// Copyright (C) 2018 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/.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/ignore"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/versioner"
|
||||
)
|
||||
|
||||
func init() {
|
||||
folderFactories[config.FolderTypeReceiveEncrypted] = newReceiveEncryptedFolder
|
||||
}
|
||||
|
||||
type receiveEncryptedFolder struct {
|
||||
*sendReceiveFolder
|
||||
}
|
||||
|
||||
func newReceiveEncryptedFolder(model *model, fset *db.FileSet, ignores *ignore.Matcher, cfg config.FolderConfiguration, ver versioner.Versioner, fs fs.Filesystem, evLogger events.Logger, ioLimiter *byteSemaphore) service {
|
||||
return &receiveEncryptedFolder{newSendReceiveFolder(model, fset, ignores, cfg, ver, fs, evLogger, ioLimiter).(*sendReceiveFolder)}
|
||||
}
|
||||
|
||||
func (f *receiveEncryptedFolder) Revert() {
|
||||
f.doInSync(func() error { f.revert(); return nil })
|
||||
}
|
||||
|
||||
func (f *receiveEncryptedFolder) revert() {
|
||||
l.Infof("Reverting unexpected items in folder %v (receive-encrypted)", f.Description())
|
||||
|
||||
f.setState(FolderScanning)
|
||||
defer f.setState(FolderIdle)
|
||||
|
||||
batch := newFileInfoBatch(func(fs []protocol.FileInfo) error {
|
||||
f.updateLocalsFromScanning(fs)
|
||||
return nil
|
||||
})
|
||||
|
||||
snap := f.fset.Snapshot()
|
||||
defer snap.Release()
|
||||
var iterErr error
|
||||
var dirs []string
|
||||
snap.WithHaveTruncated(protocol.LocalDeviceID, func(intf protocol.FileIntf) bool {
|
||||
if iterErr = batch.flushIfFull(); iterErr != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
fit := intf.(db.FileInfoTruncated)
|
||||
if !fit.IsReceiveOnlyChanged() || intf.IsDeleted() {
|
||||
return true
|
||||
}
|
||||
|
||||
if fit.IsDirectory() {
|
||||
dirs = append(dirs, fit.Name)
|
||||
return true
|
||||
}
|
||||
|
||||
if err := f.inWritableDir(f.fs.Remove, fit.Name); err != nil && !fs.IsNotExist(err) {
|
||||
f.newScanError(fit.Name, fmt.Errorf("deleting unexpected item: %w", err))
|
||||
}
|
||||
|
||||
fi := fit.ConvertToDeletedFileInfo(f.shortID)
|
||||
// Set version to zero, such that we pull the global version in case
|
||||
// this is a valid filename that was erroneously changed locally.
|
||||
// Should already be zero from scanning, but lets be safe.
|
||||
fi.Version = protocol.Vector{}
|
||||
// Purposely not removing FlagLocalReceiveOnly as the deleted
|
||||
// item should still not be sent in index updates. However being
|
||||
// deleted, it will not show up as an unexpected file in the UI
|
||||
// anymore.
|
||||
batch.append(fi)
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
f.revertHandleDirs(dirs, snap)
|
||||
|
||||
if iterErr == nil {
|
||||
iterErr = batch.flush()
|
||||
}
|
||||
if iterErr != nil {
|
||||
l.Infoln("Failed to delete unexpected items:", iterErr)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *receiveEncryptedFolder) revertHandleDirs(dirs []string, snap *db.Snapshot) {
|
||||
if len(dirs) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
scanChan := make(chan string)
|
||||
go f.pullScannerRoutine(scanChan)
|
||||
defer close(scanChan)
|
||||
|
||||
sort.Sort(sort.Reverse(sort.StringSlice(dirs)))
|
||||
for _, dir := range dirs {
|
||||
if err := f.deleteDirOnDisk(dir, snap, scanChan); err != nil {
|
||||
f.newScanError(dir, fmt.Errorf("deleting unexpected dir: %w", err))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -431,7 +431,7 @@ func setupKnownFiles(t *testing.T, ffs fs.Filesystem, data []byte) []protocol.Fi
|
||||
Permissions: 0644,
|
||||
Size: fi.Size(),
|
||||
ModifiedS: fi.ModTime().Unix(),
|
||||
ModifiedNs: int32(fi.ModTime().UnixNano() % 1e9),
|
||||
ModifiedNs: int(fi.ModTime().UnixNano() % 1e9),
|
||||
Version: protocol.Vector{Counters: []protocol.Counter{{ID: 42, Value: 42}}},
|
||||
Sequence: 42,
|
||||
Blocks: blocks,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user