mirror of
https://github.com/octoleo/syncthing.git
synced 2025-01-03 07:12:27 +00:00
This commit is contained in:
parent
df522576ac
commit
05835ed81f
@ -22,11 +22,15 @@ func init() {
|
|||||||
panic("Couldn't find block profiler")
|
panic("Couldn't find block profiler")
|
||||||
}
|
}
|
||||||
l.Debugln("Starting block profiling")
|
l.Debugln("Starting block profiling")
|
||||||
go saveBlockingProfiles(profiler)
|
go func() {
|
||||||
|
err := saveBlockingProfiles(profiler) // Only returns on error
|
||||||
|
l.Warnln("Block profiler failed:", err)
|
||||||
|
panic("Block profiler failed")
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveBlockingProfiles(profiler *pprof.Profile) {
|
func saveBlockingProfiles(profiler *pprof.Profile) error {
|
||||||
runtime.SetBlockProfileRate(1)
|
runtime.SetBlockProfileRate(1)
|
||||||
|
|
||||||
t0 := time.Now()
|
t0 := time.Now()
|
||||||
@ -35,16 +39,16 @@ func saveBlockingProfiles(profiler *pprof.Profile) {
|
|||||||
|
|
||||||
fd, err := os.Create(fmt.Sprintf("block-%05d-%07d.pprof", syscall.Getpid(), startms))
|
fd, err := os.Create(fmt.Sprintf("block-%05d-%07d.pprof", syscall.Getpid(), startms))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return err
|
||||||
}
|
}
|
||||||
err = profiler.WriteTo(fd, 0)
|
err = profiler.WriteTo(fd, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return err
|
||||||
}
|
}
|
||||||
err = fd.Close()
|
err = fd.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -23,11 +23,15 @@ func init() {
|
|||||||
rate = i
|
rate = i
|
||||||
}
|
}
|
||||||
l.Debugln("Starting heap profiling")
|
l.Debugln("Starting heap profiling")
|
||||||
go saveHeapProfiles(rate)
|
go func() {
|
||||||
|
err := saveHeapProfiles(rate) // Only returns on error
|
||||||
|
l.Warnln("Heap profiler failed:", err)
|
||||||
|
panic("Heap profiler failed")
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveHeapProfiles(rate int) {
|
func saveHeapProfiles(rate int) error {
|
||||||
runtime.MemProfileRate = rate
|
runtime.MemProfileRate = rate
|
||||||
var memstats, prevMemstats runtime.MemStats
|
var memstats, prevMemstats runtime.MemStats
|
||||||
|
|
||||||
@ -38,21 +42,21 @@ func saveHeapProfiles(rate int) {
|
|||||||
if memstats.HeapInuse > prevMemstats.HeapInuse {
|
if memstats.HeapInuse > prevMemstats.HeapInuse {
|
||||||
fd, err := os.Create(name + ".tmp")
|
fd, err := os.Create(name + ".tmp")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return err
|
||||||
}
|
}
|
||||||
err = pprof.WriteHeapProfile(fd)
|
err = pprof.WriteHeapProfile(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return err
|
||||||
}
|
}
|
||||||
err = fd.Close()
|
err = fd.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Remove(name) // Error deliberately ignored
|
os.Remove(name) // Error deliberately ignored
|
||||||
err = os.Rename(name+".tmp", name)
|
err = os.Rename(name+".tmp", name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
prevMemstats = memstats
|
prevMemstats = memstats
|
||||||
|
@ -102,7 +102,8 @@ func monitorMain(runtimeOptions RuntimeOptions) {
|
|||||||
l.Infoln("Starting syncthing")
|
l.Infoln("Starting syncthing")
|
||||||
err = cmd.Start()
|
err = cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
l.Warnln("Error starting the main Syncthing process:", err)
|
||||||
|
panic("Error starting the main Syncthing process")
|
||||||
}
|
}
|
||||||
|
|
||||||
stdoutMut.Lock()
|
stdoutMut.Lock()
|
||||||
|
@ -109,7 +109,8 @@ func New(myID protocol.DeviceID) Configuration {
|
|||||||
|
|
||||||
// Can't happen.
|
// Can't happen.
|
||||||
if err := cfg.prepare(myID); err != nil {
|
if err := cfg.prepare(myID); err != nil {
|
||||||
panic("bug: error in preparing new folder: " + err.Error())
|
l.Warnln("bug: error in preparing new folder:", err)
|
||||||
|
panic("error in preparing new folder")
|
||||||
}
|
}
|
||||||
|
|
||||||
return cfg
|
return cfg
|
||||||
|
@ -46,7 +46,8 @@ const (
|
|||||||
func init() {
|
func init() {
|
||||||
err := expandLocations()
|
err := expandLocations()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
fmt.Println(err)
|
||||||
|
panic("Failed to expand locations at init time")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +125,8 @@ func defaultConfigDir() string {
|
|||||||
case "darwin":
|
case "darwin":
|
||||||
dir, err := fs.ExpandTilde("~/Library/Application Support/Syncthing")
|
dir, err := fs.ExpandTilde("~/Library/Application Support/Syncthing")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
fmt.Println(err)
|
||||||
|
panic("Failed to get default config dir")
|
||||||
}
|
}
|
||||||
return dir
|
return dir
|
||||||
|
|
||||||
@ -134,7 +136,8 @@ func defaultConfigDir() string {
|
|||||||
}
|
}
|
||||||
dir, err := fs.ExpandTilde("~/.config/syncthing")
|
dir, err := fs.ExpandTilde("~/.config/syncthing")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
fmt.Println(err)
|
||||||
|
panic("Failed to get default config dir")
|
||||||
}
|
}
|
||||||
return dir
|
return dir
|
||||||
}
|
}
|
||||||
@ -144,7 +147,8 @@ func defaultConfigDir() string {
|
|||||||
func homeDir() string {
|
func homeDir() string {
|
||||||
home, err := fs.ExpandTilde("~")
|
home, err := fs.ExpandTilde("~")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
fmt.Println(err)
|
||||||
|
panic("Failed to get user home dir")
|
||||||
}
|
}
|
||||||
return home
|
return home
|
||||||
}
|
}
|
||||||
|
@ -594,9 +594,9 @@ func (f *sendReceiveFolder) handleDir(file protocol.FileInfo, dbUpdateChan chan<
|
|||||||
// Symlinks aren't checked for conflicts.
|
// Symlinks aren't checked for conflicts.
|
||||||
|
|
||||||
file.Version = file.Version.Merge(curFile.Version)
|
file.Version = file.Version.Merge(curFile.Version)
|
||||||
err = inWritableDir(func(name string) error {
|
err = f.inWritableDir(func(name string) error {
|
||||||
return f.moveForConflict(name, file.ModifiedBy.String(), scanChan)
|
return f.moveForConflict(name, file.ModifiedBy.String(), scanChan)
|
||||||
}, f.fs, curFile.Name)
|
}, curFile.Name)
|
||||||
} else {
|
} else {
|
||||||
err = f.deleteItemOnDisk(curFile, scanChan)
|
err = f.deleteItemOnDisk(curFile, scanChan)
|
||||||
}
|
}
|
||||||
@ -633,7 +633,7 @@ func (f *sendReceiveFolder) handleDir(file protocol.FileInfo, dbUpdateChan chan<
|
|||||||
return f.fs.Chmod(path, mode|(info.Mode()&retainBits))
|
return f.fs.Chmod(path, mode|(info.Mode()&retainBits))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = inWritableDir(mkdir, f.fs, file.Name); err == nil {
|
if err = f.inWritableDir(mkdir, file.Name); err == nil {
|
||||||
dbUpdateChan <- dbUpdateJob{file, dbUpdateHandleDir}
|
dbUpdateChan <- dbUpdateJob{file, dbUpdateHandleDir}
|
||||||
} else {
|
} else {
|
||||||
f.newPullError(file.Name, errors.Wrap(err, "creating directory"))
|
f.newPullError(file.Name, errors.Wrap(err, "creating directory"))
|
||||||
@ -748,9 +748,9 @@ func (f *sendReceiveFolder) handleSymlink(file protocol.FileInfo, dbUpdateChan c
|
|||||||
// Directories and symlinks aren't checked for conflicts.
|
// Directories and symlinks aren't checked for conflicts.
|
||||||
|
|
||||||
file.Version = file.Version.Merge(curFile.Version)
|
file.Version = file.Version.Merge(curFile.Version)
|
||||||
err = inWritableDir(func(name string) error {
|
err = f.inWritableDir(func(name string) error {
|
||||||
return f.moveForConflict(name, file.ModifiedBy.String(), scanChan)
|
return f.moveForConflict(name, file.ModifiedBy.String(), scanChan)
|
||||||
}, f.fs, curFile.Name)
|
}, curFile.Name)
|
||||||
} else {
|
} else {
|
||||||
err = f.deleteItemOnDisk(curFile, scanChan)
|
err = f.deleteItemOnDisk(curFile, scanChan)
|
||||||
}
|
}
|
||||||
@ -769,7 +769,7 @@ func (f *sendReceiveFolder) handleSymlink(file protocol.FileInfo, dbUpdateChan c
|
|||||||
return f.maybeCopyOwner(path)
|
return f.maybeCopyOwner(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = inWritableDir(createLink, f.fs, file.Name); err == nil {
|
if err = f.inWritableDir(createLink, file.Name); err == nil {
|
||||||
dbUpdateChan <- dbUpdateJob{file, dbUpdateHandleSymlink}
|
dbUpdateChan <- dbUpdateJob{file, dbUpdateHandleSymlink}
|
||||||
} else {
|
} else {
|
||||||
f.newPullError(file.Name, errors.Wrap(err, "symlink create"))
|
f.newPullError(file.Name, errors.Wrap(err, "symlink create"))
|
||||||
@ -869,9 +869,9 @@ func (f *sendReceiveFolder) deleteFileWithCurrent(file, cur protocol.FileInfo, h
|
|||||||
}
|
}
|
||||||
|
|
||||||
if f.versioner != nil && !cur.IsSymlink() {
|
if f.versioner != nil && !cur.IsSymlink() {
|
||||||
err = inWritableDir(f.versioner.Archive, f.fs, file.Name)
|
err = f.inWritableDir(f.versioner.Archive, file.Name)
|
||||||
} else {
|
} else {
|
||||||
err = inWritableDir(f.fs.Remove, f.fs, file.Name)
|
err = f.inWritableDir(f.fs.Remove, file.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == nil || fs.IsNotExist(err) {
|
if err == nil || fs.IsNotExist(err) {
|
||||||
@ -971,7 +971,7 @@ func (f *sendReceiveFolder) renameFile(cur, source, target protocol.FileInfo, db
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
err = osutil.Copy(f.fs, f.fs, source.Name, tempName)
|
err = osutil.Copy(f.fs, f.fs, source.Name, tempName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = inWritableDir(f.versioner.Archive, f.fs, source.Name)
|
err = f.inWritableDir(f.versioner.Archive, source.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1078,7 +1078,7 @@ func (f *sendReceiveFolder) handleFile(file protocol.FileInfo, copyChan chan<- c
|
|||||||
// Otherwise, discard the file ourselves in order for the
|
// Otherwise, discard the file ourselves in order for the
|
||||||
// sharedpuller not to panic when it fails to exclusively create a
|
// sharedpuller not to panic when it fails to exclusively create a
|
||||||
// file which already exists
|
// file which already exists
|
||||||
inWritableDir(f.fs.Remove, f.fs, tempName)
|
f.inWritableDir(f.fs.Remove, tempName)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Copy the blocks, as we don't want to shuffle them on the FileInfo
|
// Copy the blocks, as we don't want to shuffle them on the FileInfo
|
||||||
@ -1522,9 +1522,9 @@ func (f *sendReceiveFolder) performFinish(file, curFile protocol.FileInfo, hasCu
|
|||||||
// Directories and symlinks aren't checked for conflicts.
|
// Directories and symlinks aren't checked for conflicts.
|
||||||
|
|
||||||
file.Version = file.Version.Merge(curFile.Version)
|
file.Version = file.Version.Merge(curFile.Version)
|
||||||
err = inWritableDir(func(name string) error {
|
err = f.inWritableDir(func(name string) error {
|
||||||
return f.moveForConflict(name, file.ModifiedBy.String(), scanChan)
|
return f.moveForConflict(name, file.ModifiedBy.String(), scanChan)
|
||||||
}, f.fs, curFile.Name)
|
}, curFile.Name)
|
||||||
} else {
|
} else {
|
||||||
err = f.deleteItemOnDisk(curFile, scanChan)
|
err = f.deleteItemOnDisk(curFile, scanChan)
|
||||||
}
|
}
|
||||||
@ -1825,10 +1825,10 @@ func (f *sendReceiveFolder) deleteItemOnDisk(item protocol.FileInfo, scanChan ch
|
|||||||
// an error.
|
// an error.
|
||||||
// Symlinks aren't archived.
|
// Symlinks aren't archived.
|
||||||
|
|
||||||
return inWritableDir(f.versioner.Archive, f.fs, item.Name)
|
return f.inWritableDir(f.versioner.Archive, item.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return inWritableDir(f.fs.Remove, f.fs, item.Name)
|
return f.inWritableDir(f.fs.Remove, item.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// deleteDirOnDisk attempts to delete a directory. It checks for files/dirs inside
|
// deleteDirOnDisk attempts to delete a directory. It checks for files/dirs inside
|
||||||
@ -1879,7 +1879,7 @@ func (f *sendReceiveFolder) deleteDirOnDisk(dir string, scanChan chan<- string)
|
|||||||
f.fs.RemoveAll(del)
|
f.fs.RemoveAll(del)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := inWritableDir(f.fs.Remove, f.fs, dir)
|
err := f.inWritableDir(f.fs.Remove, dir)
|
||||||
if err == nil || fs.IsNotExist(err) {
|
if err == nil || fs.IsNotExist(err) {
|
||||||
// It was removed or it doesn't exist to start with
|
// It was removed or it doesn't exist to start with
|
||||||
return nil
|
return nil
|
||||||
@ -1963,6 +1963,10 @@ func (f *sendReceiveFolder) maybeCopyOwner(path string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *sendReceiveFolder) inWritableDir(fn func(string) error, path string) error {
|
||||||
|
return inWritableDir(fn, f.fs, path, f.IgnorePerms)
|
||||||
|
}
|
||||||
|
|
||||||
// A []FileError is sent as part of an event and will be JSON serialized.
|
// A []FileError is sent as part of an event and will be JSON serialized.
|
||||||
type FileError struct {
|
type FileError struct {
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
|
@ -8,7 +8,6 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"path/filepath"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -92,25 +91,16 @@ func (s *sharedPullerState) tempFile() (io.WriterAt, error) {
|
|||||||
return lockedWriterAt{&s.mut, s.fd}, nil
|
return lockedWriterAt{&s.mut, s.fd}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the parent directory is writable. This is
|
if err := inWritableDir(s.tempFileInWritableDir, s.fs, s.tempName, s.ignorePerms); err != nil {
|
||||||
// osutil.InWritableDir except we need to do more stuff so we duplicate it
|
s.failLocked(err)
|
||||||
// here.
|
|
||||||
dir := filepath.Dir(s.tempName)
|
|
||||||
if info, err := s.fs.Stat(dir); err != nil {
|
|
||||||
s.failLocked(errors.Wrap(err, "ensuring parent dir is writeable"))
|
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if info.Mode()&0200 == 0 {
|
|
||||||
err := s.fs.Chmod(dir, 0755)
|
|
||||||
if !s.ignorePerms && err == nil {
|
|
||||||
defer func() {
|
|
||||||
err := s.fs.Chmod(dir, info.Mode()&fs.ModePerm)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return lockedWriterAt{&s.mut, s.fd}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// tempFileInWritableDir should only be called from tempFile.
|
||||||
|
func (s *sharedPullerState) tempFileInWritableDir(_ string) error {
|
||||||
// The permissions to use for the temporary file should be those of the
|
// The permissions to use for the temporary file should be those of the
|
||||||
// final file, except we need user read & write at minimum. The
|
// final file, except we need user read & write at minimum. The
|
||||||
// permissions will be set to the final value later, but in the meantime
|
// permissions will be set to the final value later, but in the meantime
|
||||||
@ -140,14 +130,12 @@ func (s *sharedPullerState) tempFile() (io.WriterAt, error) {
|
|||||||
// what the umask dictates.
|
// what the umask dictates.
|
||||||
|
|
||||||
if err := s.fs.Chmod(s.tempName, mode); err != nil {
|
if err := s.fs.Chmod(s.tempName, mode); err != nil {
|
||||||
s.failLocked(errors.Wrap(err, "setting perms on temp file"))
|
return errors.Wrap(err, "setting perms on temp file")
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fd, err := s.fs.OpenFile(s.tempName, flags, mode)
|
fd, err := s.fs.OpenFile(s.tempName, flags, mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.failLocked(errors.Wrap(err, "opening temp file"))
|
return errors.Wrap(err, "opening temp file")
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide the temporary file
|
// Hide the temporary file
|
||||||
@ -177,16 +165,14 @@ func (s *sharedPullerState) tempFile() (io.WriterAt, error) {
|
|||||||
l.Debugln("failed to remove temporary file:", remErr)
|
l.Debugln("failed to remove temporary file:", remErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.failLocked(err)
|
return err
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same fd will be used by all writers
|
// Same fd will be used by all writers
|
||||||
s.fd = fd
|
s.fd = fd
|
||||||
|
return nil
|
||||||
return lockedWriterAt{&s.mut, s.fd}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fail sets the error on the puller state compose of error, and marks the
|
// fail sets the error on the puller state compose of error, and marks the
|
||||||
|
@ -66,7 +66,7 @@ func (d *deadlockDetector) Watch(name string, mut sync.Locker) {
|
|||||||
|
|
||||||
// inWritableDir calls fn(path), while making sure that the directory
|
// inWritableDir calls fn(path), while making sure that the directory
|
||||||
// containing `path` is writable for the duration of the call.
|
// containing `path` is writable for the duration of the call.
|
||||||
func inWritableDir(fn func(string) error, targetFs fs.Filesystem, path string) error {
|
func inWritableDir(fn func(string) error, targetFs fs.Filesystem, path string, ignorePerms bool) error {
|
||||||
dir := filepath.Dir(path)
|
dir := filepath.Dir(path)
|
||||||
info, err := targetFs.Stat(dir)
|
info, err := targetFs.Stat(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -86,8 +86,12 @@ func inWritableDir(fn func(string) error, targetFs fs.Filesystem, path string) e
|
|||||||
// succeeded or failed on its own so returning an error to the
|
// succeeded or failed on its own so returning an error to the
|
||||||
// caller is inappropriate.)
|
// caller is inappropriate.)
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := targetFs.Chmod(dir, info.Mode()); err != nil && !fs.IsNotExist(err) {
|
if err := targetFs.Chmod(dir, info.Mode()&fs.ModePerm); err != nil && !fs.IsNotExist(err) {
|
||||||
l.Warnln("Failed to restore directory permissions after gaining write access:", err)
|
logFn := l.Warnln
|
||||||
|
if ignorePerms {
|
||||||
|
logFn = l.Debugln
|
||||||
|
}
|
||||||
|
logFn("Failed to restore directory permissions after gaining write access:", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
@ -35,35 +35,35 @@ func TestInWriteableDir(t *testing.T) {
|
|||||||
|
|
||||||
// These should succeed
|
// These should succeed
|
||||||
|
|
||||||
err := inWritableDir(create, fs, "testdata/file")
|
err := inWritableDir(create, fs, "testdata/file", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("testdata/file:", err)
|
t.Error("testdata/file:", err)
|
||||||
}
|
}
|
||||||
err = inWritableDir(create, fs, "testdata/rw/foo")
|
err = inWritableDir(create, fs, "testdata/rw/foo", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("testdata/rw/foo:", err)
|
t.Error("testdata/rw/foo:", err)
|
||||||
}
|
}
|
||||||
err = inWritableDir(fs.Remove, fs, "testdata/rw/foo")
|
err = inWritableDir(fs.Remove, fs, "testdata/rw/foo", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("testdata/rw/foo:", err)
|
t.Error("testdata/rw/foo:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = inWritableDir(create, fs, "testdata/ro/foo")
|
err = inWritableDir(create, fs, "testdata/ro/foo", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("testdata/ro/foo:", err)
|
t.Error("testdata/ro/foo:", err)
|
||||||
}
|
}
|
||||||
err = inWritableDir(fs.Remove, fs, "testdata/ro/foo")
|
err = inWritableDir(fs.Remove, fs, "testdata/ro/foo", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("testdata/ro/foo:", err)
|
t.Error("testdata/ro/foo:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// These should not
|
// These should not
|
||||||
|
|
||||||
err = inWritableDir(create, fs, "testdata/nonexistent/foo")
|
err = inWritableDir(create, fs, "testdata/nonexistent/foo", false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("testdata/nonexistent/foo returned nil error")
|
t.Error("testdata/nonexistent/foo returned nil error")
|
||||||
}
|
}
|
||||||
err = inWritableDir(create, fs, "testdata/file/foo")
|
err = inWritableDir(create, fs, "testdata/file/foo", false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("testdata/file/foo returned nil error")
|
t.Error("testdata/file/foo returned nil error")
|
||||||
}
|
}
|
||||||
@ -100,7 +100,7 @@ func TestOSWindowsRemove(t *testing.T) {
|
|||||||
fs.Chmod("testdata/windows/ro/readonly", 0500)
|
fs.Chmod("testdata/windows/ro/readonly", 0500)
|
||||||
|
|
||||||
for _, path := range []string{"testdata/windows/ro/readonly", "testdata/windows/ro", "testdata/windows"} {
|
for _, path := range []string{"testdata/windows/ro/readonly", "testdata/windows/ro", "testdata/windows"} {
|
||||||
err := inWritableDir(fs.Remove, fs, path)
|
err := inWritableDir(fs.Remove, fs, path, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unexpected error %s: %s", path, err)
|
t.Errorf("Unexpected error %s: %s", path, err)
|
||||||
}
|
}
|
||||||
@ -183,7 +183,7 @@ func TestInWritableDirWindowsRename(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, path := range []string{"testdata/windows/ro/readonly", "testdata/windows/ro", "testdata/windows"} {
|
for _, path := range []string{"testdata/windows/ro/readonly", "testdata/windows/ro", "testdata/windows"} {
|
||||||
err := inWritableDir(rename, fs, path)
|
err := inWritableDir(rename, fs, path, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unexpected error %s: %s", path, err)
|
t.Errorf("Unexpected error %s: %s", path, err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user