mirror of
https://github.com/syncthing/syncthing.git
synced 2026-01-13 00:09:20 -05:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67b8ef1f3e | ||
|
|
999d4a0e23 | ||
|
|
96bb1c8e29 | ||
|
|
8fb576ed54 | ||
|
|
5e31e6356f | ||
|
|
1b5a61e03e | ||
|
|
755e689627 | ||
|
|
3f5c9b578c | ||
|
|
a2a14c8424 | ||
|
|
cff7a091f5 | ||
|
|
757d9a5333 | ||
|
|
52d80d8144 | ||
|
|
fd2e91c82d | ||
|
|
c744a75cdd | ||
|
|
35b699dc77 | ||
|
|
7127c13f18 | ||
|
|
dab29287da | ||
|
|
db0ba2555a | ||
|
|
1398fbb681 | ||
|
|
f653f540f8 | ||
|
|
078923bd1a | ||
|
|
80a83b605c | ||
|
|
28b6e8b063 | ||
|
|
f7b2e79fdc |
@@ -14,7 +14,8 @@ linters:
|
||||
- scopelint
|
||||
|
||||
service:
|
||||
golangci-lint-version: 1.16.x
|
||||
golangci-lint-version: 1.17.x
|
||||
prepare:
|
||||
- rm -f go.sum # 1.12 -> 1.13 issues with QUIC-go
|
||||
- GO111MODULE=on go mod vendor
|
||||
- go run build.go assets
|
||||
|
||||
61
build.go
61
build.go
@@ -24,6 +24,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
@@ -59,7 +60,7 @@ type target struct {
|
||||
debpre string
|
||||
debpost string
|
||||
description string
|
||||
buildPkg string
|
||||
buildPkgs []string
|
||||
binaryName string
|
||||
archiveFiles []archiveFile
|
||||
systemdServices []string
|
||||
@@ -76,9 +77,8 @@ type archiveFile struct {
|
||||
var targets = map[string]target{
|
||||
"all": {
|
||||
// Only valid for the "build" and "install" commands as it lacks all
|
||||
// the archive creation stuff.
|
||||
buildPkg: "github.com/syncthing/syncthing/cmd/...",
|
||||
tags: []string{"purego"},
|
||||
// the archive creation stuff. buildPkgs gets filled out in init()
|
||||
tags: []string{"purego"},
|
||||
},
|
||||
"syncthing": {
|
||||
// The default target for "build", "install", "tar", "zip", "deb", etc.
|
||||
@@ -87,7 +87,7 @@ var targets = map[string]target{
|
||||
debdeps: []string{"libc6", "procps"},
|
||||
debpost: "script/post-upgrade",
|
||||
description: "Open Source Continuous File Synchronization",
|
||||
buildPkg: "github.com/syncthing/syncthing/cmd/syncthing",
|
||||
buildPkgs: []string{"github.com/syncthing/syncthing/cmd/syncthing"},
|
||||
binaryName: "syncthing", // .exe will be added automatically for Windows builds
|
||||
archiveFiles: []archiveFile{
|
||||
{src: "{{binary}}", dst: "{{binary}}", perm: 0755},
|
||||
@@ -131,7 +131,7 @@ var targets = map[string]target{
|
||||
debdeps: []string{"libc6"},
|
||||
debpre: "cmd/stdiscosrv/scripts/preinst",
|
||||
description: "Syncthing Discovery Server",
|
||||
buildPkg: "github.com/syncthing/syncthing/cmd/stdiscosrv",
|
||||
buildPkgs: []string{"github.com/syncthing/syncthing/cmd/stdiscosrv"},
|
||||
binaryName: "stdiscosrv", // .exe will be added automatically for Windows builds
|
||||
archiveFiles: []archiveFile{
|
||||
{src: "{{binary}}", dst: "{{binary}}", perm: 0755},
|
||||
@@ -159,7 +159,7 @@ var targets = map[string]target{
|
||||
debdeps: []string{"libc6"},
|
||||
debpre: "cmd/strelaysrv/scripts/preinst",
|
||||
description: "Syncthing Relay Server",
|
||||
buildPkg: "github.com/syncthing/syncthing/cmd/strelaysrv",
|
||||
buildPkgs: []string{"github.com/syncthing/syncthing/cmd/strelaysrv"},
|
||||
binaryName: "strelaysrv", // .exe will be added automatically for Windows builds
|
||||
archiveFiles: []archiveFile{
|
||||
{src: "{{binary}}", dst: "{{binary}}", perm: 0755},
|
||||
@@ -187,7 +187,7 @@ var targets = map[string]target{
|
||||
debname: "syncthing-relaypoolsrv",
|
||||
debdeps: []string{"libc6"},
|
||||
description: "Syncthing Relay Pool Server",
|
||||
buildPkg: "github.com/syncthing/syncthing/cmd/strelaypoolsrv",
|
||||
buildPkgs: []string{"github.com/syncthing/syncthing/cmd/strelaypoolsrv"},
|
||||
binaryName: "strelaypoolsrv", // .exe will be added automatically for Windows builds
|
||||
archiveFiles: []archiveFile{
|
||||
{src: "{{binary}}", dst: "{{binary}}", perm: 0755},
|
||||
@@ -217,6 +217,18 @@ var dependencyRepos = []dependencyRepo{
|
||||
}
|
||||
|
||||
func init() {
|
||||
all := targets["all"]
|
||||
pkgs, _ := filepath.Glob("cmd/*")
|
||||
for _, pkg := range pkgs {
|
||||
pkg = filepath.Base(pkg)
|
||||
if strings.HasPrefix(pkg, ".") {
|
||||
// ignore dotfiles
|
||||
continue
|
||||
}
|
||||
all.buildPkgs = append(all.buildPkgs, fmt.Sprintf("github.com/syncthing/syncthing/cmd/%s", pkg))
|
||||
}
|
||||
targets["all"] = all
|
||||
|
||||
// The "syncthing" target includes a few more files found in the "etc"
|
||||
// and "extra" dirs.
|
||||
syncthingPkg := targets["syncthing"]
|
||||
@@ -382,9 +394,6 @@ func install(target target, tags []string) {
|
||||
}
|
||||
os.Setenv("GOBIN", filepath.Join(cwd, "bin"))
|
||||
|
||||
args := []string{"install", "-v"}
|
||||
args = appendParameters(args, tags, target)
|
||||
|
||||
os.Setenv("GOOS", goos)
|
||||
os.Setenv("GOARCH", goarch)
|
||||
os.Setenv("CC", cc)
|
||||
@@ -400,19 +409,20 @@ func install(target target, tags []string) {
|
||||
defer shouldCleanupSyso(sysoPath)
|
||||
}
|
||||
|
||||
runPrint(goCmd, args...)
|
||||
for _, pkg := range target.buildPkgs {
|
||||
args := []string{"install", "-v"}
|
||||
args = appendParameters(args, tags, pkg)
|
||||
|
||||
runPrint(goCmd, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func build(target target, tags []string) {
|
||||
lazyRebuildAssets()
|
||||
|
||||
tags = append(target.tags, tags...)
|
||||
|
||||
rmr(target.BinaryName())
|
||||
|
||||
args := []string{"build", "-v"}
|
||||
args = appendParameters(args, tags, target)
|
||||
|
||||
os.Setenv("GOOS", goos)
|
||||
os.Setenv("GOARCH", goarch)
|
||||
os.Setenv("CC", cc)
|
||||
@@ -432,10 +442,15 @@ func build(target target, tags []string) {
|
||||
defer shouldCleanupSyso(sysoPath)
|
||||
}
|
||||
|
||||
runPrint(goCmd, args...)
|
||||
for _, pkg := range target.buildPkgs {
|
||||
args := []string{"build", "-v"}
|
||||
args = appendParameters(args, tags, pkg)
|
||||
|
||||
runPrint(goCmd, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func appendParameters(args []string, tags []string, target target) []string {
|
||||
func appendParameters(args []string, tags []string, pkg string) []string {
|
||||
if pkgdir != "" {
|
||||
args = append(args, "-pkgdir", pkgdir)
|
||||
}
|
||||
@@ -451,7 +466,7 @@ func appendParameters(args []string, tags []string, target target) []string {
|
||||
|
||||
if !debugBinary {
|
||||
// Regular binaries get version tagged and skip some debug symbols
|
||||
args = append(args, "-ldflags", ldflags())
|
||||
args = append(args, "-ldflags", ldflags(path.Base(pkg)))
|
||||
} else {
|
||||
// -gcflags to disable optimizations and inlining. Skip -ldflags
|
||||
// because `Could not launch program: decoding dwarf section info at
|
||||
@@ -460,7 +475,7 @@ func appendParameters(args []string, tags []string, target target) []string {
|
||||
args = append(args, "-gcflags", "-N -l")
|
||||
}
|
||||
|
||||
return append(args, target.buildPkg)
|
||||
return append(args, pkg)
|
||||
}
|
||||
|
||||
func buildTar(target target) {
|
||||
@@ -708,6 +723,7 @@ func listFiles(dir string) []string {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if fi.Mode().IsRegular() {
|
||||
res = append(res, path)
|
||||
}
|
||||
@@ -789,7 +805,7 @@ func transifex() {
|
||||
runPrint(goCmd, "run", "../../../../script/transifexdl.go")
|
||||
}
|
||||
|
||||
func ldflags() string {
|
||||
func ldflags(program string) string {
|
||||
sep := '='
|
||||
if goVersion > 0 && goVersion < 1.5 {
|
||||
sep = ' '
|
||||
@@ -801,8 +817,9 @@ func ldflags() string {
|
||||
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.Stamp%c%d", sep, buildStamp())
|
||||
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.User%c%s", sep, buildUser())
|
||||
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.Host%c%s", sep, buildHost())
|
||||
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.Program%c%s", sep, program)
|
||||
if v := os.Getenv("EXTRA_LDFLAGS"); v != "" {
|
||||
fmt.Fprintf(b, " %s", v);
|
||||
fmt.Fprintf(b, " %s", v)
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/AudriusButkevicius/recli"
|
||||
"github.com/flynn-archive/go-shlex"
|
||||
@@ -128,7 +127,7 @@ func main() {
|
||||
app.HelpName = app.Name
|
||||
app.Author = "The Syncthing Authors"
|
||||
app.Usage = "Syncthing command line interface"
|
||||
app.Version = strings.Replace(build.LongVersion, "syncthing", app.Name, 1)
|
||||
app.Version = build.Version
|
||||
app.Flags = fakeFlags
|
||||
app.Metadata = map[string]interface{}{
|
||||
"client": client,
|
||||
|
||||
@@ -9,17 +9,15 @@ package main
|
||||
import (
|
||||
"crypto/tls"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/tlsutil"
|
||||
"github.com/syndtr/goleveldb/leveldb/opt"
|
||||
@@ -65,24 +63,6 @@ var levelDBOptions = &opt.Options{
|
||||
WriteBuffer: 32 << 20, // default 4<<20
|
||||
}
|
||||
|
||||
var (
|
||||
Version string
|
||||
BuildStamp string
|
||||
BuildUser string
|
||||
BuildHost string
|
||||
|
||||
BuildDate time.Time
|
||||
LongVersion string
|
||||
)
|
||||
|
||||
func init() {
|
||||
stamp, _ := strconv.Atoi(BuildStamp)
|
||||
BuildDate = time.Unix(int64(stamp), 0)
|
||||
|
||||
date := BuildDate.UTC().Format("2006-01-02 15:04:05 MST")
|
||||
LongVersion = fmt.Sprintf(`stdiscosrv %s (%s %s-%s) %s@%s %s`, Version, runtime.Version(), runtime.GOOS, runtime.GOARCH, BuildUser, BuildHost, date)
|
||||
}
|
||||
|
||||
var (
|
||||
debug = false
|
||||
)
|
||||
@@ -109,9 +89,13 @@ func main() {
|
||||
flag.StringVar(&metricsListen, "metrics-listen", "", "Metrics listen address")
|
||||
flag.StringVar(&replicationPeers, "replicate", "", "Replication peers, id@address, comma separated")
|
||||
flag.StringVar(&replicationListen, "replication-listen", ":19200", "Replication listen address")
|
||||
showVersion := flag.Bool("version", false, "Show version")
|
||||
flag.Parse()
|
||||
|
||||
log.Println(LongVersion)
|
||||
log.Println(build.LongVersion)
|
||||
if *showVersion {
|
||||
return
|
||||
}
|
||||
|
||||
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
|
||||
if err != nil {
|
||||
|
||||
@@ -14,12 +14,12 @@ import (
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/relay/protocol"
|
||||
@@ -34,24 +34,6 @@ import (
|
||||
syncthingprotocol "github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
|
||||
var (
|
||||
Version string
|
||||
BuildStamp string
|
||||
BuildUser string
|
||||
BuildHost string
|
||||
|
||||
BuildDate time.Time
|
||||
LongVersion string
|
||||
)
|
||||
|
||||
func init() {
|
||||
stamp, _ := strconv.Atoi(BuildStamp)
|
||||
BuildDate = time.Unix(int64(stamp), 0)
|
||||
|
||||
date := BuildDate.UTC().Format("2006-01-02 15:04:05 MST")
|
||||
LongVersion = fmt.Sprintf(`strelaysrv %s (%s %s-%s) %s@%s %s`, Version, runtime.Version(), runtime.GOOS, runtime.GOARCH, BuildUser, BuildHost, date)
|
||||
}
|
||||
|
||||
var (
|
||||
listen string
|
||||
debug bool
|
||||
@@ -117,8 +99,14 @@ func main() {
|
||||
flag.IntVar(&natTimeout, "nat-timeout", 10, "NAT discovery timeout in seconds")
|
||||
flag.BoolVar(&pprofEnabled, "pprof", false, "Enable the built in profiling on the status server")
|
||||
flag.IntVar(&networkBufferSize, "network-buffer", 2048, "Network buffer size (two of these per proxied connection)")
|
||||
showVersion := flag.Bool("version", false, "Show version")
|
||||
flag.Parse()
|
||||
|
||||
if *showVersion {
|
||||
fmt.Println(build.LongVersion)
|
||||
return
|
||||
}
|
||||
|
||||
if extAddress == "" {
|
||||
extAddress = listen
|
||||
}
|
||||
@@ -147,7 +135,7 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
log.Println(LongVersion)
|
||||
log.Println(build.LongVersion)
|
||||
|
||||
maxDescriptors, err := osutil.MaximizeOpenFileLimit()
|
||||
if maxDescriptors > 0 {
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"runtime"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
)
|
||||
|
||||
var rc *rateCalculator
|
||||
@@ -40,10 +42,10 @@ func getStatus(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
sessionMut.Lock()
|
||||
// This can potentially be double the number of pending sessions, as each session has two keys, one for each side.
|
||||
status["version"] = Version
|
||||
status["buildHost"] = BuildHost
|
||||
status["buildUser"] = BuildUser
|
||||
status["buildDate"] = BuildDate
|
||||
status["version"] = build.Version
|
||||
status["buildHost"] = build.Host
|
||||
status["buildUser"] = build.User
|
||||
status["buildDate"] = build.Date
|
||||
status["startTime"] = rc.startTime
|
||||
status["uptimeSeconds"] = time.Since(rc.startTime) / time.Second
|
||||
status["numPendingSessionKeys"] = len(pendingSessions)
|
||||
|
||||
@@ -7,16 +7,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("main", "Main package")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("main", strings.Contains(os.Getenv("STTRACE"), "main") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
// 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/.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
buf := make([]byte, 4096)
|
||||
var err error
|
||||
for err == nil {
|
||||
n, err := io.ReadFull(os.Stdin, buf)
|
||||
if n > 0 {
|
||||
buf = buf[:n]
|
||||
repl := bytes.Replace(buf, []byte("\n"), []byte("\r\n"), -1)
|
||||
_, err = os.Stdout.Write(repl)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
if err == io.EOF {
|
||||
return
|
||||
}
|
||||
buf = buf[:cap(buf)]
|
||||
}
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
6
go.mod
6
go.mod
@@ -25,7 +25,7 @@ require (
|
||||
github.com/lucas-clemente/quic-go v0.12.0
|
||||
github.com/maruel/panicparse v1.3.0
|
||||
github.com/mattn/go-isatty v0.0.9
|
||||
github.com/minio/sha256-simd v0.1.0
|
||||
github.com/minio/sha256-simd v0.1.1
|
||||
github.com/onsi/ginkgo v1.9.0 // indirect
|
||||
github.com/onsi/gomega v1.6.0 // indirect
|
||||
github.com/oschwald/geoip2-golang v1.3.0
|
||||
@@ -39,9 +39,9 @@ require (
|
||||
github.com/sasha-s/go-deadlock v0.2.0
|
||||
github.com/shirou/gopsutil v0.0.0-20190714054239-47ef3260b6bf
|
||||
github.com/syncthing/notify v0.0.0-20190709140112-69c7a957d3e2
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d
|
||||
github.com/thejerf/suture v3.0.2+incompatible
|
||||
github.com/urfave/cli v1.21.0
|
||||
github.com/urfave/cli v1.22.1
|
||||
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0
|
||||
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297
|
||||
|
||||
16
go.sum
16
go.sum
@@ -29,6 +29,8 @@ github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitf
|
||||
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/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/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=
|
||||
@@ -109,8 +111,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j
|
||||
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/minio/sha256-simd v0.1.0 h1:U41/2erhAKcmSI14xh/ZTUdBPOzDOIfS93ibzUSl8KM=
|
||||
github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
|
||||
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/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=
|
||||
@@ -159,11 +161,15 @@ github.com/prometheus/procfs v0.0.4 h1:w8DjqFMJDjuVwdZBQoOozr4MVWOnwF7RcL/7uxBjY
|
||||
github.com/prometheus/procfs v0.0.4/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/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/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/shirou/gopsutil v0.0.0-20190714054239-47ef3260b6bf h1:c9SV5NzG4KOk448TUE7iqCmb4E4y79CZF4zDdc1Jx3Q=
|
||||
github.com/shirou/gopsutil v0.0.0-20190714054239-47ef3260b6bf/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
|
||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
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=
|
||||
@@ -175,12 +181,14 @@ github.com/syncthing/notify v0.0.0-20190709140112-69c7a957d3e2 h1:6tuEEEpg+mxM82
|
||||
github.com/syncthing/notify v0.0.0-20190709140112-69c7a957d3e2/go.mod h1:Sn4ChoS7e4FxjCN1XHPVBT43AgnRLbuaB8pEc1Zcdjg=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965 h1:1oFLiOyVl+W7bnBzGhf7BbIv9loSFQcieWWYIjLqcAw=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d h1:gZZadD8H+fF+n9CmNhYL1Y0dJB+kLOmKd7FbPJLeGHs=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA=
|
||||
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/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.21.0 h1:wYSSj06510qPIzGSua9ZqsncMmWE3Zr55KBERygyrxE=
|
||||
github.com/urfave/cli v1.21.0/go.mod h1:lxDj6qX9Q6lWQxIrbrT0nwecwUtRnhVZAJjJZrVUZZQ=
|
||||
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
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=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
|
||||
@@ -24,6 +24,27 @@ a:hover,a:focus,a.focus{
|
||||
border-width: 2px !important;
|
||||
}
|
||||
|
||||
|
||||
.nav-tabs > li.active > a,
|
||||
.nav-tabs > li.active > a:hover,
|
||||
.nav-tabs > li.active > a:focus {
|
||||
color: #3498db !important;
|
||||
background-color: #222222 !important;
|
||||
border: 1px solid #222222 !important;
|
||||
border-bottom-color: transparent !important;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.nav-tabs{
|
||||
border-bottom: 1px solid #333;
|
||||
}
|
||||
|
||||
.nav-tabs > li > a:hover,
|
||||
.nav-tabs > li > a:focus {
|
||||
background-color: #222222 !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.navbar-text, .dropdown>a, .dropdown-menu>li>a, .hidden-xs>a, .navbar-link {
|
||||
color: #aaa !important;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,27 @@ a:hover,a:focus,a.focus{
|
||||
|
||||
}
|
||||
|
||||
.nav-tabs > li.active > a,
|
||||
.nav-tabs > li.active > a:hover,
|
||||
.nav-tabs > li.active > a:focus {
|
||||
color: #3498db !important;
|
||||
background-color: #424242 !important;
|
||||
border: 1px solid #424242 !important;
|
||||
border-bottom-color: transparent !important;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.nav-tabs{
|
||||
border-bottom: 1px solid #333;
|
||||
}
|
||||
|
||||
.nav-tabs > li > a:hover,
|
||||
.nav-tabs > li > a:focus {
|
||||
background-color: #424242 !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
|
||||
.navbar-text, .dropdown>a, .dropdown-menu>li>a, .hidden-xs>a, .navbar-link {
|
||||
color: #aaa !important;
|
||||
}
|
||||
|
||||
@@ -439,6 +439,7 @@ angular.module('syncthing.core')
|
||||
var guiCfg = $scope.config.gui;
|
||||
$scope.openNoAuth = addr.substr(0, 4) !== "127."
|
||||
&& addr.substr(0, 6) !== "[::1]:"
|
||||
&& addr.substr(0, 1) !== "/"
|
||||
&& (!guiCfg.user || !guiCfg.password)
|
||||
&& guiCfg.authMode !== 'ldap'
|
||||
&& !guiCfg.insecureAdminAccess;
|
||||
@@ -852,6 +853,9 @@ angular.module('syncthing.core')
|
||||
// 32m 40s
|
||||
// 2h 32m
|
||||
// 4d 2h
|
||||
// In case remaining scan time appears to be >31d, omit the
|
||||
// details, i.e.:
|
||||
// > 1 month
|
||||
|
||||
if (!$scope.scanProgress[folder]) {
|
||||
return "";
|
||||
@@ -871,6 +875,9 @@ angular.module('syncthing.core')
|
||||
var res = [];
|
||||
if (seconds >= 86400) {
|
||||
days = Math.floor(seconds / 86400);
|
||||
if (days > 31) {
|
||||
return '> 1 month';
|
||||
}
|
||||
res.push('' + days + 'd')
|
||||
seconds = seconds % 86400;
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ type service struct {
|
||||
started chan string // signals startup complete by sending the listener address, for testing only
|
||||
startedOnce chan struct{} // the service has started successfully at least once
|
||||
startupErr error
|
||||
listenerAddr net.Addr
|
||||
|
||||
guiErrors logger.Recorder
|
||||
systemLog logger.Recorder
|
||||
@@ -222,6 +223,7 @@ func (s *service) serve(stop chan struct{}) {
|
||||
return
|
||||
}
|
||||
|
||||
s.listenerAddr = listener.Addr()
|
||||
defer listener.Close()
|
||||
|
||||
s.cfg.Subscribe(s)
|
||||
@@ -913,7 +915,7 @@ func (s *service) getSystemStatus(w http.ResponseWriter, r *http.Request) {
|
||||
res["uptime"] = s.urService.UptimeS()
|
||||
res["startTime"] = ur.StartTime
|
||||
res["guiAddressOverridden"] = s.cfg.GUI().IsOverridden()
|
||||
res["guiAddressUsed"] = s.cfg.GUI().Address()
|
||||
res["guiAddressUsed"] = s.listenerAddr.String()
|
||||
|
||||
sendJSON(w, res)
|
||||
}
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
@@ -24,5 +21,7 @@ func shouldDebugHTTP() bool {
|
||||
func init() {
|
||||
// The debug facility was originally named "http", changed in:
|
||||
// https://github.com/syncthing/syncthing/pull/5548
|
||||
l.SetDebug("api", strings.Contains(os.Getenv("STTRACE"), "api") || strings.Contains(os.Getenv("STTRACE"), "http") || os.Getenv("STTRACE") == "all")
|
||||
if l.IsTraced("http") {
|
||||
l.SetDebug("api", true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,16 +7,9 @@
|
||||
package beacon
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("beacon", "Multicast and broadcast discovery")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("beacon", strings.Contains(os.Getenv("STTRACE"), "beacon") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -18,10 +18,11 @@ import (
|
||||
|
||||
var (
|
||||
// Injected by build script
|
||||
Program = "syncthing"
|
||||
Version = "unknown-dev"
|
||||
Host = "unknown" // Set by build script
|
||||
User = "unknown" // Set by build script
|
||||
Stamp = "0" // Set by build script
|
||||
Host = "unknown"
|
||||
User = "unknown"
|
||||
Stamp = "0"
|
||||
|
||||
// Static
|
||||
Codename = "Fermium Flea"
|
||||
@@ -73,7 +74,7 @@ func setBuildData() {
|
||||
Date = time.Unix(int64(stamp), 0)
|
||||
|
||||
date := Date.UTC().Format("2006-01-02 15:04:05 MST")
|
||||
LongVersion = fmt.Sprintf(`syncthing %s "%s" (%s %s-%s) %s@%s %s`, Version, Codename, runtime.Version(), runtime.GOOS, runtime.GOARCH, User, Host, date)
|
||||
LongVersion = fmt.Sprintf(`%s %s "%s" (%s %s-%s) %s@%s %s`, Program, Version, Codename, runtime.Version(), runtime.GOOS, runtime.GOARCH, User, Host, date)
|
||||
|
||||
if len(Tags) > 0 {
|
||||
LongVersion = fmt.Sprintf("%s [%s]", LongVersion, strings.Join(Tags, ", "))
|
||||
|
||||
@@ -87,7 +87,6 @@ var (
|
||||
"stun.voiparound.com:3478",
|
||||
"stun.voipbuster.com:3478",
|
||||
"stun.voipstunt.com:3478",
|
||||
"stun.voxgratia.org:3478",
|
||||
"stun.xten.com:3478",
|
||||
}
|
||||
)
|
||||
|
||||
@@ -7,16 +7,9 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("config", "Configuration loading and saving")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("config", strings.Contains(os.Getenv("STTRACE"), "config") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -7,16 +7,9 @@
|
||||
package connections
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("connections", "Connection handling")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("connections", strings.Contains(os.Getenv("STTRACE"), "connections") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
@@ -17,10 +14,6 @@ var (
|
||||
l = logger.DefaultLogger.NewFacility("db", "The database layer")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("db", strings.Contains(os.Getenv("STTRACE"), "db") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
func shouldDebug() bool {
|
||||
return l.ShouldDebug("db")
|
||||
}
|
||||
|
||||
@@ -562,7 +562,7 @@ func (e errorSuggestion) Error() string {
|
||||
|
||||
// unchanged checks if two files are the same and thus don't need to be updated.
|
||||
// Local flags or the invalid bit might change without the version
|
||||
// being bumped. The IsInvalid() method handles both.
|
||||
// being bumped.
|
||||
func unchanged(nf, ef FileIntf) bool {
|
||||
return ef.FileVersion().Equal(nf.FileVersion()) && ef.IsInvalid() == nf.IsInvalid()
|
||||
return ef.FileVersion().Equal(nf.FileVersion()) && ef.IsInvalid() == nf.IsInvalid() && ef.FileLocalFlags() == nf.FileLocalFlags()
|
||||
}
|
||||
|
||||
@@ -267,6 +267,13 @@ func (db *Lowlevel) Close() {
|
||||
// dbIsLarge returns whether the estimated size of the database at location
|
||||
// is large enough to warrant optimization for large databases.
|
||||
func dbIsLarge(location string) bool {
|
||||
if ^uint(0)>>63 == 0 {
|
||||
// We're compiled for a 32 bit architecture. We've seen trouble with
|
||||
// large settings there.
|
||||
// (https://forum.syncthing.net/t/many-small-ldb-files-with-database-tuning/13842)
|
||||
return false
|
||||
}
|
||||
|
||||
dir, err := os.Open(location)
|
||||
if err != nil {
|
||||
return false
|
||||
|
||||
@@ -1462,6 +1462,33 @@ func TestSequenceIndex(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIgnoreAfterReceiveOnly(t *testing.T) {
|
||||
ldb := db.OpenMemory()
|
||||
|
||||
file := "foo"
|
||||
s := db.NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb)
|
||||
|
||||
fs := fileList{{
|
||||
Name: file,
|
||||
Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1}}},
|
||||
LocalFlags: protocol.FlagLocalReceiveOnly,
|
||||
}}
|
||||
|
||||
s.Update(protocol.LocalDeviceID, fs)
|
||||
|
||||
fs[0].LocalFlags = protocol.FlagLocalIgnored
|
||||
|
||||
s.Update(protocol.LocalDeviceID, fs)
|
||||
|
||||
if f, ok := s.Get(protocol.LocalDeviceID, file); !ok {
|
||||
t.Error("File missing in db")
|
||||
} else if f.IsReceiveOnlyChanged() {
|
||||
t.Error("File is still receive-only changed")
|
||||
} else if !f.IsIgnored() {
|
||||
t.Error("File is not ignored")
|
||||
}
|
||||
}
|
||||
|
||||
func replace(fs *db.FileSet, device protocol.DeviceID, files []protocol.FileInfo) {
|
||||
fs.Drop(device)
|
||||
fs.Update(device, files)
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/proxy"
|
||||
@@ -29,8 +28,6 @@ var (
|
||||
type dialFunc func(network, addr string) (net.Conn, error)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("dialer", strings.Contains(os.Getenv("STTRACE"), "dialer") || os.Getenv("STTRACE") == "all")
|
||||
|
||||
proxy.RegisterDialerType("socks", socksDialerFunction)
|
||||
proxyDialer = getDialer(proxy.Direct)
|
||||
usingProxy = proxyDialer != proxy.Direct
|
||||
|
||||
@@ -7,16 +7,9 @@
|
||||
package discover
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("discover", "Remote device discovery")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("discover", strings.Contains(os.Getenv("STTRACE"), "discover") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -7,16 +7,9 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
liblogger "github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
dl = liblogger.DefaultLogger.NewFacility("events", "Event generation and logging")
|
||||
)
|
||||
|
||||
func init() {
|
||||
dl.SetDebug("events", strings.Contains(os.Getenv("STTRACE"), "events") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -345,6 +345,6 @@ func (e *ErrWatchEventOutsideRoot) Error() string {
|
||||
return e.msg
|
||||
}
|
||||
|
||||
func (f *BasicFilesystem) newErrWatchEventOutsideRoot(absPath, root string) *ErrWatchEventOutsideRoot {
|
||||
return &ErrWatchEventOutsideRoot{fmt.Sprintf("Watching for changes encountered an event outside of the filesystem root: f.root==%v, root==%v, path==%v. This should never happen, please report this message to forum.syncthing.net.", f.root, root, absPath)}
|
||||
func (f *BasicFilesystem) newErrWatchEventOutsideRoot(absPath string, roots []string) *ErrWatchEventOutsideRoot {
|
||||
return &ErrWatchEventOutsideRoot{fmt.Sprintf("Watching for changes encountered an event outside of the filesystem root: f.root==%v, roots==%v, path==%v. This should never happen, please report this message to forum.syncthing.net.", f.root, roots, absPath)}
|
||||
}
|
||||
|
||||
@@ -60,14 +60,20 @@ func (f *BasicFilesystem) Roots() ([]string, error) {
|
||||
// unrooted) or an error if the given path is not a subpath and handles the
|
||||
// special case when the given path is the folder root without a trailing
|
||||
// pathseparator.
|
||||
func (f *BasicFilesystem) unrootedChecked(absPath, root string) (string, *ErrWatchEventOutsideRoot) {
|
||||
if absPath+string(PathSeparator) == root {
|
||||
return ".", nil
|
||||
func (f *BasicFilesystem) unrootedChecked(absPath string, roots []string) (string, *ErrWatchEventOutsideRoot) {
|
||||
for _, root := range roots {
|
||||
// Make sure the root ends with precisely one path separator, to
|
||||
// ease prefix comparisons.
|
||||
root := strings.TrimRight(root, string(PathSeparator)) + string(PathSeparator)
|
||||
|
||||
if absPath+string(PathSeparator) == root {
|
||||
return ".", nil
|
||||
}
|
||||
if strings.HasPrefix(absPath, root) {
|
||||
return rel(absPath, root), nil
|
||||
}
|
||||
}
|
||||
if !strings.HasPrefix(absPath, root) {
|
||||
return "", f.newErrWatchEventOutsideRoot(absPath, root)
|
||||
}
|
||||
return rel(absPath, root), nil
|
||||
return "", f.newErrWatchEventOutsideRoot(absPath, roots)
|
||||
}
|
||||
|
||||
func rel(path, prefix string) string {
|
||||
@@ -78,16 +84,16 @@ var evalSymlinks = filepath.EvalSymlinks
|
||||
|
||||
// watchPaths adjust the folder root for use with the notify backend and the
|
||||
// corresponding absolute path to be passed to notify to watch name.
|
||||
func (f *BasicFilesystem) watchPaths(name string) (string, string, error) {
|
||||
func (f *BasicFilesystem) watchPaths(name string) (string, []string, error) {
|
||||
root, err := evalSymlinks(f.root)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
absName, err := rooted(name, root)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
return filepath.Join(absName, "..."), root, nil
|
||||
return filepath.Join(absName, "..."), []string{root}, nil
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
var backendBuffer = 500
|
||||
|
||||
func (f *BasicFilesystem) Watch(name string, ignore Matcher, ctx context.Context, ignorePerms bool) (<-chan Event, <-chan error, error) {
|
||||
watchPath, root, err := f.watchPaths(name)
|
||||
watchPath, roots, err := f.watchPaths(name)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -36,7 +36,7 @@ func (f *BasicFilesystem) Watch(name string, ignore Matcher, ctx context.Context
|
||||
|
||||
if ignore.SkipIgnoredDirs() {
|
||||
absShouldIgnore := func(absPath string) bool {
|
||||
rel, err := f.unrootedChecked(absPath, root)
|
||||
rel, err := f.unrootedChecked(absPath, roots)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
@@ -55,12 +55,12 @@ func (f *BasicFilesystem) Watch(name string, ignore Matcher, ctx context.Context
|
||||
}
|
||||
|
||||
errChan := make(chan error)
|
||||
go f.watchLoop(name, root, backendChan, outChan, errChan, ignore, ctx)
|
||||
go f.watchLoop(name, roots, backendChan, outChan, errChan, ignore, ctx)
|
||||
|
||||
return outChan, errChan, nil
|
||||
}
|
||||
|
||||
func (f *BasicFilesystem) watchLoop(name, evalRoot string, backendChan chan notify.EventInfo, outChan chan<- Event, errChan chan<- error, ignore Matcher, ctx context.Context) {
|
||||
func (f *BasicFilesystem) watchLoop(name string, roots []string, backendChan chan notify.EventInfo, outChan chan<- Event, errChan chan<- error, ignore Matcher, ctx context.Context) {
|
||||
for {
|
||||
// Detect channel overflow
|
||||
if len(backendChan) == backendBuffer {
|
||||
@@ -79,7 +79,7 @@ func (f *BasicFilesystem) watchLoop(name, evalRoot string, backendChan chan noti
|
||||
|
||||
select {
|
||||
case ev := <-backendChan:
|
||||
relPath, err := f.unrootedChecked(ev.Path(), evalRoot)
|
||||
relPath, err := f.unrootedChecked(ev.Path(), roots)
|
||||
if err != nil {
|
||||
select {
|
||||
case errChan <- err:
|
||||
|
||||
@@ -166,7 +166,7 @@ func TestWatchWinRoot(t *testing.T) {
|
||||
// testFs is Filesystem, but we need BasicFilesystem here
|
||||
root := `D:\`
|
||||
fs := newBasicFilesystem(root)
|
||||
watch, root, err := fs.watchPaths(".")
|
||||
watch, roots, err := fs.watchPaths(".")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -178,7 +178,7 @@ func TestWatchWinRoot(t *testing.T) {
|
||||
}
|
||||
cancel()
|
||||
}()
|
||||
fs.watchLoop(".", root, backendChan, outChan, errChan, fakeMatcher{}, ctx)
|
||||
fs.watchLoop(".", roots, backendChan, outChan, errChan, fakeMatcher{}, ctx)
|
||||
}()
|
||||
|
||||
// filepath.Dir as watch has a /... suffix
|
||||
@@ -201,23 +201,33 @@ func TestWatchWinRoot(t *testing.T) {
|
||||
|
||||
// TestWatchOutside checks that no changes from outside the folder make it in
|
||||
func TestWatchOutside(t *testing.T) {
|
||||
expectErrorForPath(t, filepath.Join(filepath.Dir(testDirAbs), "outside"))
|
||||
|
||||
rootWithoutSlash := strings.TrimRight(filepath.ToSlash(testDirAbs), "/")
|
||||
expectErrorForPath(t, rootWithoutSlash+"outside")
|
||||
expectErrorForPath(t, rootWithoutSlash+"outside/thing")
|
||||
}
|
||||
|
||||
func expectErrorForPath(t *testing.T, path string) {
|
||||
outChan := make(chan Event)
|
||||
backendChan := make(chan notify.EventInfo, backendBuffer)
|
||||
errChan := make(chan error)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
// testFs is Filesystem, but we need BasicFilesystem here
|
||||
fs := newBasicFilesystem(testDirAbs)
|
||||
|
||||
go fs.watchLoop(".", testDirAbs, backendChan, outChan, errChan, fakeMatcher{}, ctx)
|
||||
go fs.watchLoop(".", []string{testDirAbs}, backendChan, outChan, errChan, fakeMatcher{}, ctx)
|
||||
|
||||
backendChan <- fakeEventInfo(filepath.Join(filepath.Dir(testDirAbs), "outside"))
|
||||
backendChan <- fakeEventInfo(path)
|
||||
|
||||
select {
|
||||
case <-time.After(10 * time.Second):
|
||||
cancel()
|
||||
t.Errorf("Timed out before receiving error")
|
||||
case e := <-outChan:
|
||||
t.Errorf("Unexpected passed through event %v", e)
|
||||
case <-errChan:
|
||||
case <-ctx.Done():
|
||||
}
|
||||
@@ -234,7 +244,7 @@ func TestWatchSubpath(t *testing.T) {
|
||||
fs := newBasicFilesystem(testDirAbs)
|
||||
|
||||
abs, _ := fs.rooted("sub")
|
||||
go fs.watchLoop("sub", testDirAbs, backendChan, outChan, errChan, fakeMatcher{}, ctx)
|
||||
go fs.watchLoop("sub", []string{testDirAbs}, backendChan, outChan, errChan, fakeMatcher{}, ctx)
|
||||
|
||||
backendChan <- fakeEventInfo(filepath.Join(abs, "file"))
|
||||
|
||||
@@ -347,7 +357,7 @@ func TestWatchSymlinkedRoot(t *testing.T) {
|
||||
|
||||
func TestUnrootedChecked(t *testing.T) {
|
||||
fs := newBasicFilesystem(testDirAbs)
|
||||
if unrooted, err := fs.unrootedChecked("/random/other/path", testDirAbs); err == nil {
|
||||
if unrooted, err := fs.unrootedChecked("/random/other/path", []string{testDirAbs}); err == nil {
|
||||
t.Error("unrootedChecked did not return an error on outside path, but returned", unrooted)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,17 +156,19 @@ func (f *BasicFilesystem) Roots() ([]string, error) {
|
||||
// unrooted) or an error if the given path is not a subpath and handles the
|
||||
// special case when the given path is the folder root without a trailing
|
||||
// pathseparator.
|
||||
func (f *BasicFilesystem) unrootedChecked(absPath, root string) (string, error) {
|
||||
func (f *BasicFilesystem) unrootedChecked(absPath string, roots []string) (string, error) {
|
||||
absPath = f.resolveWin83(absPath)
|
||||
lowerAbsPath := UnicodeLowercase(absPath)
|
||||
lowerRoot := UnicodeLowercase(root)
|
||||
if lowerAbsPath+string(PathSeparator) == lowerRoot {
|
||||
return ".", nil
|
||||
for _, root := range roots {
|
||||
lowerRoot := UnicodeLowercase(root)
|
||||
if lowerAbsPath+string(PathSeparator) == lowerRoot {
|
||||
return ".", nil
|
||||
}
|
||||
if strings.HasPrefix(lowerAbsPath, lowerRoot) {
|
||||
return rel(absPath, root), nil
|
||||
}
|
||||
}
|
||||
if !strings.HasPrefix(lowerAbsPath, lowerRoot) {
|
||||
return "", f.newErrWatchEventOutsideRoot(lowerAbsPath, lowerRoot)
|
||||
}
|
||||
return rel(absPath, root), nil
|
||||
return "", f.newErrWatchEventOutsideRoot(lowerAbsPath, roots)
|
||||
}
|
||||
|
||||
func rel(path, prefix string) string {
|
||||
@@ -294,10 +296,10 @@ func evalSymlinks(in string) (string, error) {
|
||||
|
||||
// watchPaths adjust the folder root for use with the notify backend and the
|
||||
// corresponding absolute path to be passed to notify to watch name.
|
||||
func (f *BasicFilesystem) watchPaths(name string) (string, string, error) {
|
||||
func (f *BasicFilesystem) watchPaths(name string) (string, []string, error) {
|
||||
root, err := evalSymlinks(f.root)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
// Remove `\\?\` prefix if the path is just a drive letter as a dirty
|
||||
@@ -308,11 +310,17 @@ func (f *BasicFilesystem) watchPaths(name string) (string, string, error) {
|
||||
|
||||
absName, err := rooted(name, root)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
root = f.resolveWin83(root)
|
||||
roots := []string{f.resolveWin83(root)}
|
||||
absName = f.resolveWin83(absName)
|
||||
|
||||
return filepath.Join(absName, "..."), root, nil
|
||||
// Events returned from fs watching are all over the place, so allow
|
||||
// both the user's input and the result of "canonicalizing" the path.
|
||||
if roots[0] != f.root {
|
||||
roots = append(roots, f.root)
|
||||
}
|
||||
|
||||
return filepath.Join(absName, "..."), roots, nil
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ func TestRelUnrootedCheckedWindows(t *testing.T) {
|
||||
// on these test cases.
|
||||
for _, root := range []string{tc.root, strings.ToLower(tc.root), strings.ToUpper(tc.root)} {
|
||||
fs := BasicFilesystem{root: root}
|
||||
if res, err := fs.unrootedChecked(tc.abs, tc.root); err != nil {
|
||||
if res, err := fs.unrootedChecked(tc.abs, []string{tc.root}); err != nil {
|
||||
t.Errorf(`Unexpected error from unrootedChecked("%v", "%v"): %v (fs.root: %v)`, tc.abs, tc.root, err, root)
|
||||
} else if res != tc.expectedRel {
|
||||
t.Errorf(`unrootedChecked("%v", "%v") == "%v", expected "%v" (fs.root: %v)`, tc.abs, tc.root, res, tc.expectedRel, root)
|
||||
@@ -140,6 +140,21 @@ func TestRelUnrootedCheckedWindows(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestMultipleRoot checks that fs.unrootedChecked returns the correct path
|
||||
// when given more than one possible root path.
|
||||
func TestMultipleRoot(t *testing.T) {
|
||||
root := `c:\foO`
|
||||
roots := []string{root, `d:\`}
|
||||
rel := `bar`
|
||||
path := filepath.Join(root, rel)
|
||||
fs := BasicFilesystem{root: root}
|
||||
if res, err := fs.unrootedChecked(path, roots); err != nil {
|
||||
t.Errorf(`Unexpected error from unrootedChecked("%v", "%v"): %v (fs.root: %v)`, path, roots, err, root)
|
||||
} else if res != rel {
|
||||
t.Errorf(`unrootedChecked("%v", "%v") == "%v", expected "%v" (fs.root: %v)`, path, roots, res, rel, root)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFinalPath(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input string
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
@@ -19,11 +16,7 @@ var (
|
||||
|
||||
func init() {
|
||||
logger.DefaultLogger.NewFacility("walkfs", "Filesystem access while walking")
|
||||
switch {
|
||||
case strings.Contains(os.Getenv("STTRACE"), "walkfs") || os.Getenv("STTRACE") == "all":
|
||||
l.SetDebug("walkfs", true)
|
||||
fallthrough
|
||||
case strings.Contains(os.Getenv("STTRACE"), "fs"):
|
||||
if logger.DefaultLogger.ShouldDebug("walkfs") {
|
||||
l.SetDebug("fs", true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ type Logger interface {
|
||||
Warnf(format string, vals ...interface{})
|
||||
ShouldDebug(facility string) bool
|
||||
SetDebug(facility string, enabled bool)
|
||||
IsTraced(facility string) bool
|
||||
Facilities() map[string]string
|
||||
FacilityDebugging() []string
|
||||
NewFacility(facility, description string) Logger
|
||||
@@ -60,6 +61,7 @@ type logger struct {
|
||||
handlers [NumLevels][]MessageHandler
|
||||
facilities map[string]string // facility name => description
|
||||
debug map[string]struct{} // only facility names with debugging enabled
|
||||
traces string
|
||||
mut sync.Mutex
|
||||
}
|
||||
|
||||
@@ -78,6 +80,7 @@ func New() Logger {
|
||||
func newLogger(w io.Writer) Logger {
|
||||
return &logger{
|
||||
logger: log.New(w, "", DefaultFlags),
|
||||
traces: os.Getenv("STTRACE"),
|
||||
facilities: make(map[string]string),
|
||||
debug: make(map[string]struct{}),
|
||||
}
|
||||
@@ -210,6 +213,11 @@ func (l *logger) SetDebug(facility string, enabled bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// IsTraced returns whether the facility name is contained in STTRACE.
|
||||
func (l *logger) IsTraced(facility string) bool {
|
||||
return strings.Contains(l.traces, facility) || l.traces == "all"
|
||||
}
|
||||
|
||||
// FacilityDebugging returns the set of facilities that have debugging
|
||||
// enabled.
|
||||
func (l *logger) FacilityDebugging() []string {
|
||||
@@ -236,6 +244,8 @@ func (l *logger) Facilities() map[string]string {
|
||||
|
||||
// NewFacility returns a new logger bound to the named facility.
|
||||
func (l *logger) NewFacility(facility, description string) Logger {
|
||||
l.SetDebug(facility, l.IsTraced(facility))
|
||||
|
||||
l.mut.Lock()
|
||||
l.facilities[facility] = description
|
||||
l.mut.Unlock()
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
@@ -17,10 +14,6 @@ var (
|
||||
l = logger.DefaultLogger.NewFacility("model", "The root hub")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("model", strings.Contains(os.Getenv("STTRACE"), "model") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
func shouldDebug() bool {
|
||||
return l.ShouldDebug("model")
|
||||
}
|
||||
|
||||
@@ -478,7 +478,7 @@ func (f *folder) scanSubdirs(subDirs []string) error {
|
||||
return true
|
||||
}
|
||||
|
||||
l.Debugln("marking file as ignored", f)
|
||||
l.Debugln("marking file as ignored", file)
|
||||
nf := file.ConvertToIgnoredFileInfo(f.shortID)
|
||||
batch.append(nf)
|
||||
changes++
|
||||
@@ -512,12 +512,11 @@ func (f *folder) scanSubdirs(subDirs []string) error {
|
||||
LocalFlags: f.localFlags,
|
||||
}
|
||||
// We do not want to override the global version
|
||||
// with the deleted file. Keeping only our local
|
||||
// counter makes sure we are in conflict with any
|
||||
// other existing versions, which will be resolved
|
||||
// by the normal pulling mechanisms.
|
||||
// with the deleted file. Setting to an empty
|
||||
// version makes sure the file gets in sync on
|
||||
// the following pull.
|
||||
if file.ShouldConflict() {
|
||||
nf.Version = nf.Version.DropOthers(f.shortID)
|
||||
nf.Version = protocol.Vector{}
|
||||
}
|
||||
|
||||
batch.append(nf)
|
||||
|
||||
@@ -982,8 +982,9 @@ func (f *sendReceiveFolder) renameFile(cur, source, target protocol.FileInfo, db
|
||||
}
|
||||
|
||||
blockStatsMut.Lock()
|
||||
blockStats["total"] += len(target.Blocks)
|
||||
blockStats["renamed"] += len(target.Blocks)
|
||||
minBlocksPerBlock := target.BlockSize() / protocol.MinBlockSize
|
||||
blockStats["total"] += len(target.Blocks) * minBlocksPerBlock
|
||||
blockStats["renamed"] += len(target.Blocks) * minBlocksPerBlock
|
||||
blockStatsMut.Unlock()
|
||||
|
||||
// The file was renamed, so we have handled both the necessary delete
|
||||
@@ -1559,15 +1560,16 @@ func (f *sendReceiveFolder) finisherRoutine(in <-chan *sharedPullerState, dbUpda
|
||||
if err != nil {
|
||||
f.newPullError(state.file.Name, err)
|
||||
} else {
|
||||
minBlocksPerBlock := state.file.BlockSize() / protocol.MinBlockSize
|
||||
blockStatsMut.Lock()
|
||||
blockStats["total"] += state.reused + state.copyTotal + state.pullTotal
|
||||
blockStats["reused"] += state.reused
|
||||
blockStats["pulled"] += state.pullTotal
|
||||
blockStats["total"] += (state.reused + state.copyTotal + state.pullTotal) * minBlocksPerBlock
|
||||
blockStats["reused"] += state.reused * minBlocksPerBlock
|
||||
blockStats["pulled"] += state.pullTotal * minBlocksPerBlock
|
||||
// copyOriginShifted is counted towards copyOrigin due to progress bar reasons
|
||||
// for reporting reasons we want to separate these.
|
||||
blockStats["copyOrigin"] += state.copyOrigin - state.copyOriginShifted
|
||||
blockStats["copyOriginShifted"] += state.copyOriginShifted
|
||||
blockStats["copyElsewhere"] += state.copyTotal - state.copyOrigin
|
||||
blockStats["copyOrigin"] += (state.copyOrigin - state.copyOriginShifted) * minBlocksPerBlock
|
||||
blockStats["copyOriginShifted"] += state.copyOriginShifted * minBlocksPerBlock
|
||||
blockStats["copyElsewhere"] += (state.copyTotal - state.copyOrigin) * minBlocksPerBlock
|
||||
blockStatsMut.Unlock()
|
||||
}
|
||||
|
||||
|
||||
@@ -644,9 +644,11 @@ func (m *model) ConnectionStats() map[string]interface{} {
|
||||
|
||||
// DeviceStatistics returns statistics about each device
|
||||
func (m *model) DeviceStatistics() map[string]stats.DeviceStatistics {
|
||||
res := make(map[string]stats.DeviceStatistics)
|
||||
for id := range m.cfg.Devices() {
|
||||
res[id.String()] = m.deviceStatRef(id).GetStatistics()
|
||||
m.fmut.RLock()
|
||||
defer m.fmut.RUnlock()
|
||||
res := make(map[string]stats.DeviceStatistics, len(m.deviceStatRefs))
|
||||
for id, sr := range m.deviceStatRefs {
|
||||
res[id.String()] = sr.GetStatistics()
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -1449,14 +1451,14 @@ func (m *model) Closed(conn protocol.Connection, err error) {
|
||||
func (m *model) closeConns(devs []protocol.DeviceID, err error) config.Waiter {
|
||||
conns := make([]connections.Connection, 0, len(devs))
|
||||
closed := make([]chan struct{}, 0, len(devs))
|
||||
m.pmut.Lock()
|
||||
m.pmut.RLock()
|
||||
for _, dev := range devs {
|
||||
if conn, ok := m.conn[dev]; ok {
|
||||
conns = append(conns, conn)
|
||||
closed = append(closed, m.closed[dev])
|
||||
}
|
||||
}
|
||||
m.pmut.Unlock()
|
||||
m.pmut.RUnlock()
|
||||
for _, conn := range conns {
|
||||
conn.Close(err)
|
||||
}
|
||||
@@ -1906,21 +1908,13 @@ func (m *model) DownloadProgress(device protocol.DeviceID, folder string, update
|
||||
})
|
||||
}
|
||||
|
||||
func (m *model) deviceStatRef(deviceID protocol.DeviceID) *stats.DeviceStatisticsReference {
|
||||
m.fmut.Lock()
|
||||
defer m.fmut.Unlock()
|
||||
|
||||
if sr, ok := m.deviceStatRefs[deviceID]; ok {
|
||||
return sr
|
||||
}
|
||||
|
||||
sr := stats.NewDeviceStatisticsReference(m.db, deviceID.String())
|
||||
m.deviceStatRefs[deviceID] = sr
|
||||
return sr
|
||||
}
|
||||
|
||||
func (m *model) deviceWasSeen(deviceID protocol.DeviceID) {
|
||||
m.deviceStatRef(deviceID).WasSeen()
|
||||
m.fmut.RLock()
|
||||
sr, ok := m.deviceStatRefs[deviceID]
|
||||
m.fmut.RUnlock()
|
||||
if ok {
|
||||
sr.WasSeen()
|
||||
}
|
||||
}
|
||||
|
||||
type indexSender struct {
|
||||
@@ -2125,9 +2119,9 @@ func (m *model) ScanFolderSubdirs(folder string, subs []string) error {
|
||||
}
|
||||
|
||||
func (m *model) DelayScan(folder string, next time.Duration) {
|
||||
m.fmut.Lock()
|
||||
m.fmut.RLock()
|
||||
runner, ok := m.folderRunners[folder]
|
||||
m.fmut.Unlock()
|
||||
m.fmut.RUnlock()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@@ -2137,10 +2131,10 @@ func (m *model) DelayScan(folder string, next time.Duration) {
|
||||
// numHashers returns the number of hasher routines to use for a given folder,
|
||||
// taking into account configuration and available CPU cores.
|
||||
func (m *model) numHashers(folder string) int {
|
||||
m.fmut.Lock()
|
||||
m.fmut.RLock()
|
||||
folderCfg := m.folderCfgs[folder]
|
||||
numFolders := len(m.folderCfgs)
|
||||
m.fmut.Unlock()
|
||||
m.fmut.RUnlock()
|
||||
|
||||
if folderCfg.Hashers > 0 {
|
||||
// Specific value set in the config, use that.
|
||||
@@ -2553,7 +2547,15 @@ func (m *model) CommitConfiguration(from, to config.Configuration) bool {
|
||||
toDevices := to.DeviceMap()
|
||||
for deviceID, toCfg := range toDevices {
|
||||
fromCfg, ok := fromDevices[deviceID]
|
||||
if !ok || fromCfg.Paused == toCfg.Paused {
|
||||
if !ok {
|
||||
sr := stats.NewDeviceStatisticsReference(m.db, deviceID.String())
|
||||
m.fmut.Lock()
|
||||
m.deviceStatRefs[deviceID] = sr
|
||||
m.fmut.Unlock()
|
||||
continue
|
||||
}
|
||||
delete(fromDevices, deviceID)
|
||||
if fromCfg.Paused == toCfg.Paused {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -2570,6 +2572,11 @@ func (m *model) CommitConfiguration(from, to config.Configuration) bool {
|
||||
m.evLogger.Log(events.DeviceResumed, map[string]string{"device": deviceID.String()})
|
||||
}
|
||||
}
|
||||
m.fmut.Lock()
|
||||
for deviceID := range fromDevices {
|
||||
delete(m.deviceStatRefs, deviceID)
|
||||
}
|
||||
m.fmut.Unlock()
|
||||
|
||||
scanLimiter.setCapacity(to.Options.MaxConcurrentScans)
|
||||
|
||||
|
||||
@@ -377,18 +377,25 @@ func pullInvalidIgnored(t *testing.T, ft config.FolderType) {
|
||||
if f.IsInvalid() {
|
||||
t.Errorf("File %v is still marked as invalid", f.Name)
|
||||
}
|
||||
// The unignored files should only have a local version,
|
||||
// to mark them as in conflict with any other existing versions.
|
||||
ev := protocol.Vector{}.Update(myID.Short())
|
||||
if v := f.Version; !v.Equal(ev) {
|
||||
t.Errorf("File %v has version %v, expected %v", f.Name, v, ev)
|
||||
}
|
||||
ev := protocol.Vector{}
|
||||
if f.Name == ign {
|
||||
// The unignored deleted file should have an
|
||||
// empty version, to make it not override
|
||||
// existing global files.
|
||||
if !f.Deleted {
|
||||
t.Errorf("File %v was not marked as deleted", f.Name)
|
||||
}
|
||||
} else if f.Deleted {
|
||||
t.Errorf("File %v is marked as deleted", f.Name)
|
||||
} else {
|
||||
// The unignored existing file should have a
|
||||
// version with only a local counter, to make
|
||||
// it conflict changed global files.
|
||||
ev = protocol.Vector{}.Update(myID.Short())
|
||||
if f.Deleted {
|
||||
t.Errorf("File %v is marked as deleted", f.Name)
|
||||
}
|
||||
}
|
||||
if v := f.Version; !v.Equal(ev) {
|
||||
t.Errorf("File %v has version %v, expected %v", f.Name, v, ev)
|
||||
}
|
||||
delete(expected, f.Name)
|
||||
}
|
||||
@@ -453,8 +460,8 @@ func TestIssue4841(t *testing.T) {
|
||||
|
||||
f := checkReceived(<-received)
|
||||
|
||||
if expected := (protocol.Vector{}.Update(myID.Short())); !f.Version.Equal(expected) {
|
||||
t.Errorf("Got Version == %v, expected %v", f.Version, expected)
|
||||
if !f.Version.Equal(protocol.Vector{}) {
|
||||
t.Errorf("Got Version == %v, expected empty version", f.Version)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1014,3 +1021,112 @@ func TestNeedFolderFiles(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestIgnoreDeleteUnignore checks that the deletion of an ignored file is not
|
||||
// propagated upon un-ignoring.
|
||||
// https://github.com/syncthing/syncthing/issues/6038
|
||||
func TestIgnoreDeleteUnignore(t *testing.T) {
|
||||
w, fcfg := tmpDefaultWrapper()
|
||||
m := setupModel(w)
|
||||
fss := fcfg.Filesystem()
|
||||
tmpDir := fss.URI()
|
||||
defer cleanupModelAndRemoveDir(m, tmpDir)
|
||||
|
||||
m.RemoveFolder(fcfg)
|
||||
m.AddFolder(fcfg)
|
||||
// Reach in and update the ignore matcher to one that always does
|
||||
// reloads when asked to, instead of checking file mtimes. This is
|
||||
// because we might be changing the files on disk often enough that the
|
||||
// mtimes will be unreliable to determine change status.
|
||||
m.fmut.Lock()
|
||||
m.folderIgnores["default"] = ignore.New(fss, ignore.WithChangeDetector(newAlwaysChanged()))
|
||||
m.fmut.Unlock()
|
||||
m.StartFolder(fcfg.ID)
|
||||
|
||||
fc := addFakeConn(m, device1)
|
||||
fc.folder = "default"
|
||||
fc.mut.Lock()
|
||||
fc.mut.Unlock()
|
||||
|
||||
file := "foobar"
|
||||
contents := []byte("test file contents\n")
|
||||
|
||||
basicCheck := func(fs []protocol.FileInfo) {
|
||||
t.Helper()
|
||||
if len(fs) != 1 {
|
||||
t.Fatal("expected a single index entry, got", len(fs))
|
||||
} else if fs[0].Name != file {
|
||||
t.Fatalf("expected a index entry for %v, got one for %v", file, fs[0].Name)
|
||||
}
|
||||
}
|
||||
|
||||
done := make(chan struct{})
|
||||
fc.mut.Lock()
|
||||
fc.indexFn = func(folder string, fs []protocol.FileInfo) {
|
||||
basicCheck(fs)
|
||||
close(done)
|
||||
}
|
||||
fc.mut.Unlock()
|
||||
|
||||
if err := ioutil.WriteFile(filepath.Join(fss.URI(), file), contents, 0644); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
m.ScanFolders()
|
||||
|
||||
select {
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatalf("timed out before index was received")
|
||||
case <-done:
|
||||
}
|
||||
|
||||
done = make(chan struct{})
|
||||
fc.mut.Lock()
|
||||
fc.indexFn = func(folder string, fs []protocol.FileInfo) {
|
||||
basicCheck(fs)
|
||||
f := fs[0]
|
||||
if !f.IsInvalid() {
|
||||
t.Errorf("Received non-invalid index update")
|
||||
}
|
||||
close(done)
|
||||
}
|
||||
fc.mut.Unlock()
|
||||
|
||||
if err := m.SetIgnores("default", []string{"foobar"}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatal("timed out before receiving index update")
|
||||
case <-done:
|
||||
}
|
||||
|
||||
done = make(chan struct{})
|
||||
fc.mut.Lock()
|
||||
fc.indexFn = func(folder string, fs []protocol.FileInfo) {
|
||||
basicCheck(fs)
|
||||
f := fs[0]
|
||||
if f.IsInvalid() {
|
||||
t.Errorf("Received invalid index update")
|
||||
}
|
||||
if !f.Version.Equal(protocol.Vector{}) && f.Deleted {
|
||||
t.Error("Received deleted index entry with non-empty version")
|
||||
}
|
||||
l.Infoln(f)
|
||||
close(done)
|
||||
}
|
||||
fc.mut.Unlock()
|
||||
|
||||
if err := fss.Remove(file); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.SetIgnores("default", []string{}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatalf("timed out before index was received")
|
||||
case <-done:
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,16 +7,9 @@
|
||||
package nat
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("nat", "NAT discovery and port mapping")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("nat", strings.Contains(os.Getenv("STTRACE"), "nat") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -7,16 +7,9 @@
|
||||
package pmp
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("pmp", "NAT-PMP discovery and port mapping")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("pmp", strings.Contains(os.Getenv("STTRACE"), "pmp") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -3,16 +3,9 @@
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("protocol", "The BEP protocol")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("protocol", strings.Contains(os.Getenv("STTRACE"), "protocol") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -7,16 +7,9 @@
|
||||
package rc
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("rc", "Remote control package")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("rc", strings.Contains(os.Getenv("STTRACE"), "rc") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -3,16 +3,9 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("relay", "")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("relay", strings.Contains(os.Getenv("STTRACE"), "relay") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -7,16 +7,9 @@
|
||||
package scanner
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("scanner", "File change detection and hashing")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("scanner", strings.Contains(os.Getenv("STTRACE"), "scanner") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -7,16 +7,9 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("stats", "Persistent device and folder statistics")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("stats", strings.Contains(os.Getenv("STTRACE"), "stats") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -7,16 +7,9 @@
|
||||
package stun
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("stun", "STUN functionality")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("stun", strings.Contains(os.Getenv("STTRACE"), "stun") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ package sync
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
deadlock "github.com/sasha-s/go-deadlock"
|
||||
@@ -23,13 +22,11 @@ var (
|
||||
// We make an exception in this package and have an actual "if debug { ...
|
||||
// }" variable, as it may be rather performance critical and does
|
||||
// nonstandard things (from a debug logging PoV).
|
||||
debug = strings.Contains(os.Getenv("STTRACE"), "sync") || os.Getenv("STTRACE") == "all"
|
||||
debug = logger.DefaultLogger.ShouldDebug("sync")
|
||||
useDeadlock = false
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("sync", strings.Contains(os.Getenv("STTRACE"), "sync") || os.Getenv("STTRACE") == "all")
|
||||
|
||||
if n, _ := strconv.Atoi(os.Getenv("STLOCKTHRESHOLD")); n > 0 {
|
||||
threshold = time.Duration(n) * time.Millisecond
|
||||
}
|
||||
|
||||
@@ -7,16 +7,9 @@
|
||||
package syncthing
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("app", "Main run facility")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("app", strings.Contains(os.Getenv("STTRACE"), "app") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -7,16 +7,9 @@
|
||||
package upgrade
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("upgrade", "Binary upgrades")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("upgrade", strings.Contains(os.Getenv("STTRACE"), "upgrade") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -7,16 +7,9 @@
|
||||
package upnp
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("upnp", "UPnP discovery and port mapping")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("upnp", strings.Contains(os.Getenv("STTRACE"), "upnp") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -7,16 +7,9 @@
|
||||
package ur
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("ur", "Usage reporting")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("ur", strings.Contains(os.Getenv("STTRACE"), "ur") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -7,16 +7,9 @@
|
||||
package versioner
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("versioner", "File versioning")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("versioner", strings.Contains(os.Getenv("STTRACE"), "versioner") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
@@ -7,18 +7,9 @@
|
||||
package watchaggregator
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var facilityName = "watchaggregator"
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility(facilityName, "Filesystem event watcher")
|
||||
l = logger.DefaultLogger.NewFacility("watchaggregator", "Filesystem event watcher")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug(facilityName, strings.Contains(os.Getenv("STTRACE"), facilityName) || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user