There are at least three problems with using git-annex
on /sdcard
on Android, or on a FAT filesystem, or on (to a first
approximation) Windows:
- symlinks
- hard links
- unix permissions
So, I've added an annex.crippledfilesystem
setting. git annex init
now
probes to see if all three are supported, and if not, enables that, as well
as direct mode.
In crippled filesystem mode, all the permissions settings are skipped. Most of them are only used to lock down content in the annex in indirect mode anyway, so no great loss.
There are several uses of hard links, most of which can be dealt with by making copies. The one use of permissions and hard links I absolutely needed to deal with was that they're used to lock down a file as it's being ingested into the annex. That can't be done on crippled filesystems, so I made it instead check the metadata of the file before and after to detect if it changed, the same way direct mode detects when files are modified. This is likely better than the old method anyway.
The other reason files are hardlinked while they're being ingested is that this allows running lsof on a single directory of files that are in the process of being added, to detect if anything has them open for write. I still need to adjust the lsof check to work in crippled filesystem mode. It seems this won't make it much slower to run lsof on the whole repository.
At this point, I can use git-annex with a repository on /sdcard
or a FAT
filesystem, and at least git annex add
works.
Still several things on the TODO list before crippled filesystem mode is
complete. The only one I'm scared about is making git merge
do something
sane when it wants to merge two trees full of symlinks, and the filesystem
doesn't let it create a symlink..
Windows supports hardlinks on NTFS filesystems. Not sure about the privileges needed; I think all users can create them.
Recent versions also support symlinks, but that's limited to Administrators by default, so Cygwin-Git (like the rest of Cygwin) uses special files with the "system" flag.
As far as I know, Git does not try to dereference symlinks when merging – it only tracks the paths they point to. Where symlinks are not supported (e.g. vfat filesystems in general, or msysGit on Windows) it simply creates regular files containing the target path (i.e. the raw contents of the respective blobs).
Regarding the use of Unix permissions: The "open file" syscall on Windows has a "share mode" flag, which can be used to disallow other programs from opening the file for writing (and/or even reading) as long as git-annex keeps it open. (I guess this is similar to mandatory locks in Linux.)