It seems that performing git annex adjust --unlock-present
or sync
will remove the +x permission from files.
Steps to reproduce:
$ mkdir /tmp/ga; cd /tmp/ga; git init ; git annex init $ touch a.txt s.sh $ chmod +x s.sh $ git annex add . && git annex sync $ stat -Lc%A s.sh -r-xr-xr-x $ git annex adjust --unlock-present $ stat -c%A s.sh -rw-r--r--
The permission is removed also after a sync, but only in case other files have been changed (and adjust called behind the scenes):
$ chmod +x s.sh $ git annex sync $ stat -c%A s.sh -rwxr-xr-x $ git annex drop --force a.txt $ stat -c%A s.sh -rwxr-xr-x $ git annex sync $ stat -c%A s.sh -rw-r--r--
I'm using git-annex version: 10.20240430-g5b36e6b4 with annex.alwayscommit = false.
PS: git-annex is so solid that this is the first data-related issue I've ever seen. Kudos!
Notice that
git-annex unlock
does preserve the execute bit when the object file has it set.Currently, generating an adjusted branch does not look at permissions of object files.
Now git-annex generally does not preserve execute bit on object files (eg when storing in a special remote), and of course doesn't know the permissions of an object file that's not currently present. So, if adjusted branch generation did look at the permissions, running it twice in two different repositories, or at different times in the same repository could result in different adjusted branch trees being generated.
That might or might not be a problem for interoperability? Adjusted branches are not usually pushed anywhere, so might not matter much.
It seems that in
instance AdjustTreeItem LinkAdjustment
it would no longer be able to haveadjustmentIsStable
return True. Well, it could, but thengit-annex adjust --unlock
followed bygit-annex get foo
when it happens to get an object with the execute bit, followed bygit-annex adjust --unlock
would not reflect the execute bit in the adjusted branch.So handling that case matters, re-adjusting would get slower. This might impact users who have a large tree they are adjusting with --unlock. (
git-annex adjust --unlock-present
is already not stable of course, so no additional performance penalty there)Of course, statting every object file to check for execute bits would also make adjusting a large tree somewhat slower. Probably on the order of less than 10% slower I'd guess, because it currently has to catKey, which is slower than stat.
Overall, I think this is probably worth doing, just to be symmetric with
git-annex unlock
.There's also an argument that, if I have a large executable (LLM models come to mind for some ungodly reason), and I annex it and enter an adjusted branch, I should still be able to run it. Although it's really better to add it unlocked in the first place, since then you're tracking the execute bit in git permanantly and not relying on best-effort execute bit preservation when copying objects around.
If the object file is executable at
git-annex unlock
time, the pointer file is made executable. If the object is then dropped, the pointer file remains executable.So shouldn't it be the case for symmetry that
git-annex adjust --unlock
should make the pointer file executable, and a drop followed by re-doing the same adjustment should leave the pointer file executable? That would argue for leaving it stable.I don't think there's a perfect solution to that question, both behaviors seem perhaps wanted at different times. But since leaving it stable avoids extra work, I'm leaning toward that.