Compare commits

...
9 Commits
Author SHA1 Message Date
Audrius Butkevicius 5ce8261d89 Fix build on Solaris 2014-09-28 21:55:08 +01:00
Jakob Borg 25c080b46f Fix config tests for autoUpgradeIntervalH
Conflicts:
	internal/config/config_test.go
2014-09-28 21:49:00 +01:00
Audrius Butkevicius ee765990b7 Add autoUpgrade option in UI
Conflicts:
	gui/app.js
	internal/auto/gui.files.go
2014-09-28 21:20:29 +01:00
Audrius Butkevicius 77fcb52b6a Add autoUpgrade coroutine (fixes #727)
Conflicts:
	internal/config/config.go
2014-09-28 21:19:54 +01:00
Audrius Butkevicius aaec3330a9 Allow a single upgrade at a time 2014-09-28 21:17:44 +01:00
Jakob Borg 3f55a885a1 Don't require godep to build 2014-09-28 21:22:01 +02:00
Jakob Borg 80a1c931a9 Short benchmark test only by default 2014-09-28 21:21:39 +02:00
Jakob Borg a147f4bb77 Genfiles should be random by default 2014-09-28 21:21:28 +02:00
Audrius Butkevicius e4316aec6e Remove field placeholders (fixes #748)
All of them are either required, or empty by default, or for example
node name is later populated on first connection.
2014-09-28 21:04:48 +02:00
15 changed files with 230 additions and 147 deletions
+21 -25
View File
@@ -67,28 +67,22 @@ func main() {
checkRequiredGoVersion()
if check() != nil {
setup()
}
if flag.NArg() == 0 {
install("./cmd/...")
return
}
switch flag.Arg(0) {
for _, cmd := range flag.Args() {
switch cmd {
case "setup":
setup()
case "install":
pkg := "./cmd/..."
if flag.NArg() > 2 {
pkg = flag.Arg(1)
}
install(pkg)
case "build":
pkg := "./cmd/syncthing"
if flag.NArg() > 2 {
pkg = flag.Arg(1)
}
var tags []string
if noupgrade {
tags = []string{"noupgrade"}
@@ -97,9 +91,6 @@ func main() {
case "test":
pkg := "./..."
if flag.NArg() > 2 {
pkg = flag.Arg(1)
}
test(pkg)
case "assets":
@@ -127,13 +118,9 @@ func main() {
clean()
default:
log.Fatalf("Unknown command %q", flag.Arg(0))
log.Fatalf("Unknown command %q", cmd)
}
}
}
func check() error {
_, err := exec.LookPath("godep")
return err
}
func checkRequiredGoVersion() {
@@ -163,24 +150,25 @@ func setup() {
}
func test(pkg string) {
runPrint("godep", "go", "test", "-short", "-timeout", "10s", pkg)
setBuildEnv()
runPrint("go", "test", "-short", "-timeout", "10s", pkg)
}
func install(pkg string) {
os.Setenv("GOBIN", "./bin")
setBuildEnv()
runPrint("godep", "go", "install", "-ldflags", ldflags(), pkg)
runPrint("go", "install", "-ldflags", ldflags(), pkg)
}
func build(pkg string, tags []string) {
rmr("syncthing", "syncthing.exe")
args := []string{"go", "build", "-ldflags", ldflags()}
args := []string{"build", "-ldflags", ldflags()}
if len(tags) > 0 {
args = append(args, "-tags", strings.Join(tags, ","))
}
args = append(args, pkg)
setBuildEnv()
runPrint("godep", args...)
runPrint("go", args...)
}
func buildTar() {
@@ -230,10 +218,18 @@ func setBuildEnv() {
if goarch == "386" {
os.Setenv("GO386", "387")
}
wd, err := os.Getwd()
if err != nil {
log.Println("Warning: can't determine current dir:", err)
log.Println("Build might not work as expected")
}
os.Setenv("GOPATH", fmt.Sprintf("%s%c%s", filepath.Join(wd, "Godeps", "_workspace"), os.PathListSeparator, os.Getenv("GOPATH")))
log.Println("GOPATH=" + os.Getenv("GOPATH"))
}
func assets() {
runPipe("internal/auto/gui.files.go", "godep", "go", "run", "cmd/genassets/main.go", "gui")
setBuildEnv()
runPipe("internal/auto/gui.files.go", "go", "run", "cmd/genassets/main.go", "gui")
}
func xdr() {
+37
View File
@@ -620,6 +620,10 @@ nextRepo:
go standbyMonitor()
}
if cfg.Options.AutoUpgradeIntervalH > 0 {
go autoUpgrade()
}
events.Default.Log(events.StartupComplete, nil)
go generateEvents()
@@ -1172,3 +1176,36 @@ func standbyMonitor() {
now = time.Now()
}
}
func autoUpgrade() {
var skipped bool
interval := time.Duration(cfg.Options.AutoUpgradeIntervalH) * time.Hour
for {
if skipped {
time.Sleep(interval)
} else {
skipped = true
}
rel, err := upgrade.LatestRelease(strings.Contains(Version, "-beta"))
if err != nil {
l.Warnln("Automatic upgrade:", err)
continue
}
if upgrade.CompareVersions(rel.Tag, Version) <= 0 {
continue
}
l.Infof("Automatic upgrade (current %q < latest %q)", Version, rel.Tag)
err = upgrade.UpgradeTo(rel, GoArchExtra)
if err != nil {
l.Warnln("Automatic upgrade:", err)
continue
}
l.Warnf("Automatically upgraded to version %q. Restarting in 1 minute.", rel.Tag)
time.Sleep(time.Minute)
stop <- exitUpgrading
return
}
}
+8
View File
@@ -533,6 +533,7 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca
$scope.tmpOptions = angular.copy($scope.config.Options);
$scope.tmpOptions.UREnabled = ($scope.tmpOptions.URAccepted > 0);
$scope.tmpOptions.NodeName = $scope.thisNode().Name;
$scope.tmpOptions.AutoUpgradeEnabled = ($scope.tmpOptions.AutoUpgradeIntervalH > 0);
$scope.tmpGUI = angular.copy($scope.config.GUI);
$('#settings').modal();
};
@@ -563,6 +564,13 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca
$scope.tmpOptions.URAccepted = -1;
}
// Check if auto-upgrade has been enabled or disabled
if ($scope.tmpOptions.AutoUpgradeEnabled) {
$scope.tmpOptions.AutoUpgradeIntervalH = $scope.tmpOptions.AutoUpgradeIntervalH || 12;
} else {
$scope.tmpOptions.AutoUpgradeIntervalH = 0;
}
// Check if protocol will need to be changed on restart
if ($scope.config.GUI.UseTLS !== $scope.tmpGUI.UseTLS) {
$scope.protocolChanged = true;
+24 -14
View File
@@ -383,13 +383,13 @@
</div>
<div class="form-group">
<label translate for="name">Node Name</label>
<input placeholder="Home Server" id="name" class="form-control" type="text" ng-model="currentNode.Name"></input>
<input id="name" class="form-control" type="text" ng-model="currentNode.Name"></input>
<p translate ng-if="currentNode.NodeID == myID" class="help-block">Shown instead of Node ID in the cluster status. Will be advertised to other nodes as an optional default name.</p>
<p translate ng-if="currentNode.NodeID != myID" class="help-block">Shown instead of Node ID in the cluster status. Will be updated to the name the node advertises if left empty.</p>
</div>
<div class="form-group">
<label translate for="addresses">Addresses</label>
<input placeholder="dynamic" ng-disabled="currentNode.NodeID == myID" id="addresses" class="form-control" type="text" ng-model="currentNode.AddressesStr"></input>
<input ng-disabled="currentNode.NodeID == myID" id="addresses" class="form-control" type="text" ng-model="currentNode.AddressesStr"></input>
<p translate class="help-block">Enter comma separated "ip:port" addresses or "dynamic" to perform automatic discovery of the address.</p>
</div>
<div ng-if="!editingSelf" class="form-group">
@@ -434,7 +434,7 @@
<div class="col-md-12">
<div class="form-group" ng-class="{'has-error': repoEditor.repoID.$invalid && repoEditor.repoID.$dirty}">
<label for="repoID"><span translate>Repository ID</span></label>
<input name="repoID" placeholder="documents" ng-disabled="editingExisting" id="repoID" class="form-control" type="text" ng-model="currentRepo.ID" required unique-repo ng-pattern="/^[a-zA-Z0-9-_.]{1,64}$/"></input>
<input name="repoID" ng-disabled="editingExisting" id="repoID" class="form-control" type="text" ng-model="currentRepo.ID" required unique-repo ng-pattern="/^[a-zA-Z0-9-_.]{1,64}$/"></input>
<p class="help-block">
<span translate ng-if="repoEditor.repoID.$valid || repoEditor.repoID.$pristine">Short identifier for the repository. Must be the same on all cluster nodes.</span>
<span translate ng-if="repoEditor.repoID.$error.uniqueRepo">The repository ID must be unique.</span>
@@ -444,7 +444,7 @@
</div>
<div class="form-group" ng-class="{'has-error': repoEditor.repoPath.$invalid && repoEditor.repoPath.$dirty}">
<label translate for="repoPath">Repository Path</label>
<input name="repoPath" placeholder="~/Documents" ng-disabled="editingExisting" id="repoPath" class="form-control" type="text" ng-model="currentRepo.Directory" required></input>
<input name="repoPath" ng-disabled="editingExisting" id="repoPath" class="form-control" type="text" ng-model="currentRepo.Directory" required></input>
<p class="help-block">
<span translate ng-if="repoEditor.repoPath.$valid || repoEditor.repoPath.$pristine">Path to the repository on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for</span> <code>{{system.tilde}}</code>.
<span translate ng-if="repoEditor.repoPath.$error.required && repoEditor.repoPath.$dirty">The repository path cannot be blank.</span>
@@ -452,7 +452,7 @@
</div>
<div class="form-group" ng-class="{'has-error': repoEditor.rescanIntervalS.$invalid && repoEditor.rescanIntervalS.$dirty}">
<label for="rescanIntervalS"><span translate>Rescan Interval</span> (s)</label>
<input name="rescanIntervalS" placeholder="60" id="rescanIntervalS" class="form-control" type="number" ng-model="currentRepo.RescanIntervalS" required min="5"></input>
<input name="rescanIntervalS" id="rescanIntervalS" class="form-control" type="number" ng-model="currentRepo.RescanIntervalS" required min="5"></input>
<p class="help-block">
<span translate ng-if="!repoEditor.rescanIntervalS.$valid && repoEditor.rescanIntervalS.$dirty">The rescan interval must be at least 5 seconds.</span>
</p>
@@ -528,7 +528,7 @@
</div>
<div class="form-group" ng-if="currentRepo.FileVersioningSelector == 'staggered'">
<label translate for="staggeredVersionsPath">Versions Path</label>
<input name="staggeredVersionsPath" placeholder="" id="staggeredVersionsPath" class="form-control" type="text" ng-model="currentRepo.staggeredVersionsPath"></input>
<input name="staggeredVersionsPath" id="staggeredVersionsPath" class="form-control" type="text" ng-model="currentRepo.staggeredVersionsPath"></input>
<p translate class="help-block">Path where versions should be stored (leave empty for the default .stversions folder in the repository).</p>
</div>
</div>
@@ -606,6 +606,7 @@
<label translate for="MaxSendKbps">Outgoing Rate Limit (KiB/s)</label>
<input id="MaxSendKbps" class="form-control" type="number" ng-model="tmpOptions.MaxSendKbps">
</div>
<div class="col-md-6">
<div class="form-group">
<div class="checkbox">
<label>
@@ -613,14 +614,6 @@
</label>
</div>
</div>
<div class="form-group">
<div class="checkbox">
<label>
<span translate>Local Discovery</span> <input id="LocalAnnEnabled" type="checkbox" ng-model="tmpOptions.LocalAnnEnabled">
</label>
</div>
</div>
<div class="form-group">
<div class="checkbox">
<label>
@@ -628,6 +621,23 @@
</label>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<div class="checkbox">
<label>
<span translate>Automatic upgrades</span> <input id="AutoUpgradeEnabled" type="checkbox" ng-model="tmpOptions.AutoUpgradeEnabled">
</label>
</div>
</div>
<div class="form-group">
<div class="checkbox">
<label>
<span translate>Local Discovery</span> <input id="LocalAnnEnabled" type="checkbox" ng-model="tmpOptions.LocalAnnEnabled">
</label>
</div>
</div>
</div>
<div class="form-group">
<label translate for="GlobalAnnServer">Global Discovery Server</label>
<input ng-disabled="!tmpOptions.GlobalAnnEnabled" id="GlobalAnnServer" class="form-control" type="text" ng-model="tmpOptions.GlobalAnnServer">
File diff suppressed because one or more lines are too long
+1
View File
@@ -128,6 +128,7 @@ type OptionsConfiguration struct {
UPnPRenewal int `xml:"upnpRenewalMinutes" default:"30"`
URAccepted int `xml:"urAccepted"` // Accepted usage reporting version; 0 for off (undecided), -1 for off (permanently)
RestartOnWakeup bool `xml:"restartOnWakeup" default:"true"`
AutoUpgradeIntervalH int `xml:"autoUpgradeIntervalH" default:"12"` // 0 for off
Deprecated_RescanIntervalS int `xml:"rescanIntervalS,omitempty" json:"-"`
Deprecated_UREnabled bool `xml:"urEnabled,omitempty" json:"-"`
+2
View File
@@ -38,6 +38,7 @@ func TestDefaultValues(t *testing.T) {
UPnPLease: 0,
UPnPRenewal: 30,
RestartOnWakeup: true,
AutoUpgradeIntervalH: 12,
}
cfg := New("test", node1)
@@ -130,6 +131,7 @@ func TestOverriddenValues(t *testing.T) {
UPnPLease: 60,
UPnPRenewal: 15,
RestartOnWakeup: false,
AutoUpgradeIntervalH: 24,
}
cfg, err := Load("testdata/overridenvalues.xml", node1)
+1
View File
@@ -16,5 +16,6 @@
<upnpLeaseMinutes>60</upnpLeaseMinutes>
<upnpRenewalMinutes>15</upnpRenewalMinutes>
<restartOnWakeup>false</restartOnWakeup>
<autoUpgradeIntervalH>24</autoUpgradeIntervalH>
</options>
</configuration>
+21
View File
@@ -26,8 +26,29 @@ var (
ErrVersionUpToDate = errors.New("current version is up to date")
ErrVersionUnknown = errors.New("couldn't fetch release information")
ErrUpgradeUnsupported = errors.New("upgrade unsupported")
ErrUpgradeInProgress = errors.New("upgrade already in progress")
upgradeUnlocked = make(chan bool, 1)
)
func init() {
upgradeUnlocked <- true
}
// A wrapper around actual implementations
func UpgradeTo(rel Release, archExtra string) error {
select {
case <-upgradeUnlocked:
err := upgradeTo(rel, archExtra)
// If we've failed to upgrade, unlock so that another attempt could be made
if err != nil {
upgradeUnlocked <- true
}
return err
default:
return ErrUpgradeInProgress
}
}
// Returns 1 if a>b, -1 if a<b and 0 if they are equal
func CompareVersions(a, b string) int {
arel, apre := versionParts(a)
+1 -2
View File
@@ -24,12 +24,11 @@ import (
)
// Upgrade to the given release, saving the previous binary with a ".old" extension.
func UpgradeTo(rel Release, archExtra string) error {
func upgradeTo(rel Release, archExtra string) error {
path, err := osext.Executable()
if err != nil {
return err
}
osName := runtime.GOOS
if osName == "darwin" {
// We call the darwin release bundles macosx because that makes more
+1 -1
View File
@@ -6,7 +6,7 @@
package upgrade
func UpgradeTo(rel Release, extra string) error {
func upgradeTo(rel Release, extra string) error {
return ErrUpgradeUnsupported
}
+1 -2
View File
@@ -24,12 +24,11 @@ import (
)
// Upgrade to the given release, saving the previous binary with a ".old" extension.
func UpgradeTo(rel Release, archExtra string) error {
func upgradeTo(rel Release, archExtra string) error {
path, err := osext.Executable()
if err != nil {
return err
}
expectedRelease := fmt.Sprintf("syncthing-%s-%s%s-%s.", runtime.GOOS, runtime.GOARCH, archExtra, rel.Tag)
if debug {
l.Debugf("expected release asset %q", expectedRelease)
+1 -1
View File
@@ -2,7 +2,7 @@
set -euo pipefail
IFS=$'\n\t'
go test -tags integration -v
go test -tags integration -v -short
./test-http.sh
./test-merge.sh
./test-delupd.sh
+8 -4
View File
@@ -17,10 +17,6 @@ import (
"time"
)
func init() {
rand.Seed(42)
}
func ReadRand(bs []byte) (int, error) {
var r uint32
for i := range bs {
@@ -42,12 +38,20 @@ func main() {
var files int
var maxexp int
var srcname string
var random bool
flag.IntVar(&files, "files", 1000, "Number of files")
flag.IntVar(&maxexp, "maxexp", 20, "Maximum file size (max = 2^n + 128*1024 B)")
flag.StringVar(&srcname, "src", "/usr/share/dict/words", "Source material")
flag.BoolVar(&random, "random", true, "When false, always generate the same set of file")
flag.Parse()
if random {
rand.Seed(time.Now().UnixNano())
} else {
rand.Seed(42)
}
fd, err := os.Open(srcname)
if err != nil {
log.Fatal(err)
+6 -1
View File
@@ -14,6 +14,11 @@ import (
)
func TestBenchmarkTransfer(t *testing.T) {
nfiles := 10000
if testing.Short() {
nfiles = 1000
}
log.Println("Cleaning...")
err := removeAll("s1", "s2", "h1/index", "h2/index")
if err != nil {
@@ -21,7 +26,7 @@ func TestBenchmarkTransfer(t *testing.T) {
}
log.Println("Generating files...")
err = generateFiles("s1", 10000, 22, "../bin/syncthing")
err = generateFiles("s1", nfiles, 22, "../bin/syncthing")
if err != nil {
t.Fatal(err)
}