mirror of
https://github.com/octoleo/syncthing.git
synced 2025-01-09 17:53:59 +00:00
Merge pull request #1705 from AudriusButkevicius/glob
Add osutil.Glob to deal with Windows (fixes #1690)
This commit is contained in:
commit
a17c48aed6
@ -829,7 +829,7 @@ func restGetSystemBrowse(w http.ResponseWriter, r *http.Request) {
|
|||||||
if strings.HasSuffix(current, pathSeparator) && !strings.HasSuffix(search, pathSeparator) {
|
if strings.HasSuffix(current, pathSeparator) && !strings.HasSuffix(search, pathSeparator) {
|
||||||
search = search + pathSeparator
|
search = search + pathSeparator
|
||||||
}
|
}
|
||||||
subdirectories, _ := filepath.Glob(search + "*")
|
subdirectories, _ := osutil.Glob(search + "*")
|
||||||
ret := make([]string, 0, 10)
|
ret := make([]string, 0, 10)
|
||||||
for _, subdirectory := range subdirectories {
|
for _, subdirectory := range subdirectories {
|
||||||
info, err := os.Stat(subdirectory)
|
info, err := os.Stat(subdirectory)
|
||||||
|
@ -1061,7 +1061,7 @@ func cleanConfigDirectory() {
|
|||||||
|
|
||||||
for pat, dur := range patterns {
|
for pat, dur := range patterns {
|
||||||
pat = filepath.Join(baseDirs["config"], pat)
|
pat = filepath.Join(baseDirs["config"], pat)
|
||||||
files, err := filepath.Glob(pat)
|
files, err := osutil.Glob(pat)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Infoln("Cleaning:", err)
|
l.Infoln("Cleaning:", err)
|
||||||
continue
|
continue
|
||||||
|
17
internal/osutil/glob_unix.go
Normal file
17
internal/osutil/glob_unix.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (C) 2015 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 http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package osutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Glob(pattern string) (matches []string, err error) {
|
||||||
|
return filepath.Glob(pattern)
|
||||||
|
}
|
92
internal/osutil/glob_windows.go
Normal file
92
internal/osutil/glob_windows.go
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
// Copyright (C) 2015 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 http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package osutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Deals with https://github.com/golang/go/issues/10577
|
||||||
|
func Glob(pattern string) (matches []string, err error) {
|
||||||
|
if !hasMeta(pattern) {
|
||||||
|
if _, err = os.Lstat(pattern); err != nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return []string{pattern}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
dir, file := filepath.Split(pattern)
|
||||||
|
switch dir {
|
||||||
|
case "":
|
||||||
|
dir = "."
|
||||||
|
case string(filepath.Separator):
|
||||||
|
// nothing
|
||||||
|
default:
|
||||||
|
dir = dir[0 : len(dir)-1] // chop off trailing separator
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasMeta(dir) {
|
||||||
|
return glob(dir, file, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
var m []string
|
||||||
|
m, err = Glob(dir)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, d := range m {
|
||||||
|
matches, err = glob(d, file, matches)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasMeta(path string) bool {
|
||||||
|
// Strip off Windows long path prefix if it exists.
|
||||||
|
if strings.HasPrefix(path, "\\\\?\\") {
|
||||||
|
path = path[4:]
|
||||||
|
}
|
||||||
|
// TODO(niemeyer): Should other magic characters be added here?
|
||||||
|
return strings.IndexAny(path, "*?[") >= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func glob(dir, pattern string, matches []string) (m []string, e error) {
|
||||||
|
m = matches
|
||||||
|
fi, err := os.Stat(dir)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !fi.IsDir() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d, err := os.Open(dir)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer d.Close()
|
||||||
|
|
||||||
|
names, _ := d.Readdirnames(-1)
|
||||||
|
sort.Strings(names)
|
||||||
|
|
||||||
|
for _, n := range names {
|
||||||
|
matched, err := filepath.Match(pattern, n)
|
||||||
|
if err != nil {
|
||||||
|
return m, err
|
||||||
|
}
|
||||||
|
if matched {
|
||||||
|
m = append(m, filepath.Join(dir, n))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
@ -97,14 +97,14 @@ func (v Simple) Archive(filePath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Glob according to the new file~timestamp.ext pattern.
|
// Glob according to the new file~timestamp.ext pattern.
|
||||||
newVersions, err := filepath.Glob(filepath.Join(dir, taggedFilename(file, TimeGlob)))
|
newVersions, err := osutil.Glob(filepath.Join(dir, taggedFilename(file, TimeGlob)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Warnln("globbing:", err)
|
l.Warnln("globbing:", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also according to the old file.ext~timestamp pattern.
|
// Also according to the old file.ext~timestamp pattern.
|
||||||
oldVersions, err := filepath.Glob(filepath.Join(dir, file+"~"+TimeGlob))
|
oldVersions, err := osutil.Glob(filepath.Join(dir, file+"~"+TimeGlob))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Warnln("globbing:", err)
|
l.Warnln("globbing:", err)
|
||||||
return nil
|
return nil
|
||||||
|
@ -329,14 +329,14 @@ func (v Staggered) Archive(filePath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Glob according to the new file~timestamp.ext pattern.
|
// Glob according to the new file~timestamp.ext pattern.
|
||||||
newVersions, err := filepath.Glob(filepath.Join(dir, taggedFilename(file, TimeGlob)))
|
newVersions, err := osutil.Glob(filepath.Join(dir, taggedFilename(file, TimeGlob)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Warnln("globbing:", err)
|
l.Warnln("globbing:", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also according to the old file.ext~timestamp pattern.
|
// Also according to the old file.ext~timestamp pattern.
|
||||||
oldVersions, err := filepath.Glob(filepath.Join(dir, file+"~"+TimeGlob))
|
oldVersions, err := osutil.Glob(filepath.Join(dir, file+"~"+TimeGlob))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Warnln("globbing:", err)
|
l.Warnln("globbing:", err)
|
||||||
return nil
|
return nil
|
||||||
|
@ -7,8 +7,12 @@
|
|||||||
package versioner
|
package versioner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTaggedFilename(t *testing.T) {
|
func TestTaggedFilename(t *testing.T) {
|
||||||
@ -42,3 +46,45 @@ func TestTaggedFilename(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSimpleVersioningVersionCount(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("Test takes some time, skipping.")
|
||||||
|
}
|
||||||
|
|
||||||
|
dir, err := ioutil.TempDir("", "")
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
v := NewSimple("", dir, map[string]string{"keep": "2"})
|
||||||
|
versionDir := filepath.Join(dir, ".stversions")
|
||||||
|
|
||||||
|
path := filepath.Join(dir, "test")
|
||||||
|
|
||||||
|
for i := 1; i <= 3; i++ {
|
||||||
|
f, err := os.Create(path)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
v.Archive(path)
|
||||||
|
|
||||||
|
d, err := os.Open(versionDir)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
n, err := d.Readdirnames(-1)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if float64(len(n)) != math.Min(float64(i), 2) {
|
||||||
|
t.Error("Wrong count")
|
||||||
|
}
|
||||||
|
d.Close()
|
||||||
|
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -49,7 +49,7 @@ func TestCLIReset(t *testing.T) {
|
|||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
|
|
||||||
dirs, err = filepath.Glob("*.syncthing-reset-*")
|
dirs, err = osutil.Glob("*.syncthing-reset-*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ func TestConflict(t *testing.T) {
|
|||||||
// The conflict is expected on the s2 side due to how we calculate which
|
// The conflict is expected on the s2 side due to how we calculate which
|
||||||
// file is the winner (based on device ID)
|
// file is the winner (based on device ID)
|
||||||
|
|
||||||
files, err := filepath.Glob("s2/*sync-conflict*")
|
files, err := osutil.Glob("s2/*sync-conflict*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -170,7 +170,7 @@ func TestConflict(t *testing.T) {
|
|||||||
// The conflict should manifest on the s2 side again, where we should have
|
// The conflict should manifest on the s2 side again, where we should have
|
||||||
// moved the file to a conflict copy instead of just deleting it.
|
// moved the file to a conflict copy instead of just deleting it.
|
||||||
|
|
||||||
files, err = filepath.Glob("s2/*sync-conflict*")
|
files, err = osutil.Glob("s2/*sync-conflict*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -240,7 +240,7 @@ func TestInitialMergeConflicts(t *testing.T) {
|
|||||||
|
|
||||||
// s1 should have three-four files (there's a conflict from s2 which may or may not have synced yet)
|
// s1 should have three-four files (there's a conflict from s2 which may or may not have synced yet)
|
||||||
|
|
||||||
files, err := filepath.Glob("s1/file*")
|
files, err := osutil.Glob("s1/file*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -250,7 +250,7 @@ func TestInitialMergeConflicts(t *testing.T) {
|
|||||||
|
|
||||||
// s2 should have four files (there's a conflict)
|
// s2 should have four files (there's a conflict)
|
||||||
|
|
||||||
files, err = filepath.Glob("s2/file*")
|
files, err = osutil.Glob("s2/file*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -260,7 +260,7 @@ func TestInitialMergeConflicts(t *testing.T) {
|
|||||||
|
|
||||||
// file1 is in conflict, so there's two versions of that one
|
// file1 is in conflict, so there's two versions of that one
|
||||||
|
|
||||||
files, err = filepath.Glob("s2/file1*")
|
files, err = osutil.Glob("s2/file1*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -316,7 +316,7 @@ func TestResetConflicts(t *testing.T) {
|
|||||||
|
|
||||||
// s1 should have three files
|
// s1 should have three files
|
||||||
|
|
||||||
files, err := filepath.Glob("s1/file*")
|
files, err := osutil.Glob("s1/file*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -326,7 +326,7 @@ func TestResetConflicts(t *testing.T) {
|
|||||||
|
|
||||||
// s2 should have three
|
// s2 should have three
|
||||||
|
|
||||||
files, err = filepath.Glob("s2/file*")
|
files, err = osutil.Glob("s2/file*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -409,7 +409,7 @@ func TestResetConflicts(t *testing.T) {
|
|||||||
|
|
||||||
// s2 should have five files (three plus two conflicts)
|
// s2 should have five files (three plus two conflicts)
|
||||||
|
|
||||||
files, err = filepath.Glob("s2/file*")
|
files, err = osutil.Glob("s2/file*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -419,7 +419,7 @@ func TestResetConflicts(t *testing.T) {
|
|||||||
|
|
||||||
// file1 is in conflict, so there's two versions of that one
|
// file1 is in conflict, so there's two versions of that one
|
||||||
|
|
||||||
files, err = filepath.Glob("s2/file1*")
|
files, err = osutil.Glob("s2/file1*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -429,7 +429,7 @@ func TestResetConflicts(t *testing.T) {
|
|||||||
|
|
||||||
// file2 is in conflict, so there's two versions of that one
|
// file2 is in conflict, so there's two versions of that one
|
||||||
|
|
||||||
files, err = filepath.Glob("s2/file2*")
|
files, err = osutil.Glob("s2/file2*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -241,7 +241,7 @@ func (i *inifiteReader) Read(bs []byte) (int, error) {
|
|||||||
// rm -rf
|
// rm -rf
|
||||||
func removeAll(dirs ...string) error {
|
func removeAll(dirs ...string) error {
|
||||||
for _, dir := range dirs {
|
for _, dir := range dirs {
|
||||||
files, err := filepath.Glob(dir)
|
files, err := osutil.Glob(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user