Compare commits

..

24 Commits

Author SHA1 Message Date
Jakob Borg
67b8ef1f3e cmd/*, lib/build: Set correct LongVersion (fixes #5993) (#5997)
The relay and discosrv didn't use the new lib/build package, now they
do. Conversely the lib/build package wasn't aware there might be other
users and hard coded the program name - now it's set by the build
script
2019-10-07 13:30:25 +02:00
Evgeny Kuznetsov
999d4a0e23 gui: Better info for stalled and lengthy scans (fixes #5627) (#6061) 2019-10-05 11:34:42 +02:00
Lukas Lihotzki
96bb1c8e29 all, lib/logger: Refactor SetDebug calls (#6054) 2019-10-04 13:03:34 +02:00
Audrius Butkevicius
8fb576ed54 lib/model: Adjust blocks reported in usage reporting (fixes #5995) (#6037)
* lib/model: Adjust blocks reported in usage reporting (fixes #5995)

* Use variables, fix go.mod
2019-10-04 12:03:13 +01:00
Jakob Borg
5e31e6356f lib/api: Report actual listener address (fixes #6049) (#6060) 2019-10-04 11:25:41 +01:00
Jakob Borg
1b5a61e03e build: Upgrade github.com/syndtr/goleveldb
Newer is always better. Always.
2019-10-03 17:45:45 +02:00
Jakob Borg
755e689627 lib/db: Always use small db settings on 32 bit archs (#6053) 2019-10-03 13:40:14 +01:00
boomsquared
3f5c9b578c gui: Fix tab headers in black and dark themes (fixes #5583) 2019-10-01 20:09:52 +01:00
Simon Frei
a2a14c8424 lib/model: Set empty version when unignoring deleted files (fixes 6038) (#6039) 2019-10-01 15:34:59 +02:00
Lukas Lihotzki
cff7a091f5 gui: Don't show auth warning when listening on UNIX socket (fixes #6040) (#6041) 2019-10-01 13:22:33 +02:00
Jakob Borg
757d9a5333 Merge branch 'release'
* release:
  readme: Fix broken link to README-Docker.md (#6025)
  docker: Make it easy to disable the GUI, document it (#6021)
2019-10-01 07:46:59 +02:00
Jakob Borg
52d80d8144 lib/fs: Improve root check (#6033)
The root check would allow things like c:\foobar\baz if the root was
c:\foo, because string wise that's a prefix. Now it doesn't.
2019-09-29 23:38:11 +08:00
Ilya Brin
fd2e91c82d readme: Fix broken link to README-Docker.md (#6025) 2019-09-23 13:28:42 +09:00
Jakob Borg
c744a75cdd docker: Make it easy to disable the GUI, document it (#6021) 2019-09-22 11:33:29 +01:00
Simon Frei
35b699dc77 lib/fs: Check events against both the user and eval root (#6013) 2019-09-22 08:03:22 +01:00
Jakob Borg
7127c13f18 build: Tweak golang-ci config to build (#6022) 2019-09-22 07:57:58 +01:00
Jakob Borg
dab29287da Merge branch 'release'
* release:
  gui, lib/api: Use effective listen address for no auth warning
  docker: Build using Go 1.13
2019-09-21 12:10:04 +02:00
Jakob Borg
db0ba2555a gui, lib/api: Use effective listen address for no auth warning
This adds a field `guiAddressUsed` to the system status response, that
holds the current listening address actually in use. This may be
different from the one stored in the config because it may have been
overridden by environment or command line flag.

The GUI now checks this field to see if we are listening on localhost.
If we are not, the authentication required warning is displayed,
regardless of the *configured* listening address.
2019-09-20 16:23:33 +02:00
Jakob Borg
1398fbb681 docker: Build using Go 1.13 2019-09-20 11:02:43 +02:00
dependabot-preview[bot]
f653f540f8 build(deps): bump github.com/urfave/cli from 1.21.0 to 1.22.1 (#6015)
Bumps [github.com/urfave/cli](https://github.com/urfave/cli) from 1.21.0 to 1.22.1.
- [Release notes](https://github.com/urfave/cli/releases)
- [Changelog](https://github.com/urfave/cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/urfave/cli/compare/v1.21.0...v1.22.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-16 08:31:00 +01:00
dependabot-preview[bot]
078923bd1a build(deps): bump github.com/minio/sha256-simd from 0.1.0 to 0.1.1 (#6014)
Bumps [github.com/minio/sha256-simd](https://github.com/minio/sha256-simd) from 0.1.0 to 0.1.1.
- [Release notes](https://github.com/minio/sha256-simd/releases)
- [Commits](https://github.com/minio/sha256-simd/compare/v0.1.0...v0.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-16 08:28:46 +01:00
ghjklw
80a83b605c lib/config: Remove stun.voxgratia.org (fixes #6010) (#6011)
DNS resolution fails for this server:
named[9495]: REFUSED unexpected RCODE resolving 'stun.voxgratia.org/A/IN': 2600:9000:5303:ae00::1#53
named[9495]: REFUSED unexpected RCODE resolving 'stun.voxgratia.org/A/IN': 205.251.198.31#53
2019-09-13 09:05:25 +01:00
Simon Frei
28b6e8b063 lib/db: Update db when only local flags change (fixes #6008) (#6007) 2019-09-12 08:47:39 +02:00
Simon Frei
f7b2e79fdc lib/model: Use read-locks wherever possible (#6005) 2019-09-12 05:55:23 +01:00
55 changed files with 436 additions and 388 deletions

View File

@@ -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

View File

@@ -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()
}

View File

@@ -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,

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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")
}

View File

@@ -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
View File

@@ -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
View File

@@ -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=

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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)
}

View File

@@ -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)
}
}

View File

@@ -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")
}

View File

@@ -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, ", "))

View File

@@ -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",
}
)

View File

@@ -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")
}

View File

@@ -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")
}

View File

@@ -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")
}

View File

@@ -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()
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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")
}

View File

@@ -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")
}

View File

@@ -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)}
}

View File

@@ -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
}

View File

@@ -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:

View File

@@ -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)
}
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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()

View File

@@ -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")
}

View File

@@ -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)

View File

@@ -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()
}

View File

@@ -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)

View File

@@ -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:
}
}

View File

@@ -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")
}

View File

@@ -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")
}

View File

@@ -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")
}

View File

@@ -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")
}

View File

@@ -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")
}

View File

@@ -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")
}

View File

@@ -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")
}

View File

@@ -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")
}

View File

@@ -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
}

View File

@@ -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")
}

View File

@@ -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")
}

View File

@@ -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")
}

View File

@@ -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")
}

View File

@@ -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")
}

View File

@@ -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")
}