Repository: syncthing/syncthing
File: lib/model/folder_sendrecv.go (Go)

Code before:
	}

	for _, del := range toBeDeleted {
		f.fs.RemoveAll(del)
	}

	err := osutil.InWritableDir(f.fs.Remove, f.fs, dir)
	if err == nil || fs.IsNotExist(err) {
		// It was removed or it doesn't exist to start with
		return nil
	}
	if _, serr := f.fs.Lstat(dir); serr != nil && !fs.IsPermission(serr) {
		// We get an error just looking at the directory, and it's not a
		// permission problem. Lets assume the error is in fact some variant
		// of "file does not exist" (possibly expressed as some parent being a
		// file and not a directory etc) and that the delete is handled.
		return nil
	}

	return err
}

// itemChanged returns true if the given disk file differs from the information
// in the database and schedules that file for scanning
func (f *sendReceiveFolder) itemChanged(stat fs.FileInfo, item protocol.FileInfo, hasItem bool, scanChan chan<- string) (changed bool, err error) {
	defer func() {
		if changed {
			scanChan <- item.Name
		}
	}()

	if !hasItem || item.Deleted {
		// The item appeared from nowhere
		return true, nil
	}

	// Check that the item on disk is what we expect it to be according
	// to the database. If there's a mismatch here, there might be local
	// changes that we don't know about yet and we should scan before
	// touching the item.
	statItem, err := scanner.CreateFileInfo(stat, item.Name, f.fs)
	if err != nil {
		return false, errors.Wrap(err, "comparing item on disk to db")
	}

	return !statItem.IsEquivalentOptional(item, f.IgnorePerms, true, protocol.LocalAllFlags), nil
}

// checkToBeDeleted makes sure the file on disk is compatible with what there is
// in the DB before the caller proceeds with actually deleting it.
// I.e. non-nil error status means "Do not delete!".

Review comment (suggestion):
I think a lot of stuff that is passed into this, could just be geneerated by this function itself, so you'd just need to pass in a name or protocol.FileInfo (to avoid the db access).

I wonder how often we'd end up with double stats because of this. If alot, perhaps not worth it.


Code after:
		return errDirNotEmpty
	}

	for _, del := range toBeDeleted {
		f.fs.RemoveAll(del)
	}

	err := osutil.InWritableDir(f.fs.Remove, f.fs, dir)
	if err == nil || fs.IsNotExist(err) {
		// It was removed or it doesn't exist to start with
		return nil
	}
	if _, serr := f.fs.Lstat(dir); serr != nil && !fs.IsPermission(serr) {
		// We get an error just looking at the directory, and it's not a
		// permission problem. Lets assume the error is in fact some variant
		// of "file does not exist" (possibly expressed as some parent being a
		// file and not a directory etc) and that the delete is handled.
		return nil
	}

	return err
}

// itemChanged returns true if the given disk file differs from the information
// in the database and schedules that file for scanning
func (f *sendReceiveFolder) itemChanged(stat fs.FileInfo, item protocol.FileInfo, hasItem bool, scanChan chan<- string) (changed bool, err error) {
	defer func() {
		if changed {
			scanChan <- item.Name
		}
	}()

	if !hasItem || item.Deleted {
		// The item appeared from nowhere
		return true, nil
	}

	// Check that the item on disk is what we expect it to be according
	// to the database. If there's a mismatch here, there might be local
	// changes that we don't know about yet and we should scan before
	// touching the item.
	statItem, err := scanner.CreateFileInfo(stat, item.Name, f.fs)
	if err != nil {
		return false, errors.Wrap(err, "comparing item on disk to db")
	}

	return !statItem.IsEquivalentOptional(item, f.IgnorePerms, true, protocol.LocalAllFlags), nil
}

// checkToBeDeleted makes sure the file on disk is compatible with what there is
// in the DB before the caller proceeds with actually deleting it.