[v0.7.2] Directory syncing

Prior to v0.7.2, syncthing doesn’t know or care much about directories. When syncing files it makes sure to create the parent directory on the destination if it doesn’t exist, that’s all. Fixing this so that the existance, modification time and permission bits of directories were synced was nontrivial in the old design. The difficulty was mostly that scanning for modifications could happen concurrently with making modifications, so we could never be sure if a change to a directory was done by the user or by us.

In v0.7.0 the update mechanism was changed to a loop that

  1. checks for needed changes and performs them
  2. scans for changes made by the user

which makes it possible to insert a directory syncing step between steps one and two.

The new directory syncing is in three parts. Part one is trivial, simply that the file scanner now also records the state of directories it finds instead of just files.

Part two is in the change puller, where we update local files to the cluster state. If the change is to a directory and it doesn’t exist, we create it. Part three is the directory syncing step as alluded to above. In this step we scan the local repository on disk. For each directory,

  1. If the permissions bits differ from the cluster state, update them.
  2. If the modification time differs from the cluster state, restore it.
  3. If the directory has been deleted in the cluster, delete it. If there were files in it, those should have been removed at the file syncing previously.

After this step we’ll have created any new directories, fixed the modification time and permission for all directories and removed those which are no longer in the cluster. Back to the holding pattern of looking for local changes and waiting for changes from the cluster.

Caveats;

It’s possible that syncthing makes a change to a directory (say, updates a file that changed on another node) and the user does something to that directory at the same time. We can’t know this happened so we’ll restore the modification time and permission bits as dictated by the cluster anyway. This race condition should be rare and I don’t think we can solve it reliably.