mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-23 03:18:59 +00:00
Merge remote-tracking branch 'origin/pr/721'
* origin/pr/721: Add tests for model.GetIgnores model.SetIgnores Expose ignores in the UI Add comments directive to ignores Expose ignores rest endpoints Expose ignores from model
This commit is contained in:
commit
737a28050c
File diff suppressed because one or more lines are too long
@ -84,6 +84,7 @@ func startGUI(cfg config.GUIConfiguration, assetDir string, m *model.Model) erro
|
|||||||
getRestMux.HandleFunc("/rest/discovery", restGetDiscovery)
|
getRestMux.HandleFunc("/rest/discovery", restGetDiscovery)
|
||||||
getRestMux.HandleFunc("/rest/errors", restGetErrors)
|
getRestMux.HandleFunc("/rest/errors", restGetErrors)
|
||||||
getRestMux.HandleFunc("/rest/events", restGetEvents)
|
getRestMux.HandleFunc("/rest/events", restGetEvents)
|
||||||
|
getRestMux.HandleFunc("/rest/ignores", withModel(m, restGetIgnores))
|
||||||
getRestMux.HandleFunc("/rest/lang", restGetLang)
|
getRestMux.HandleFunc("/rest/lang", restGetLang)
|
||||||
getRestMux.HandleFunc("/rest/model", withModel(m, restGetModel))
|
getRestMux.HandleFunc("/rest/model", withModel(m, restGetModel))
|
||||||
getRestMux.HandleFunc("/rest/model/version", withModel(m, restGetModelVersion))
|
getRestMux.HandleFunc("/rest/model/version", withModel(m, restGetModelVersion))
|
||||||
@ -105,6 +106,7 @@ func startGUI(cfg config.GUIConfiguration, assetDir string, m *model.Model) erro
|
|||||||
postRestMux.HandleFunc("/rest/discovery/hint", restPostDiscoveryHint)
|
postRestMux.HandleFunc("/rest/discovery/hint", restPostDiscoveryHint)
|
||||||
postRestMux.HandleFunc("/rest/error", restPostError)
|
postRestMux.HandleFunc("/rest/error", restPostError)
|
||||||
postRestMux.HandleFunc("/rest/error/clear", restClearErrors)
|
postRestMux.HandleFunc("/rest/error/clear", restClearErrors)
|
||||||
|
postRestMux.HandleFunc("/rest/ignores", withModel(m, restPostIgnores))
|
||||||
postRestMux.HandleFunc("/rest/model/override", withModel(m, restPostOverride))
|
postRestMux.HandleFunc("/rest/model/override", withModel(m, restPostOverride))
|
||||||
postRestMux.HandleFunc("/rest/reset", restPostReset)
|
postRestMux.HandleFunc("/rest/reset", restPostReset)
|
||||||
postRestMux.HandleFunc("/rest/restart", restPostRestart)
|
postRestMux.HandleFunc("/rest/restart", restPostRestart)
|
||||||
@ -457,6 +459,41 @@ func restGetReport(m *model.Model, w http.ResponseWriter, r *http.Request) {
|
|||||||
json.NewEncoder(w).Encode(reportData(m))
|
json.NewEncoder(w).Encode(reportData(m))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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"))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
json.NewEncoder(w).Encode(map[string][]string{
|
||||||
|
"ignore": ignores,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func restPostIgnores(m *model.Model, w http.ResponseWriter, r *http.Request) {
|
||||||
|
qs := r.URL.Query()
|
||||||
|
|
||||||
|
var data map[string][]string
|
||||||
|
err := json.NewDecoder(r.Body).Decode(&data)
|
||||||
|
r.Body.Close()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = m.SetIgnores(qs.Get("repo"), data["ignore"])
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
restGetIgnores(m, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
func restGetEvents(w http.ResponseWriter, r *http.Request) {
|
func restGetEvents(w http.ResponseWriter, r *http.Request) {
|
||||||
qs := r.URL.Query()
|
qs := r.URL.Query()
|
||||||
sinceStr := qs.Get("since")
|
sinceStr := qs.Get("since")
|
||||||
|
36
gui/app.js
36
gui/app.js
@ -888,6 +888,42 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http, $translate, $loca
|
|||||||
$scope.saveConfig();
|
$scope.saveConfig();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.editIgnores = function () {
|
||||||
|
if (!$scope.editingExisting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#editIgnoresButton').attr('disabled', 'disabled');
|
||||||
|
$http.get(urlbase + '/ignores?repo=' + encodeURIComponent($scope.currentRepo.ID))
|
||||||
|
.success(function (data) {
|
||||||
|
$('#editRepo').modal('hide');
|
||||||
|
var textArea = $('#editIgnores textarea');
|
||||||
|
|
||||||
|
textArea.val(data.ignore.join('\n'));
|
||||||
|
|
||||||
|
$('#editIgnores').modal()
|
||||||
|
.on('hidden.bs.modal', function () {
|
||||||
|
$('#editRepo').modal();
|
||||||
|
})
|
||||||
|
.on('shown.bs.modal', function () {
|
||||||
|
textArea.focus();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
$('#editIgnoresButton').removeAttr('disabled');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.saveIgnores = function () {
|
||||||
|
if (!$scope.editingExisting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$http.post(urlbase + '/ignores?repo=' + encodeURIComponent($scope.currentRepo.ID), {
|
||||||
|
ignore: $('#editIgnores textarea').val().split('\n')
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
$scope.setAPIKey = function (cfg) {
|
$scope.setAPIKey = function (cfg) {
|
||||||
cfg.APIKey = randomString(30, 32);
|
cfg.APIKey = randomString(30, 32);
|
||||||
};
|
};
|
||||||
|
@ -522,6 +522,35 @@
|
|||||||
<button type="button" class="btn btn-primary btn-sm" ng-click="saveRepo()" ng-disabled="repoEditor.$invalid"><span class="glyphicon glyphicon-ok"></span> <span translate>Save</span></button>
|
<button type="button" class="btn btn-primary btn-sm" ng-click="saveRepo()" ng-disabled="repoEditor.$invalid"><span class="glyphicon glyphicon-ok"></span> <span translate>Save</span></button>
|
||||||
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal"><span class="glyphicon glyphicon-remove"></span> <span translate>Close</span></button>
|
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal"><span class="glyphicon glyphicon-remove"></span> <span translate>Close</span></button>
|
||||||
<button ng-if="editingExisting" type="button" class="btn btn-danger pull-left btn-sm" ng-click="deleteRepo()"><span class="glyphicon glyphicon-minus"></span> <span translate>Delete</span></button>
|
<button ng-if="editingExisting" type="button" class="btn btn-danger pull-left btn-sm" ng-click="deleteRepo()"><span class="glyphicon glyphicon-minus"></span> <span translate>Delete</span></button>
|
||||||
|
<button id="editIgnoresButton" ng-if="editingExisting" type="button" class="btn btn-default pull-left btn-sm" ng-click="editIgnores()"><span class="glyphicon glyphicon-pencil"></span> <span translate>Edit ignored files and directories</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Ignores editor modal -->
|
||||||
|
|
||||||
|
<div id="editIgnores" class="modal fade" tabindex="-1">
|
||||||
|
<div class="modal-dialog modal-lg">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 translate class="modal-title">Ignored files and directories</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p translate>Supported patterns:</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>*</code> - <span translate>Single-level wildcard (matches anything within a single directory)</span>
|
||||||
|
<li><code>**</code> - <span translate>Multi-level wildcard (matches anything within all directories at any depth)</span>
|
||||||
|
<li><code>!</code> - <span translate>Inversion of the given condition, which excludes the given pattern from any previous matches</span>
|
||||||
|
<li><code>#include</code> - <span translate>Including ignores from another file</span>
|
||||||
|
<li><code>//</code> - <span translate>Comment</span>
|
||||||
|
</ul>
|
||||||
|
<textarea class="form-control" rows="15"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<div class="pull-left"><span translate >Ignore file location</span>:<code>{{ currentRepo.Directory }}/.stignore</code></div>
|
||||||
|
<button type="button" class="btn btn-primary btn-sm" data-dismiss="modal" ng-click="saveIgnores()"><span class="glyphicon glyphicon-ok"></span> <span translate>Save</span></button>
|
||||||
|
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal"><span class="glyphicon glyphicon-remove"></span> <span translate>Close</span></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
"Bugs": "Bugs",
|
"Bugs": "Bugs",
|
||||||
"CPU Utilization": "CPU Utilization",
|
"CPU Utilization": "CPU Utilization",
|
||||||
"Close": "Close",
|
"Close": "Close",
|
||||||
|
"Comment": "Comment",
|
||||||
"Connection Error": "Connection Error",
|
"Connection Error": "Connection Error",
|
||||||
"Copyright © 2014 Jakob Borg and the following Contributors:": "Copyright © 2014 Jakob Borg and the following Contributors:",
|
"Copyright © 2014 Jakob Borg and the following Contributors:": "Copyright © 2014 Jakob Borg and the following Contributors:",
|
||||||
"Delete": "Delete",
|
"Delete": "Delete",
|
||||||
@ -20,6 +21,7 @@
|
|||||||
"Edit": "Edit",
|
"Edit": "Edit",
|
||||||
"Edit Node": "Edit Node",
|
"Edit Node": "Edit Node",
|
||||||
"Edit Repository": "Edit Repository",
|
"Edit Repository": "Edit Repository",
|
||||||
|
"Edit ignored files and directories": "Edit ignored files and directories",
|
||||||
"Enable UPnP": "Enable UPnP",
|
"Enable UPnP": "Enable UPnP",
|
||||||
"Enter comma separated \"ip:port\" addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated \"ip:port\" addresses or \"dynamic\" to perform automatic discovery of the address.",
|
"Enter comma separated \"ip:port\" addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated \"ip:port\" addresses or \"dynamic\" to perform automatic discovery of the address.",
|
||||||
"Error": "Error",
|
"Error": "Error",
|
||||||
@ -37,7 +39,11 @@
|
|||||||
"Global Repository": "Global Repository",
|
"Global Repository": "Global Repository",
|
||||||
"Idle": "Idle",
|
"Idle": "Idle",
|
||||||
"Ignore Permissions": "Ignore Permissions",
|
"Ignore Permissions": "Ignore Permissions",
|
||||||
|
"Ignore file location": "Ignore file location",
|
||||||
|
"Ignored files and directories": "Ignored files and directories",
|
||||||
|
"Including ignores from another file": "Including ignores from another file",
|
||||||
"Incoming Rate Limit (KiB/s)": "Incoming Rate Limit (KiB/s)",
|
"Incoming Rate Limit (KiB/s)": "Incoming Rate Limit (KiB/s)",
|
||||||
|
"Inversion of the given condition, which excludes the given pattern from any previous matches": "Inversion of the given condition, which excludes the given pattern from any previous matches",
|
||||||
"Keep Versions": "Keep Versions",
|
"Keep Versions": "Keep Versions",
|
||||||
"Last seen": "Last seen",
|
"Last seen": "Last seen",
|
||||||
"Latest Release": "Latest Release",
|
"Latest Release": "Latest Release",
|
||||||
@ -48,6 +54,7 @@
|
|||||||
"Max File Change Rate (KiB/s)": "Max File Change Rate (KiB/s)",
|
"Max File Change Rate (KiB/s)": "Max File Change Rate (KiB/s)",
|
||||||
"Max Outstanding Requests": "Max Outstanding Requests",
|
"Max Outstanding Requests": "Max Outstanding Requests",
|
||||||
"Maximum Age": "Maximum Age",
|
"Maximum Age": "Maximum Age",
|
||||||
|
"Multi-level wildcard (matches anything within all directories at any depth)": "Multi-level wildcard (matches anything within all directories at any depth)",
|
||||||
"Never": "Never",
|
"Never": "Never",
|
||||||
"No": "No",
|
"No": "No",
|
||||||
"No File Versioning": "No File Versioning",
|
"No File Versioning": "No File Versioning",
|
||||||
@ -90,11 +97,13 @@
|
|||||||
"Shown instead of Node ID in the cluster status. Will be updated to the name the node advertises if left empty.": "Shown instead of Node ID in the cluster status. Will be updated to the name the node advertises if left empty.",
|
"Shown instead of Node ID in the cluster status. Will be updated to the name the node advertises if left empty.": "Shown instead of Node ID in the cluster status. Will be updated to the name the node advertises if left empty.",
|
||||||
"Shutdown": "Shutdown",
|
"Shutdown": "Shutdown",
|
||||||
"Simple File Versioning": "Simple File Versioning",
|
"Simple File Versioning": "Simple File Versioning",
|
||||||
|
"Single-level wildcard (matches anything within a single directory)": "Single-level wildcard (matches anything within a single directory)",
|
||||||
"Source Code": "Source Code",
|
"Source Code": "Source Code",
|
||||||
"Staggered File Versioning": "Staggered File Versioning",
|
"Staggered File Versioning": "Staggered File Versioning",
|
||||||
"Start Browser": "Start Browser",
|
"Start Browser": "Start Browser",
|
||||||
"Stopped": "Stopped",
|
"Stopped": "Stopped",
|
||||||
"Support / Forum": "Support / Forum",
|
"Support / Forum": "Support / Forum",
|
||||||
|
"Supported patterns:": "Supported patterns:",
|
||||||
"Sync Protocol Listen Addresses": "Sync Protocol Listen Addresses",
|
"Sync Protocol Listen Addresses": "Sync Protocol Listen Addresses",
|
||||||
"Synchronization": "Synchronization",
|
"Synchronization": "Synchronization",
|
||||||
"Syncing": "Syncing",
|
"Syncing": "Syncing",
|
||||||
@ -116,6 +125,7 @@
|
|||||||
"The number of old versions to keep, per file.": "The number of old versions to keep, per file.",
|
"The number of old versions to keep, per file.": "The number of old versions to keep, per file.",
|
||||||
"The number of versions must be a number and cannot be blank.": "The number of versions must be a number and cannot be blank.",
|
"The number of versions must be a number and cannot be blank.": "The number of versions must be a number and cannot be blank.",
|
||||||
"The repository ID cannot be blank.": "The repository ID cannot be blank.",
|
"The repository ID cannot be blank.": "The repository ID cannot be blank.",
|
||||||
|
"The repository ID must be a short identifier (64 characters or less) consisting of letters, numbers and the dot (.), dash (-) and underscode (_) characters only.": "The repository ID must be a short identifier (64 characters or less) consisting of letters, numbers and the dot (.), dash (-) and underscode (_) characters only.",
|
||||||
"The repository ID must be a short identifier (64 characters or less) consisting of letters, numbers and the the dot (.), dash (-) and underscode (_) characters only.": "The repository ID must be a short identifier (64 characters or less) consisting of letters, numbers and the the dot (.), dash (-) and underscode (_) characters only.",
|
"The repository ID must be a short identifier (64 characters or less) consisting of letters, numbers and the the dot (.), dash (-) and underscode (_) characters only.": "The repository ID must be a short identifier (64 characters or less) consisting of letters, numbers and the the dot (.), dash (-) and underscode (_) characters only.",
|
||||||
"The repository ID must be unique.": "The repository ID must be unique.",
|
"The repository ID must be unique.": "The repository ID must be unique.",
|
||||||
"The repository path cannot be blank.": "The repository path cannot be blank.",
|
"The repository path cannot be blank.": "The repository path cannot be blank.",
|
||||||
|
@ -122,6 +122,8 @@ func parseIgnoreFile(fd io.Reader, currentFile string, seen map[string]bool) (Pa
|
|||||||
switch {
|
switch {
|
||||||
case line == "":
|
case line == "":
|
||||||
continue
|
continue
|
||||||
|
case strings.HasPrefix(line, "//"):
|
||||||
|
continue
|
||||||
case strings.HasPrefix(line, "#"):
|
case strings.HasPrefix(line, "#"):
|
||||||
err = addPattern(line)
|
err = addPattern(line)
|
||||||
case strings.HasSuffix(line, "/**"):
|
case strings.HasSuffix(line, "/**"):
|
||||||
|
@ -133,3 +133,21 @@ func TestCaseSensitivity(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCommentsAndBlankLines(t *testing.T) {
|
||||||
|
stignore := `
|
||||||
|
// foo
|
||||||
|
//bar
|
||||||
|
|
||||||
|
//!baz
|
||||||
|
//#dex
|
||||||
|
|
||||||
|
// ips
|
||||||
|
|
||||||
|
|
||||||
|
`
|
||||||
|
pats, _ := ignore.Parse(bytes.NewBufferString(stignore), ".stignore")
|
||||||
|
if len(pats) > 0 {
|
||||||
|
t.Errorf("Expected no patterns")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,10 +5,12 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -22,6 +24,7 @@ import (
|
|||||||
"github.com/syncthing/syncthing/files"
|
"github.com/syncthing/syncthing/files"
|
||||||
"github.com/syncthing/syncthing/ignore"
|
"github.com/syncthing/syncthing/ignore"
|
||||||
"github.com/syncthing/syncthing/lamport"
|
"github.com/syncthing/syncthing/lamport"
|
||||||
|
"github.com/syncthing/syncthing/osutil"
|
||||||
"github.com/syncthing/syncthing/protocol"
|
"github.com/syncthing/syncthing/protocol"
|
||||||
"github.com/syncthing/syncthing/scanner"
|
"github.com/syncthing/syncthing/scanner"
|
||||||
"github.com/syncthing/syncthing/stats"
|
"github.com/syncthing/syncthing/stats"
|
||||||
@ -579,6 +582,78 @@ func (m *Model) ConnectedTo(nodeID protocol.NodeID) bool {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Model) GetIgnores(repo string) ([]string, error) {
|
||||||
|
var lines []string
|
||||||
|
|
||||||
|
cfg, ok := m.repoCfgs[repo]
|
||||||
|
if !ok {
|
||||||
|
return lines, fmt.Errorf("Repo %s does not exist", repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.rmut.Lock()
|
||||||
|
defer m.rmut.Unlock()
|
||||||
|
|
||||||
|
fd, err := os.Open(filepath.Join(cfg.Directory, ".stignore"))
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return lines, nil
|
||||||
|
}
|
||||||
|
l.Warnln("Loading .stignore:", err)
|
||||||
|
return lines, err
|
||||||
|
}
|
||||||
|
defer fd.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(fd)
|
||||||
|
for scanner.Scan() {
|
||||||
|
lines = append(lines, strings.TrimSpace(scanner.Text()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Model) SetIgnores(repo string, content []string) error {
|
||||||
|
cfg, ok := m.repoCfgs[repo]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Repo %s does not exist", repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
fd, err := ioutil.TempFile("", "stignore-"+repo)
|
||||||
|
if err != nil {
|
||||||
|
l.Warnln("Saving .stignore:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
writer := bufio.NewWriter(fd)
|
||||||
|
for _, line := range content {
|
||||||
|
fmt.Fprintln(writer, line)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = writer.Flush()
|
||||||
|
if err != nil {
|
||||||
|
l.Warnln("Saving .stignore:", err)
|
||||||
|
fd.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = fd.Close()
|
||||||
|
if err != nil {
|
||||||
|
l.Warnln("Saving .stignore:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
file := filepath.Join(cfg.Directory, ".stignore")
|
||||||
|
m.rmut.Lock()
|
||||||
|
os.Remove(file)
|
||||||
|
err = osutil.Rename(fd.Name(), file)
|
||||||
|
m.rmut.Unlock()
|
||||||
|
if err != nil {
|
||||||
|
l.Warnln("Saving .stignore:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.ScanRepo(repo)
|
||||||
|
}
|
||||||
|
|
||||||
// AddConnection adds a new peer connection to the model. An initial index will
|
// AddConnection adds a new peer connection to the model. An initial index will
|
||||||
// be sent to the connected peer, thereafter index updates whenever the local
|
// be sent to the connected peer, thereafter index updates whenever the local
|
||||||
// repository changes.
|
// repository changes.
|
||||||
|
@ -369,3 +369,89 @@ func TestClusterConfig(t *testing.T) {
|
|||||||
t.Errorf("Incorrect node ID %x != %x", id, node2)
|
t.Errorf("Incorrect node ID %x != %x", id, node2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIgnores(t *testing.T) {
|
||||||
|
arrEqual := func(a, b []string) bool {
|
||||||
|
if len(a) != len(b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range a {
|
||||||
|
if a[i] != b[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
db, _ := leveldb.Open(storage.NewMemStorage(), nil)
|
||||||
|
m := NewModel("/tmp", nil, "node", "syncthing", "dev", db)
|
||||||
|
m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"})
|
||||||
|
|
||||||
|
expected := []string{
|
||||||
|
".*",
|
||||||
|
"quux",
|
||||||
|
}
|
||||||
|
|
||||||
|
ignores, err := m.GetIgnores("default")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !arrEqual(ignores, expected) {
|
||||||
|
t.Errorf("Incorrect ignores: %v != %v", ignores, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
ignores = append(ignores, "pox")
|
||||||
|
|
||||||
|
err = m.SetIgnores("default", ignores)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ignores2, err := m.GetIgnores("default")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if arrEqual(expected, ignores2) {
|
||||||
|
t.Errorf("Incorrect ignores: %v == %v", ignores2, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !arrEqual(ignores, ignores2) {
|
||||||
|
t.Errorf("Incorrect ignores: %v != %v", ignores2, ignores)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = m.SetIgnores("default", expected)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ignores, err = m.GetIgnores("default")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !arrEqual(ignores, expected) {
|
||||||
|
t.Errorf("Incorrect ignores: %v != %v", ignores, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
ignores, err = m.GetIgnores("doesnotexist")
|
||||||
|
if err == nil {
|
||||||
|
t.Error("No error")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = m.SetIgnores("doesnotexist", expected)
|
||||||
|
if err == nil {
|
||||||
|
t.Error("No error")
|
||||||
|
}
|
||||||
|
|
||||||
|
m.AddRepo(config.RepositoryConfiguration{ID: "fresh", Directory: "XXX"})
|
||||||
|
ignores, err = m.GetIgnores("fresh")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if len(ignores) > 0 {
|
||||||
|
t.Errorf("Expected no ignores, got: %v", ignores)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user