diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a8abb8551..0d55f12b1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,7 +12,7 @@ least the following: - What operating system, operating system version and version of Syncthing you are running - - The same for other connected nodes, where relevant + - The same for other connected devices, where relevant - Screenshot if the issue concerns something visible in the GUI diff --git a/README.md b/README.md index 3ebd0667e..080e8edf7 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ syncthing This is the `syncthing` project. The following are the project goals: - 1. Define a protocol for synchronization of a file repository between a - number of collaborating nodes. The protocol should be well defined, + 1. Define a protocol for synchronization of a file folder between a + number of collaborating devices. The protocol should be well defined, unambiguous, easily understood, free to use, efficient, secure and language neutral. This is the [Block Exchange Protocol](https://github.com/syncthing/syncthing/blob/master/protocol/PROTOCOL.md). diff --git a/cmd/stindex/main.go b/cmd/stindex/main.go index 4494b117e..3be124a96 100644 --- a/cmd/stindex/main.go +++ b/cmd/stindex/main.go @@ -19,8 +19,8 @@ func main() { log.SetFlags(0) log.SetOutput(os.Stdout) - repo := flag.String("repo", "default", "Repository ID") - node := flag.String("node", "", "Node ID (blank for global)") + folder := flag.String("folder", "default", "Folder ID") + device := flag.String("device", "", "Device ID (blank for global)") flag.Parse() db, err := leveldb.OpenFile(flag.Arg(0), nil) @@ -28,10 +28,10 @@ func main() { log.Fatal(err) } - fs := files.NewSet(*repo, db) + fs := files.NewSet(*folder, db) - if *node == "" { - log.Printf("*** Global index for repo %q", *repo) + if *device == "" { + log.Printf("*** Global index for folder %q", *folder) fs.WithGlobalTruncated(func(fi protocol.FileIntf) bool { f := fi.(protocol.FileInfoTruncated) fmt.Println(f) @@ -39,11 +39,11 @@ func main() { return true }) } else { - n, err := protocol.NodeIDFromString(*node) + n, err := protocol.DeviceIDFromString(*device) if err != nil { log.Fatal(err) } - log.Printf("*** Have index for repo %q node %q", *repo, n) + log.Printf("*** Have index for folder %q device %q", *folder, n) fs.WithHaveTruncated(n, func(fi protocol.FileIntf) bool { f := fi.(protocol.FileInfoTruncated) fmt.Println(f) diff --git a/cmd/syncthing/gui.go b/cmd/syncthing/gui.go index 74601aca0..ce873cb44 100644 --- a/cmd/syncthing/gui.go +++ b/cmd/syncthing/gui.go @@ -88,12 +88,12 @@ func startGUI(cfg config.GUIConfiguration, assetDir string, m *model.Model) erro getRestMux.HandleFunc("/rest/lang", restGetLang) getRestMux.HandleFunc("/rest/model", withModel(m, restGetModel)) getRestMux.HandleFunc("/rest/need", withModel(m, restGetNeed)) - getRestMux.HandleFunc("/rest/nodeid", restGetNodeID) + getRestMux.HandleFunc("/rest/deviceid", restGetDeviceID) getRestMux.HandleFunc("/rest/report", withModel(m, restGetReport)) getRestMux.HandleFunc("/rest/system", restGetSystem) getRestMux.HandleFunc("/rest/upgrade", restGetUpgrade) getRestMux.HandleFunc("/rest/version", restGetVersion) - getRestMux.HandleFunc("/rest/stats/node", withModel(m, restGetNodeStats)) + getRestMux.HandleFunc("/rest/stats/device", withModel(m, restGetDeviceStats)) // Debug endpoints, not for general use getRestMux.HandleFunc("/rest/debug/peerCompletion", withModel(m, restGetPeerCompletion)) @@ -220,17 +220,17 @@ func restGetVersion(w http.ResponseWriter, r *http.Request) { func restGetCompletion(m *model.Model, w http.ResponseWriter, r *http.Request) { var qs = r.URL.Query() - var repo = qs.Get("repo") - var nodeStr = qs.Get("node") + var folder = qs.Get("folder") + var deviceStr = qs.Get("device") - node, err := protocol.NodeIDFromString(nodeStr) + device, err := protocol.DeviceIDFromString(deviceStr) if err != nil { http.Error(w, err.Error(), 500) return } res := map[string]float64{ - "completion": m.Completion(node, repo), + "completion": m.Completion(device, folder), } w.Header().Set("Content-Type", "application/json; charset=utf-8") @@ -239,29 +239,29 @@ func restGetCompletion(m *model.Model, w http.ResponseWriter, r *http.Request) { func restGetModel(m *model.Model, w http.ResponseWriter, r *http.Request) { var qs = r.URL.Query() - var repo = qs.Get("repo") + var folder = qs.Get("folder") var res = make(map[string]interface{}) - for _, cr := range cfg.Repositories { - if cr.ID == repo { + for _, cr := range cfg.Folders { + if cr.ID == folder { res["invalid"] = cr.Invalid break } } - globalFiles, globalDeleted, globalBytes := m.GlobalSize(repo) + globalFiles, globalDeleted, globalBytes := m.GlobalSize(folder) res["globalFiles"], res["globalDeleted"], res["globalBytes"] = globalFiles, globalDeleted, globalBytes - localFiles, localDeleted, localBytes := m.LocalSize(repo) + localFiles, localDeleted, localBytes := m.LocalSize(folder) res["localFiles"], res["localDeleted"], res["localBytes"] = localFiles, localDeleted, localBytes - needFiles, needBytes := m.NeedSize(repo) + needFiles, needBytes := m.NeedSize(folder) res["needFiles"], res["needBytes"] = needFiles, needBytes res["inSyncFiles"], res["inSyncBytes"] = globalFiles-needFiles, globalBytes-needBytes - res["state"], res["stateChanged"] = m.State(repo) - res["version"] = m.CurrentLocalVersion(repo) + m.RemoteLocalVersion(repo) + res["state"], res["stateChanged"] = m.State(folder) + res["version"] = m.CurrentLocalVersion(folder) + m.RemoteLocalVersion(folder) w.Header().Set("Content-Type", "application/json; charset=utf-8") json.NewEncoder(w).Encode(res) @@ -269,15 +269,15 @@ func restGetModel(m *model.Model, w http.ResponseWriter, r *http.Request) { func restPostOverride(m *model.Model, w http.ResponseWriter, r *http.Request) { var qs = r.URL.Query() - var repo = qs.Get("repo") - go m.Override(repo) + var folder = qs.Get("folder") + go m.Override(folder) } func restGetNeed(m *model.Model, w http.ResponseWriter, r *http.Request) { var qs = r.URL.Query() - var repo = qs.Get("repo") + var folder = qs.Get("folder") - files := m.NeedFilesRepoLimited(repo, 100, 2500) // max 100 files or 2500 blocks + files := m.NeedFilesFolderLimited(folder, 100, 2500) // max 100 files or 2500 blocks w.Header().Set("Content-Type", "application/json; charset=utf-8") json.NewEncoder(w).Encode(files) @@ -289,8 +289,8 @@ func restGetConnections(m *model.Model, w http.ResponseWriter, r *http.Request) json.NewEncoder(w).Encode(res) } -func restGetNodeStats(m *model.Model, w http.ResponseWriter, r *http.Request) { - var res = m.NodeStatistics() +func restGetDeviceStats(m *model.Model, w http.ResponseWriter, r *http.Request) { + var res = m.DeviceStatistics() w.Header().Set("Content-Type", "application/json; charset=utf-8") json.NewEncoder(w).Encode(res) } @@ -357,8 +357,8 @@ func restPostRestart(w http.ResponseWriter, r *http.Request) { } func restPostReset(w http.ResponseWriter, r *http.Request) { - flushResponse(`{"ok": "resetting repos"}`, w) - resetRepositories() + flushResponse(`{"ok": "resetting folders"}`, w) + resetFolders() go restart() } @@ -431,10 +431,10 @@ func showGuiError(l logger.LogLevel, err string) { func restPostDiscoveryHint(w http.ResponseWriter, r *http.Request) { var qs = r.URL.Query() - var node = qs.Get("node") + var device = qs.Get("device") var addr = qs.Get("addr") - if len(node) != 0 && len(addr) != 0 && discoverer != nil { - discoverer.Hint(node, []string{addr}) + if len(device) != 0 && len(addr) != 0 && discoverer != nil { + discoverer.Hint(device, []string{addr}) } } @@ -451,7 +451,7 @@ func restGetIgnores(m *model.Model, w http.ResponseWriter, r *http.Request) { qs := r.URL.Query() w.Header().Set("Content-Type", "application/json; charset=utf-8") - ignores, err := m.GetIgnores(qs.Get("repo")) + ignores, err := m.GetIgnores(qs.Get("folder")) if err != nil { http.Error(w, err.Error(), 500) return @@ -473,7 +473,7 @@ func restPostIgnores(m *model.Model, w http.ResponseWriter, r *http.Request) { return } - err = m.SetIgnores(qs.Get("repo"), data["ignore"]) + err = m.SetIgnores(qs.Get("folder"), data["ignore"]) if err != nil { http.Error(w, err.Error(), 500) return @@ -519,10 +519,10 @@ func restGetUpgrade(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(res) } -func restGetNodeID(w http.ResponseWriter, r *http.Request) { +func restGetDeviceID(w http.ResponseWriter, r *http.Request) { qs := r.URL.Query() idStr := qs.Get("id") - id, err := protocol.NodeIDFromString(idStr) + id, err := protocol.DeviceIDFromString(idStr) w.Header().Set("Content-Type", "application/json; charset=utf-8") if err == nil { json.NewEncoder(w).Encode(map[string]string{ @@ -570,9 +570,9 @@ func restPostUpgrade(w http.ResponseWriter, r *http.Request) { func restPostScan(m *model.Model, w http.ResponseWriter, r *http.Request) { qs := r.URL.Query() - repo := qs.Get("repo") + folder := qs.Get("folder") sub := qs.Get("sub") - err := m.ScanRepoSub(repo, sub) + err := m.ScanFolderSub(folder, sub) if err != nil { http.Error(w, err.Error(), 500) } @@ -595,21 +595,21 @@ func restGetPeerCompletion(m *model.Model, w http.ResponseWriter, r *http.Reques tot := map[string]float64{} count := map[string]float64{} - for _, repo := range cfg.Repositories { - for _, node := range repo.NodeIDs() { - nodeStr := node.String() - if m.ConnectedTo(node) { - tot[nodeStr] += m.Completion(node, repo.ID) + for _, folder := range cfg.Folders { + for _, device := range folder.DeviceIDs() { + deviceStr := device.String() + if m.ConnectedTo(device) { + tot[deviceStr] += m.Completion(device, folder.ID) } else { - tot[nodeStr] = 0 + tot[deviceStr] = 0 } - count[nodeStr]++ + count[deviceStr]++ } } comp := map[string]int{} - for node := range tot { - comp[node] = int(tot[node] / count[node]) + for device := range tot { + comp[device] = int(tot[device] / count[device]) } w.Header().Set("Content-Type", "application/json; charset=utf-8") diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index 0cf5f48b2..369c2dc68 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -84,7 +84,7 @@ func init() { var ( cfg config.Configuration - myID protocol.NodeID + myID protocol.DeviceID confDir string logFlags int = log.Ltime writeRateLimit *ratelimit.Bucket @@ -208,7 +208,7 @@ func main() { cert, err := loadCert(dir, "") if err == nil { l.Warnln("Key exists; will not overwrite.") - l.Infoln("Node ID:", protocol.NewNodeID(cert.Certificate[0])) + l.Infoln("Device ID:", protocol.NewDeviceID(cert.Certificate[0])) return } @@ -218,7 +218,7 @@ func main() { l.Fatalln("load cert:", err) } if err == nil { - l.Infoln("Node ID:", protocol.NewNodeID(cert.Certificate[0])) + l.Infoln("Device ID:", protocol.NewDeviceID(cert.Certificate[0])) } return } @@ -264,7 +264,7 @@ func main() { } if reset { - resetRepositories() + resetFolders() return } @@ -319,7 +319,7 @@ func syncthingMain() { } } - myID = protocol.NewNodeID(cert.Certificate[0]) + myID = protocol.NewDeviceID(cert.Certificate[0]) l.SetPrefix(fmt.Sprintf("[%s] ", myID.String()[:5])) l.Infoln(LongVersion) @@ -336,7 +336,7 @@ func syncthingMain() { cfg, err = config.Load(cfgFile, myID) if err == nil { - myCfg := cfg.GetNodeConfiguration(myID) + myCfg := cfg.GetDeviceConfiguration(myID) if myCfg == nil || myCfg.Name == "" { myName, _ = os.Hostname() } else { @@ -345,20 +345,20 @@ func syncthingMain() { } else { l.Infoln("No config file; starting with empty defaults") myName, _ = os.Hostname() - defaultRepo := filepath.Join(getHomeDir(), "Sync") + defaultFolder := filepath.Join(getHomeDir(), "Sync") cfg = config.New(cfgFile, myID) - cfg.Repositories = []config.RepositoryConfiguration{ + cfg.Folders = []config.FolderConfiguration{ { ID: "default", - Directory: defaultRepo, + Directory: defaultFolder, RescanIntervalS: 60, - Nodes: []config.RepositoryNodeConfiguration{{NodeID: myID}}, + Devices: []config.FolderDeviceConfiguration{{DeviceID: myID}}, }, } - cfg.Nodes = []config.NodeConfiguration{ + cfg.Devices = []config.DeviceConfiguration{ { - NodeID: myID, + DeviceID: myID, Addresses: []string{"dynamic"}, Name: myName, }, @@ -422,48 +422,48 @@ func syncthingMain() { l.Fatalln("Cannot open database:", err, "- Is another copy of Syncthing already running?") } - // Remove database entries for repos that no longer exist in the config - repoMap := cfg.RepoMap() - for _, repo := range files.ListRepos(db) { - if _, ok := repoMap[repo]; !ok { - l.Infof("Cleaning data for dropped repo %q", repo) - files.DropRepo(db, repo) + // Remove database entries for folders that no longer exist in the config + folderMap := cfg.FolderMap() + for _, folder := range files.ListFolders(db) { + if _, ok := folderMap[folder]; !ok { + l.Infof("Cleaning data for dropped folder %q", folder) + files.DropFolder(db, folder) } } m := model.NewModel(confDir, &cfg, myName, "syncthing", Version, db) -nextRepo: - for i, repo := range cfg.Repositories { - if repo.Invalid != "" { +nextFolder: + for i, folder := range cfg.Folders { + if folder.Invalid != "" { continue } - repo.Directory = expandTilde(repo.Directory) - m.AddRepo(repo) + folder.Directory = expandTilde(folder.Directory) + m.AddFolder(folder) - fi, err := os.Stat(repo.Directory) - if m.CurrentLocalVersion(repo.ID) > 0 { + fi, err := os.Stat(folder.Directory) + if m.CurrentLocalVersion(folder.ID) > 0 { // Safety check. If the cached index contains files but the - // repository doesn't exist, we have a problem. We would assume + // folder doesn't exist, we have a problem. We would assume // that all files have been deleted which might not be the case, // so mark it as invalid instead. if err != nil || !fi.IsDir() { - l.Warnf("Stopping repository %q - directory missing, but has files in index", repo.ID) - cfg.Repositories[i].Invalid = "repo directory missing" - continue nextRepo + l.Warnf("Stopping folder %q - directory missing, but has files in index", folder.ID) + cfg.Folders[i].Invalid = "folder directory missing" + continue nextFolder } } else if os.IsNotExist(err) { // If we don't have any files in the index, and the directory // doesn't exist, try creating it. - err = os.MkdirAll(repo.Directory, 0700) + err = os.MkdirAll(folder.Directory, 0700) } if err != nil { // If there was another error or we could not create the - // directory, the repository is invalid. - l.Warnf("Stopping repository %q - %v", err) - cfg.Repositories[i].Invalid = err.Error() - continue nextRepo + // directory, the folder is invalid. + l.Warnf("Stopping folder %q - %v", err) + cfg.Folders[i].Invalid = err.Error() + continue nextFolder } } @@ -507,33 +507,33 @@ nextRepo: } } - // Clear out old indexes for other nodes. Otherwise we'll start up and + // Clear out old indexes for other devices. Otherwise we'll start up and // start needing a bunch of files which are nowhere to be found. This // needs to be changed when we correctly do persistent indexes. - for _, repoCfg := range cfg.Repositories { - if repoCfg.Invalid != "" { + for _, folderCfg := range cfg.Folders { + if folderCfg.Invalid != "" { continue } - for _, node := range repoCfg.NodeIDs() { - if node == myID { + for _, device := range folderCfg.DeviceIDs() { + if device == myID { continue } - m.Index(node, repoCfg.ID, nil) + m.Index(device, folderCfg.ID, nil) } } - // Walk the repository and update the local model before establishing any - // connections to other nodes. + // Walk the folder and update the local model before establishing any + // connections to other devices. - m.CleanRepos() - l.Infoln("Performing initial repository scan") - m.ScanRepos() + m.CleanFolders() + l.Infoln("Performing initial folder scan") + m.ScanFolders() - // Remove all .idx* files that don't belong to an active repo. + // Remove all .idx* files that don't belong to an active folder. validIndexes := make(map[string]bool) - for _, repo := range cfg.Repositories { - dir := expandTilde(repo.Directory) + for _, folder := range cfg.Folders { + dir := expandTilde(folder.Directory) id := fmt.Sprintf("%x", sha1.Sum([]byte(dir))) validIndexes[id] = true } @@ -566,23 +566,23 @@ nextRepo: setupUPnP() } - // Routine to connect out to configured nodes + // Routine to connect out to configured devices discoverer = discovery(externalPort) go listenConnect(myID, m, tlsCfg) - for _, repo := range cfg.Repositories { - if repo.Invalid != "" { + for _, folder := range cfg.Folders { + if folder.Invalid != "" { continue } - // Routine to pull blocks from other nodes to synchronize the local - // repository. Does not run when we are in read only (publish only) mode. - if repo.ReadOnly { - l.Okf("Ready to synchronize %s (read only; no external updates accepted)", repo.ID) - m.StartRepoRO(repo.ID) + // Routine to pull blocks from other devices to synchronize the local + // folder. Does not run when we are in read only (publish only) mode. + if folder.ReadOnly { + l.Okf("Ready to synchronize %s (read only; no external updates accepted)", folder.ID) + m.StartFolderRO(folder.ID) } else { - l.Okf("Ready to synchronize %s (read-write)", repo.ID) - m.StartRepoRW(repo.ID) + l.Okf("Ready to synchronize %s (read-write)", folder.ID) + m.StartFolderRW(folder.ID) } } @@ -595,9 +595,9 @@ nextRepo: defer pprof.StopCPUProfile() } - for _, node := range cfg.Nodes { - if len(node.Name) > 0 { - l.Infof("Node %s is %q at %v", node.NodeID, node.Name, node.Addresses) + for _, device := range cfg.Devices { + if len(device.Name) > 0 { + l.Infof("Device %s is %q at %v", device.DeviceID, device.Name, device.Addresses) } } @@ -668,7 +668,7 @@ func setupUPnP() { } func setupExternalPort(igd *upnp.IGD, port int) int { - // We seed the random number generator with the node ID to get a + // We seed the random number generator with the device ID to get a // repeatable sequence of random external ports. rnd := rand.NewSource(certSeed(cert.Certificate[0])) for i := 0; i < 10; i++ { @@ -714,12 +714,12 @@ func renewUPnP(port int) { } } -func resetRepositories() { +func resetFolders() { suffix := fmt.Sprintf(".syncthing-reset-%d", time.Now().UnixNano()) - for _, repo := range cfg.Repositories { - if _, err := os.Stat(repo.Directory); err == nil { - l.Infof("Reset: Moving %s -> %s", repo.Directory, repo.Directory+suffix) - os.Rename(repo.Directory, repo.Directory+suffix) + for _, folder := range cfg.Folders { + if _, err := os.Stat(folder.Directory); err == nil { + l.Infof("Reset: Moving %s -> %s", folder.Directory, folder.Directory+suffix) + os.Rename(folder.Directory, folder.Directory+suffix) } } @@ -773,7 +773,7 @@ func shutdown() { stop <- exitSuccess } -func listenConnect(myID protocol.NodeID, m *model.Model, tlsCfg *tls.Config) { +func listenConnect(myID protocol.DeviceID, m *model.Model, tlsCfg *tls.Config) { var conns = make(chan *tls.Conn) // Listen @@ -793,7 +793,7 @@ next: continue } remoteCert := certs[0] - remoteID := protocol.NewNodeID(remoteCert.Raw) + remoteID := protocol.NewDeviceID(remoteCert.Raw) if remoteID == myID { l.Infof("Connected to myself (%s) - should not happen", remoteID) @@ -802,17 +802,17 @@ next: } if m.ConnectedTo(remoteID) { - l.Infof("Connected to already connected node (%s)", remoteID) + l.Infof("Connected to already connected device (%s)", remoteID) conn.Close() continue } - for _, nodeCfg := range cfg.Nodes { - if nodeCfg.NodeID == remoteID { + for _, deviceCfg := range cfg.Devices { + if deviceCfg.DeviceID == remoteID { // Verify the name on the certificate. By default we set it to // "syncthing" when generating, but the user may have replaced // the certificate and used another name. - certName := nodeCfg.CertName + certName := deviceCfg.CertName if certName == "" { certName = "syncthing" } @@ -839,13 +839,13 @@ next: } name := fmt.Sprintf("%s-%s", conn.LocalAddr(), conn.RemoteAddr()) - protoConn := protocol.NewConnection(remoteID, rd, wr, m, name, nodeCfg.Compression) + protoConn := protocol.NewConnection(remoteID, rd, wr, m, name, deviceCfg.Compression) l.Infof("Established secure connection to %s at %s", remoteID, name) if debugNet { l.Debugf("cipher suite %04X", conn.ConnectionState().CipherSuite) } - events.Default.Log(events.NodeConnected, map[string]string{ + events.Default.Log(events.DeviceConnected, map[string]string{ "id": remoteID.String(), "addr": conn.RemoteAddr().String(), }) @@ -855,11 +855,11 @@ next: } } - events.Default.Log(events.NodeRejected, map[string]string{ - "node": remoteID.String(), + events.Default.Log(events.DeviceRejected, map[string]string{ + "device": remoteID.String(), "address": conn.RemoteAddr().String(), }) - l.Infof("Connection from %s with unknown node ID %s; ignoring", conn.RemoteAddr(), remoteID) + l.Infof("Connection from %s with unknown device ID %s; ignoring", conn.RemoteAddr(), remoteID) conn.Close() } } @@ -908,21 +908,21 @@ func listenTLS(conns chan *tls.Conn, addr string, tlsCfg *tls.Config) { func dialTLS(m *model.Model, conns chan *tls.Conn, tlsCfg *tls.Config) { var delay time.Duration = 1 * time.Second for { - nextNode: - for _, nodeCfg := range cfg.Nodes { - if nodeCfg.NodeID == myID { + nextDevice: + for _, deviceCfg := range cfg.Devices { + if deviceCfg.DeviceID == myID { continue } - if m.ConnectedTo(nodeCfg.NodeID) { + if m.ConnectedTo(deviceCfg.DeviceID) { continue } var addrs []string - for _, addr := range nodeCfg.Addresses { + for _, addr := range deviceCfg.Addresses { if addr == "dynamic" { if discoverer != nil { - t := discoverer.Lookup(nodeCfg.NodeID) + t := discoverer.Lookup(deviceCfg.DeviceID) if len(t) == 0 { continue } @@ -943,7 +943,7 @@ func dialTLS(m *model.Model, conns chan *tls.Conn, tlsCfg *tls.Config) { addr = net.JoinHostPort(host, "22000") } if debugNet { - l.Debugln("dial", nodeCfg.NodeID, addr) + l.Debugln("dial", deviceCfg.DeviceID, addr) } raddr, err := net.ResolveTCPAddr("tcp", addr) @@ -973,7 +973,7 @@ func dialTLS(m *model.Model, conns chan *tls.Conn, tlsCfg *tls.Config) { } conns <- tc - continue nextNode + continue nextDevice } } diff --git a/cmd/syncthing/usage_report.go b/cmd/syncthing/usage_report.go index ec6af7b44..1080fa559 100644 --- a/cmd/syncthing/usage_report.go +++ b/cmd/syncthing/usage_report.go @@ -31,13 +31,13 @@ func reportData(m *model.Model) map[string]interface{} { res["version"] = Version res["longVersion"] = LongVersion res["platform"] = runtime.GOOS + "-" + runtime.GOARCH - res["numRepos"] = len(cfg.Repositories) - res["numNodes"] = len(cfg.Nodes) + res["numFolders"] = len(cfg.Folders) + res["numDevices"] = len(cfg.Devices) var totFiles, maxFiles int var totBytes, maxBytes int64 - for _, repo := range cfg.Repositories { - files, _, bytes := m.GlobalSize(repo.ID) + for _, folder := range cfg.Folders { + files, _, bytes := m.GlobalSize(folder.ID) totFiles += files totBytes += bytes if files > maxFiles { @@ -49,9 +49,9 @@ func reportData(m *model.Model) map[string]interface{} { } res["totFiles"] = totFiles - res["repoMaxFiles"] = maxFiles + res["folderMaxFiles"] = maxFiles res["totMiB"] = totBytes / 1024 / 1024 - res["repoMaxMiB"] = maxBytes / 1024 / 1024 + res["folderMaxMiB"] = maxBytes / 1024 / 1024 var mem runtime.MemStats runtime.ReadMemStats(&mem) diff --git a/gui/app.js b/gui/app.js index 5ef4b1459..1325b009c 100644 --- a/gui/app.js +++ b/gui/app.js @@ -83,11 +83,11 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca $scope.errors = []; $scope.model = {}; $scope.myID = ''; - $scope.nodes = []; + $scope.devices = []; $scope.protocolChanged = false; $scope.reportData = {}; $scope.reportPreview = false; - $scope.repos = {}; + $scope.folders = {}; $scope.seenError = ''; $scope.upgradeInfo = {}; $scope.stats = {}; @@ -180,33 +180,33 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca $scope.$on('StateChanged', function (event, arg) { var data = arg.data; - if ($scope.model[data.repo]) { - $scope.model[data.repo].state = data.to; + if ($scope.model[data.folder]) { + $scope.model[data.folder].state = data.to; } }); $scope.$on('LocalIndexUpdated', function (event, arg) { var data = arg.data; - refreshRepo(data.repo); + refreshFolder(data.folder); - // Update completion status for all nodes that we share this repo with. - $scope.repos[data.repo].Nodes.forEach(function (nodeCfg) { - refreshCompletion(nodeCfg.NodeID, data.repo); + // Update completion status for all devices that we share this folder with. + $scope.folders[data.folder].Devices.forEach(function (deviceCfg) { + refreshCompletion(deviceCfg.DeviceID, data.folder); }); }); $scope.$on('RemoteIndexUpdated', function (event, arg) { var data = arg.data; - refreshRepo(data.repo); - refreshCompletion(data.node, data.repo); + refreshFolder(data.folder); + refreshCompletion(data.device, data.folder); }); - $scope.$on('NodeDisconnected', function (event, arg) { + $scope.$on('DeviceDisconnected', function (event, arg) { delete $scope.connections[arg.data.id]; - refreshNodeStats(); + refreshDeviceStats(); }); - $scope.$on('NodeConnected', function (event, arg) { + $scope.$on('DeviceConnected', function (event, arg) { if (!$scope.connections[arg.data.id]) { $scope.connections[arg.data.id] = { inbps: 0, @@ -251,13 +251,13 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca var debouncedFuncs = {}; - function refreshRepo(repo) { - var key = "refreshRepo" + repo; + function refreshFolder(folder) { + var key = "refreshFolder" + folder; if (!debouncedFuncs[key]) { debouncedFuncs[key] = debounce(function () { - $http.get(urlbase + '/model?repo=' + encodeURIComponent(repo)).success(function (data) { - $scope.model[repo] = data; - console.log("refreshRepo", repo, data); + $http.get(urlbase + '/model?folder=' + encodeURIComponent(folder)).success(function (data) { + $scope.model[folder] = data; + console.log("refreshFolder", folder, data); }); }, 1000, true); } @@ -270,19 +270,19 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca $scope.config = config; $scope.config.Options.ListenStr = $scope.config.Options.ListenAddress.join(', '); - $scope.nodes = $scope.config.Nodes; - $scope.nodes.forEach(function (nodeCfg) { - $scope.completion[nodeCfg.NodeID] = { + $scope.devices = $scope.config.Devices; + $scope.devices.forEach(function (deviceCfg) { + $scope.completion[deviceCfg.DeviceID] = { _total: 100, }; }); - $scope.nodes.sort(nodeCompare); + $scope.devices.sort(deviceCompare); - $scope.repos = repoMap($scope.config.Repositories); - Object.keys($scope.repos).forEach(function (repo) { - refreshRepo(repo); - $scope.repos[repo].Nodes.forEach(function (nodeCfg) { - refreshCompletion(nodeCfg.NodeID, repo); + $scope.folders = folderMap($scope.config.Folders); + Object.keys($scope.folders).forEach(function (folder) { + refreshFolder(folder); + $scope.folders[folder].Devices.forEach(function (deviceCfg) { + refreshCompletion(deviceCfg.DeviceID, folder); }); }); @@ -299,32 +299,32 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca }); } - function refreshCompletion(node, repo) { - if (node === $scope.myID) { + function refreshCompletion(device, folder) { + if (device === $scope.myID) { return; } - var key = "refreshCompletion" + node + repo; + var key = "refreshCompletion" + device + folder; if (!debouncedFuncs[key]) { debouncedFuncs[key] = debounce(function () { - $http.get(urlbase + '/completion?node=' + node + '&repo=' + encodeURIComponent(repo)).success(function (data) { - if (!$scope.completion[node]) { - $scope.completion[node] = {}; + $http.get(urlbase + '/completion?device=' + device + '&folder=' + encodeURIComponent(folder)).success(function (data) { + if (!$scope.completion[device]) { + $scope.completion[device] = {}; } - $scope.completion[node][repo] = data.completion; + $scope.completion[device][folder] = data.completion; var tot = 0, cnt = 0; - for (var cmp in $scope.completion[node]) { + for (var cmp in $scope.completion[device]) { if (cmp === "_total") { continue; } - tot += $scope.completion[node][cmp]; + tot += $scope.completion[device][cmp]; cnt += 1; } - $scope.completion[node]._total = tot / cnt; + $scope.completion[device]._total = tot / cnt; - console.log("refreshCompletion", node, repo, $scope.completion[node]); + console.log("refreshCompletion", device, folder, $scope.completion[device]); }); }, 1000, true); } @@ -373,14 +373,14 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca }); } - var refreshNodeStats = debounce(function () { - $http.get(urlbase + "/stats/node").success(function (data) { + var refreshDeviceStats = debounce(function () { + $http.get(urlbase + "/stats/device").success(function (data) { $scope.stats = data; - for (var node in $scope.stats) { - $scope.stats[node].LastSeen = new Date($scope.stats[node].LastSeen); - $scope.stats[node].LastSeenDays = (new Date() - $scope.stats[node].LastSeen) / 1000 / 86400; + for (var device in $scope.stats) { + $scope.stats[device].LastSeen = new Date($scope.stats[device].LastSeen); + $scope.stats[device].LastSeenDays = (new Date() - $scope.stats[device].LastSeen) / 1000 / 86400; } - console.log("refreshNodeStats", data); + console.log("refreshDeviceStats", data); }); }, 500); @@ -388,7 +388,7 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca refreshSystem(); refreshConfig(); refreshConnectionStats(); - refreshNodeStats(); + refreshDeviceStats(); $http.get(urlbase + '/version').success(function (data) { $scope.version = data.version; @@ -411,28 +411,28 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca refreshErrors(); }; - $scope.repoStatus = function (repo) { - if (typeof $scope.model[repo] === 'undefined') { + $scope.folderStatus = function (folder) { + if (typeof $scope.model[folder] === 'undefined') { return 'unknown'; } - if ($scope.model[repo].invalid !== '') { + if ($scope.model[folder].invalid !== '') { return 'stopped'; } - return '' + $scope.model[repo].state; + return '' + $scope.model[folder].state; }; - $scope.repoClass = function (repo) { - if (typeof $scope.model[repo] === 'undefined') { + $scope.folderClass = function (folder) { + if (typeof $scope.model[folder] === 'undefined') { return 'info'; } - if ($scope.model[repo].invalid !== '') { + if ($scope.model[folder].invalid !== '') { return 'danger'; } - var state = '' + $scope.model[repo].state; + var state = '' + $scope.model[folder].state; if (state == 'idle') { return 'success'; } @@ -445,21 +445,21 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca return 'info'; }; - $scope.syncPercentage = function (repo) { - if (typeof $scope.model[repo] === 'undefined') { + $scope.syncPercentage = function (folder) { + if (typeof $scope.model[folder] === 'undefined') { return 100; } - if ($scope.model[repo].globalBytes === 0) { + if ($scope.model[folder].globalBytes === 0) { return 100; } - var pct = 100 * $scope.model[repo].inSyncBytes / $scope.model[repo].globalBytes; + var pct = 100 * $scope.model[folder].inSyncBytes / $scope.model[folder].globalBytes; return Math.floor(pct); }; - $scope.nodeIcon = function (nodeCfg) { - if ($scope.connections[nodeCfg.NodeID]) { - if ($scope.completion[nodeCfg.NodeID] && $scope.completion[nodeCfg.NodeID]._total === 100) { + $scope.deviceIcon = function (deviceCfg) { + if ($scope.connections[deviceCfg.DeviceID]) { + if ($scope.completion[deviceCfg.DeviceID] && $scope.completion[deviceCfg.DeviceID]._total === 100) { return 'ok'; } else { return 'refresh'; @@ -469,9 +469,9 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca return 'minus'; }; - $scope.nodeClass = function (nodeCfg) { - if ($scope.connections[nodeCfg.NodeID]) { - if ($scope.completion[nodeCfg.NodeID] && $scope.completion[nodeCfg.NodeID]._total === 100) { + $scope.deviceClass = function (deviceCfg) { + if ($scope.connections[deviceCfg.DeviceID]) { + if ($scope.completion[deviceCfg.DeviceID] && $scope.completion[deviceCfg.DeviceID]._total === 100) { return 'success'; } else { return 'primary'; @@ -481,25 +481,25 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca return 'info'; }; - $scope.nodeAddr = function (nodeCfg) { - var conn = $scope.connections[nodeCfg.NodeID]; + $scope.deviceAddr = function (deviceCfg) { + var conn = $scope.connections[deviceCfg.DeviceID]; if (conn) { return conn.Address; } return '?'; }; - $scope.nodeCompletion = function (nodeCfg) { - var conn = $scope.connections[nodeCfg.NodeID]; + $scope.deviceCompletion = function (deviceCfg) { + var conn = $scope.connections[deviceCfg.DeviceID]; if (conn) { return conn.Completion + '%'; } return ''; }; - $scope.findNode = function (nodeID) { - var matches = $scope.nodes.filter(function (n) { - return n.NodeID == nodeID; + $scope.findDevice = function (deviceID) { + var matches = $scope.devices.filter(function (n) { + return n.DeviceID == deviceID; }); if (matches.length != 1) { return undefined; @@ -507,32 +507,32 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca return matches[0]; }; - $scope.nodeName = function (nodeCfg) { - if (typeof nodeCfg === 'undefined') { + $scope.deviceName = function (deviceCfg) { + if (typeof deviceCfg === 'undefined') { return ""; } - if (nodeCfg.Name) { - return nodeCfg.Name; + if (deviceCfg.Name) { + return deviceCfg.Name; } - return nodeCfg.NodeID.substr(0, 6); + return deviceCfg.DeviceID.substr(0, 6); }; - $scope.thisNodeName = function () { - var node = $scope.thisNode(); - if (typeof node === 'undefined') { - return "(unknown node)"; + $scope.thisDeviceName = function () { + var device = $scope.thisDevice(); + if (typeof device === 'undefined') { + return "(unknown device)"; } - if (node.Name) { - return node.Name; + if (device.Name) { + return device.Name; } - return node.NodeID.substr(0, 6); + return device.DeviceID.substr(0, 6); }; $scope.editSettings = function () { // Make a working copy $scope.tmpOptions = angular.copy($scope.config.Options); $scope.tmpOptions.UREnabled = ($scope.tmpOptions.URAccepted > 0); - $scope.tmpOptions.NodeName = $scope.thisNode().Name; + $scope.tmpOptions.DeviceName = $scope.thisDevice().Name; $scope.tmpGUI = angular.copy($scope.config.GUI); $('#settings').modal(); }; @@ -569,7 +569,7 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca } // Apply new settings locally - $scope.thisNode().Name = $scope.tmpOptions.NodeName; + $scope.thisDevice().Name = $scope.tmpOptions.DeviceName; $scope.config.Options = angular.copy($scope.tmpOptions); $scope.config.GUI = angular.copy($scope.tmpGUI); $scope.config.Options.ListenAddress = $scope.config.Options.ListenStr.split(',').map(function (x) { @@ -623,100 +623,100 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca $scope.configInSync = true; }; - $scope.editNode = function (nodeCfg) { - $scope.currentNode = $.extend({}, nodeCfg); + $scope.editDevice = function (deviceCfg) { + $scope.currentDevice = $.extend({}, deviceCfg); $scope.editingExisting = true; - $scope.editingSelf = (nodeCfg.NodeID == $scope.myID); - $scope.currentNode.AddressesStr = nodeCfg.Addresses.join(', '); - $scope.nodeEditor.$setPristine(); - $('#editNode').modal(); + $scope.editingSelf = (deviceCfg.DeviceID == $scope.myID); + $scope.currentDevice.AddressesStr = deviceCfg.Addresses.join(', '); + $scope.deviceEditor.$setPristine(); + $('#editDevice').modal(); }; - $scope.idNode = function () { + $scope.idDevice = function () { $('#idqr').modal('show'); }; - $scope.addNode = function () { - $scope.currentNode = { + $scope.addDevice = function () { + $scope.currentDevice = { AddressesStr: 'dynamic', Compression: true, Introducer: true }; $scope.editingExisting = false; $scope.editingSelf = false; - $scope.nodeEditor.$setPristine(); - $('#editNode').modal(); + $scope.deviceEditor.$setPristine(); + $('#editDevice').modal(); }; - $scope.deleteNode = function () { - $('#editNode').modal('hide'); + $scope.deleteDevice = function () { + $('#editDevice').modal('hide'); if (!$scope.editingExisting) { return; } - $scope.nodes = $scope.nodes.filter(function (n) { - return n.NodeID !== $scope.currentNode.NodeID; + $scope.devices = $scope.devices.filter(function (n) { + return n.DeviceID !== $scope.currentDevice.DeviceID; }); - $scope.config.Nodes = $scope.nodes; + $scope.config.Devices = $scope.devices; - for (var id in $scope.repos) { - $scope.repos[id].Nodes = $scope.repos[id].Nodes.filter(function (n) { - return n.NodeID !== $scope.currentNode.NodeID; + for (var id in $scope.folders) { + $scope.folders[id].Devices = $scope.folders[id].Devices.filter(function (n) { + return n.DeviceID !== $scope.currentDevice.DeviceID; }); } $scope.saveConfig(); }; - $scope.saveNode = function () { - var nodeCfg, done, i; + $scope.saveDevice = function () { + var deviceCfg, done, i; - $('#editNode').modal('hide'); - nodeCfg = $scope.currentNode; - nodeCfg.Addresses = nodeCfg.AddressesStr.split(',').map(function (x) { + $('#editDevice').modal('hide'); + deviceCfg = $scope.currentDevice; + deviceCfg.Addresses = deviceCfg.AddressesStr.split(',').map(function (x) { return x.trim(); }); done = false; - for (i = 0; i < $scope.nodes.length; i++) { - if ($scope.nodes[i].NodeID === nodeCfg.NodeID) { - $scope.nodes[i] = nodeCfg; + for (i = 0; i < $scope.devices.length; i++) { + if ($scope.devices[i].DeviceID === deviceCfg.DeviceID) { + $scope.devices[i] = deviceCfg; done = true; break; } } if (!done) { - $scope.nodes.push(nodeCfg); + $scope.devices.push(deviceCfg); } - $scope.nodes.sort(nodeCompare); - $scope.config.Nodes = $scope.nodes; + $scope.devices.sort(deviceCompare); + $scope.config.Devices = $scope.devices; $scope.saveConfig(); }; - $scope.otherNodes = function () { - return $scope.nodes.filter(function (n) { - return n.NodeID !== $scope.myID; + $scope.otherDevices = function () { + return $scope.devices.filter(function (n) { + return n.DeviceID !== $scope.myID; }); }; - $scope.thisNode = function () { + $scope.thisDevice = function () { var i, n; - for (i = 0; i < $scope.nodes.length; i++) { - n = $scope.nodes[i]; - if (n.NodeID === $scope.myID) { + for (i = 0; i < $scope.devices.length; i++) { + n = $scope.devices[i]; + if (n.DeviceID === $scope.myID) { return n; } } }; - $scope.allNodes = function () { - var nodes = $scope.otherNodes(); - nodes.push($scope.thisNode()); - return nodes; + $scope.allDevices = function () { + var devices = $scope.otherDevices(); + devices.push($scope.thisDevice()); + return devices; }; $scope.errorList = function () { @@ -730,134 +730,134 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca $http.post(urlbase + '/error/clear'); }; - $scope.friendlyNodes = function (str) { - for (var i = 0; i < $scope.nodes.length; i++) { - var cfg = $scope.nodes[i]; - str = str.replace(cfg.NodeID, $scope.nodeName(cfg)); + $scope.friendlyDevices = function (str) { + for (var i = 0; i < $scope.devices.length; i++) { + var cfg = $scope.devices[i]; + str = str.replace(cfg.DeviceID, $scope.deviceName(cfg)); } return str; }; - $scope.repoList = function () { - return repoList($scope.repos); + $scope.folderList = function () { + return folderList($scope.folders); }; - $scope.editRepo = function (nodeCfg) { - $scope.currentRepo = angular.copy(nodeCfg); - $scope.currentRepo.selectedNodes = {}; - $scope.currentRepo.Nodes.forEach(function (n) { - $scope.currentRepo.selectedNodes[n.NodeID] = true; + $scope.editFolder = function (deviceCfg) { + $scope.currentFolder = angular.copy(deviceCfg); + $scope.currentFolder.selectedDevices = {}; + $scope.currentFolder.Devices.forEach(function (n) { + $scope.currentFolder.selectedDevices[n.DeviceID] = true; }); - if ($scope.currentRepo.Versioning && $scope.currentRepo.Versioning.Type === "simple") { - $scope.currentRepo.simpleFileVersioning = true; - $scope.currentRepo.FileVersioningSelector = "simple"; - $scope.currentRepo.simpleKeep = +$scope.currentRepo.Versioning.Params.keep; - } else if ($scope.currentRepo.Versioning && $scope.currentRepo.Versioning.Type === "staggered") { - $scope.currentRepo.staggeredFileVersioning = true; - $scope.currentRepo.FileVersioningSelector = "staggered"; - $scope.currentRepo.staggeredMaxAge = Math.floor(+$scope.currentRepo.Versioning.Params.maxAge / 86400); - $scope.currentRepo.staggeredCleanInterval = +$scope.currentRepo.Versioning.Params.cleanInterval; - $scope.currentRepo.staggeredVersionsPath = $scope.currentRepo.Versioning.Params.versionsPath; + if ($scope.currentFolder.Versioning && $scope.currentFolder.Versioning.Type === "simple") { + $scope.currentFolder.simpleFileVersioning = true; + $scope.currentFolder.FileVersioningSelector = "simple"; + $scope.currentFolder.simpleKeep = +$scope.currentFolder.Versioning.Params.keep; + } else if ($scope.currentFolder.Versioning && $scope.currentFolder.Versioning.Type === "staggered") { + $scope.currentFolder.staggeredFileVersioning = true; + $scope.currentFolder.FileVersioningSelector = "staggered"; + $scope.currentFolder.staggeredMaxAge = Math.floor(+$scope.currentFolder.Versioning.Params.maxAge / 86400); + $scope.currentFolder.staggeredCleanInterval = +$scope.currentFolder.Versioning.Params.cleanInterval; + $scope.currentFolder.staggeredVersionsPath = $scope.currentFolder.Versioning.Params.versionsPath; } else { - $scope.currentRepo.FileVersioningSelector = "none"; + $scope.currentFolder.FileVersioningSelector = "none"; } - $scope.currentRepo.simpleKeep = $scope.currentRepo.simpleKeep || 5; - $scope.currentRepo.staggeredCleanInterval = $scope.currentRepo.staggeredCleanInterval || 3600; - $scope.currentRepo.staggeredVersionsPath = $scope.currentRepo.staggeredVersionsPath || ""; + $scope.currentFolder.simpleKeep = $scope.currentFolder.simpleKeep || 5; + $scope.currentFolder.staggeredCleanInterval = $scope.currentFolder.staggeredCleanInterval || 3600; + $scope.currentFolder.staggeredVersionsPath = $scope.currentFolder.staggeredVersionsPath || ""; // staggeredMaxAge can validly be zero, which we should not replace // with the default value of 365. So only set the default if it's // actually undefined. - if (typeof $scope.currentRepo.staggeredMaxAge === 'undefined') { - $scope.currentRepo.staggeredMaxAge = 365; + if (typeof $scope.currentFolder.staggeredMaxAge === 'undefined') { + $scope.currentFolder.staggeredMaxAge = 365; } $scope.editingExisting = true; - $scope.repoEditor.$setPristine(); - $('#editRepo').modal(); + $scope.folderEditor.$setPristine(); + $('#editFolder').modal(); }; - $scope.addRepo = function () { - $scope.currentRepo = { - selectedNodes: {} + $scope.addFolder = function () { + $scope.currentFolder = { + selectedDevices: {} }; - $scope.currentRepo.RescanIntervalS = 60; - $scope.currentRepo.FileVersioningSelector = "none"; - $scope.currentRepo.simpleKeep = 5; - $scope.currentRepo.staggeredMaxAge = 365; - $scope.currentRepo.staggeredCleanInterval = 3600; - $scope.currentRepo.staggeredVersionsPath = ""; + $scope.currentFolder.RescanIntervalS = 60; + $scope.currentFolder.FileVersioningSelector = "none"; + $scope.currentFolder.simpleKeep = 5; + $scope.currentFolder.staggeredMaxAge = 365; + $scope.currentFolder.staggeredCleanInterval = 3600; + $scope.currentFolder.staggeredVersionsPath = ""; $scope.editingExisting = false; - $scope.repoEditor.$setPristine(); - $('#editRepo').modal(); + $scope.folderEditor.$setPristine(); + $('#editFolder').modal(); }; - $scope.saveRepo = function () { - var repoCfg, done, i; + $scope.saveFolder = function () { + var folderCfg, done, i; - $('#editRepo').modal('hide'); - repoCfg = $scope.currentRepo; - repoCfg.Nodes = []; - repoCfg.selectedNodes[$scope.myID] = true; - for (var nodeID in repoCfg.selectedNodes) { - if (repoCfg.selectedNodes[nodeID] === true) { - repoCfg.Nodes.push({ - NodeID: nodeID + $('#editFolder').modal('hide'); + folderCfg = $scope.currentFolder; + folderCfg.Devices = []; + folderCfg.selectedDevices[$scope.myID] = true; + for (var deviceID in folderCfg.selectedDevices) { + if (folderCfg.selectedDevices[deviceID] === true) { + folderCfg.Devices.push({ + DeviceID: deviceID }); } } - delete repoCfg.selectedNodes; + delete folderCfg.selectedDevices; - if (repoCfg.FileVersioningSelector === "simple") { - repoCfg.Versioning = { + if (folderCfg.FileVersioningSelector === "simple") { + folderCfg.Versioning = { 'Type': 'simple', 'Params': { - 'keep': '' + repoCfg.simpleKeep, + 'keep': '' + folderCfg.simpleKeep, } }; - delete repoCfg.simpleFileVersioning; - delete repoCfg.simpleKeep; - } else if (repoCfg.FileVersioningSelector === "staggered") { - repoCfg.Versioning = { + delete folderCfg.simpleFileVersioning; + delete folderCfg.simpleKeep; + } else if (folderCfg.FileVersioningSelector === "staggered") { + folderCfg.Versioning = { 'Type': 'staggered', 'Params': { - 'maxAge': '' + (repoCfg.staggeredMaxAge * 86400), - 'cleanInterval': '' + repoCfg.staggeredCleanInterval, - 'versionsPath': '' + repoCfg.staggeredVersionsPath, + 'maxAge': '' + (folderCfg.staggeredMaxAge * 86400), + 'cleanInterval': '' + folderCfg.staggeredCleanInterval, + 'versionsPath': '' + folderCfg.staggeredVersionsPath, } }; - delete repoCfg.staggeredFileVersioning; - delete repoCfg.staggeredMaxAge; - delete repoCfg.staggeredCleanInterval; - delete repoCfg.staggeredVersionsPath; + delete folderCfg.staggeredFileVersioning; + delete folderCfg.staggeredMaxAge; + delete folderCfg.staggeredCleanInterval; + delete folderCfg.staggeredVersionsPath; } else { - delete repoCfg.Versioning; + delete folderCfg.Versioning; } - $scope.repos[repoCfg.ID] = repoCfg; - $scope.config.Repositories = repoList($scope.repos); + $scope.folders[folderCfg.ID] = folderCfg; + $scope.config.Folders = folderList($scope.folders); $scope.saveConfig(); }; - $scope.sharesRepo = function (repoCfg) { + $scope.sharesFolder = function (folderCfg) { var names = []; - repoCfg.Nodes.forEach(function (node) { - names.push($scope.nodeName($scope.findNode(node.NodeID))); + folderCfg.Devices.forEach(function (device) { + names.push($scope.deviceName($scope.findDevice(device.DeviceID))); }); names.sort(); return names.join(", "); }; - $scope.deleteRepo = function () { - $('#editRepo').modal('hide'); + $scope.deleteFolder = function () { + $('#editFolder').modal('hide'); if (!$scope.editingExisting) { return; } - delete $scope.repos[$scope.currentRepo.ID]; - $scope.config.Repositories = repoList($scope.repos); + delete $scope.folders[$scope.currentFolder.ID]; + $scope.config.Folders = folderList($scope.folders); $scope.saveConfig(); }; @@ -868,18 +868,18 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca } $('#editIgnoresButton').attr('disabled', 'disabled'); - $http.get(urlbase + '/ignores?repo=' + encodeURIComponent($scope.currentRepo.ID)) + $http.get(urlbase + '/ignores?folder=' + encodeURIComponent($scope.currentFolder.ID)) .success(function (data) { data.ignore = data.ignore || []; - $('#editRepo').modal('hide'); + $('#editFolder').modal('hide'); var textArea = $('#editIgnores textarea'); textArea.val(data.ignore.join('\n')); $('#editIgnores').modal() .on('hidden.bs.modal', function () { - $('#editRepo').modal(); + $('#editFolder').modal(); }) .on('shown.bs.modal', function () { textArea.focus(); @@ -895,7 +895,7 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca return; } - $http.post(urlbase + '/ignores?repo=' + encodeURIComponent($scope.currentRepo.ID), { + $http.post(urlbase + '/ignores?folder=' + encodeURIComponent($scope.currentFolder.ID), { ignore: $('#editIgnores textarea').val().split('\n') }); }; @@ -923,10 +923,10 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca $('#ur').modal('hide'); }; - $scope.showNeed = function (repo) { + $scope.showNeed = function (folder) { $scope.neededLoaded = false; $('#needed').modal(); - $http.get(urlbase + "/need?repo=" + encodeURIComponent(repo)).success(function (data) { + $http.get(urlbase + "/need?folder=" + encodeURIComponent(folder)).success(function (data) { $scope.needed = data; $scope.neededLoaded = true; }); @@ -947,8 +947,8 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca } }; - $scope.override = function (repo) { - $http.post(urlbase + "/model/override?repo=" + encodeURIComponent(repo)); + $scope.override = function (folder) { + $http.post(urlbase + "/model/override?folder=" + encodeURIComponent(folder)); }; $scope.about = function () { @@ -959,34 +959,34 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca $scope.reportPreview = true; }; - $scope.rescanRepo = function (repo) { - $http.post(urlbase + "/scan?repo=" + encodeURIComponent(repo)); + $scope.rescanFolder = function (folder) { + $http.post(urlbase + "/scan?folder=" + encodeURIComponent(folder)); }; $scope.init(); setInterval($scope.refresh, 10000); }); -function nodeCompare(a, b) { +function deviceCompare(a, b) { if (typeof a.Name !== 'undefined' && typeof b.Name !== 'undefined') { if (a.Name < b.Name) return -1; return a.Name > b.Name; } - if (a.NodeID < b.NodeID) { + if (a.DeviceID < b.DeviceID) { return -1; } - return a.NodeID > b.NodeID; + return a.DeviceID > b.DeviceID; } -function repoCompare(a, b) { +function folderCompare(a, b) { if (a.ID < b.ID) { return -1; } return a.ID > b.ID; } -function repoMap(l) { +function folderMap(l) { var m = {}; l.forEach(function (r) { m[r.ID] = r; @@ -994,12 +994,12 @@ function repoMap(l) { return m; } -function repoList(m) { +function folderList(m) { var l = []; for (var id in m) { l.push(m[id]); } - l.sort(repoCompare); + l.sort(folderCompare); return l; } @@ -1137,20 +1137,20 @@ syncthing.filter('basename', function () { }; }); -syncthing.directive('uniqueRepo', function () { +syncthing.directive('uniqueFolder', function () { return { require: 'ngModel', link: function (scope, elm, attrs, ctrl) { ctrl.$parsers.unshift(function (viewValue) { if (scope.editingExisting) { // we shouldn't validate - ctrl.$setValidity('uniqueRepo', true); - } else if (scope.repos[viewValue]) { - // the repo exists already - ctrl.$setValidity('uniqueRepo', false); + ctrl.$setValidity('uniqueFolder', true); + } else if (scope.folders[viewValue]) { + // the folder exists already + ctrl.$setValidity('uniqueFolder', false); } else { - // the repo is unique - ctrl.$setValidity('uniqueRepo', true); + // the folder is unique + ctrl.$setValidity('uniqueFolder', true); } return viewValue; }); @@ -1158,20 +1158,20 @@ syncthing.directive('uniqueRepo', function () { }; }); -syncthing.directive('validNodeid', function ($http) { +syncthing.directive('validDeviceid', function ($http) { return { require: 'ngModel', link: function (scope, elm, attrs, ctrl) { ctrl.$parsers.unshift(function (viewValue) { if (scope.editingExisting) { // we shouldn't validate - ctrl.$setValidity('validNodeid', true); + ctrl.$setValidity('validDeviceid', true); } else { - $http.get(urlbase + '/nodeid?id=' + viewValue).success(function (resp) { + $http.get(urlbase + '/deviceid?id=' + viewValue).success(function (resp) { if (resp.error) { - ctrl.$setValidity('validNodeid', false); + ctrl.$setValidity('validDeviceid', false); } else { - ctrl.$setValidity('validNodeid', true); + ctrl.$setValidity('validDeviceid', true); } }); } diff --git a/gui/index.html b/gui/index.html index 1b913afbf..7c0cdde1d 100644 --- a/gui/index.html +++ b/gui/index.html @@ -13,7 +13,7 @@ -