diff options
-rw-r--r-- | CHANGELOG | 4 | ||||
-rw-r--r-- | Git/CurrentRepo.hs | 21 | ||||
-rw-r--r-- | doc/bugs/add_fails_with_v6_repo_when_four_levels_deep.mdwn | 2 | ||||
-rw-r--r-- | doc/bugs/add_fails_with_v6_repo_when_four_levels_deep/comment_12_d54f9cd6470cbaf6f066513e6fc66f69._comment | 80 |
4 files changed, 103 insertions, 4 deletions
@@ -19,6 +19,10 @@ git-annex (6.20180627) UNRELEASED; urgency=medium * unused --from: Allow specifiying a repository by uuid or description. * Send User-Agent and any configured annex.http-headers when downloading with http, fixes reversion introduced when switching to http-client. + * Work around git bug that runs smudge/clean filters at the top of the + repository while passing them a relative GIT_WORK_TREE that may point + outside of the repository, by using GIT_PREFIX to get back to the + subdirectory where a relative GIT_WORK_TREE is valid. -- Joey Hess <id@joeyh.name> Fri, 22 Jun 2018 10:36:22 -0400 diff --git a/Git/CurrentRepo.hs b/Git/CurrentRepo.hs index df074cf8bf..2eca12fa4b 100644 --- a/Git/CurrentRepo.hs +++ b/Git/CurrentRepo.hs @@ -25,12 +25,20 @@ import Utility.Env.Set - directory if necessary to ensure it is within the repository's work - tree. While not needed for git commands, this is useful for anything - else that looks for files in the worktree. + - + - Also works around a git bug when running some hooks. It + - runs the hooks in the top of the repository, but if GIT_WORK_TREE + - was relative, it then points to the wrong directory. In this situation + - GIT_PREFIX contains the directory that GIT_WORK_TREE (and GIT_DIR) + - are relative to. -} get :: IO Repo get = do - gd <- pathenv "GIT_DIR" + prefix <- getpathenv "GIT_PREFIX" + gd <- pathenv "GIT_DIR" prefix r <- configure gd =<< fromCwd - wt <- maybe (worktree $ location r) Just <$> pathenv "GIT_WORK_TREE" + wt <- maybe (worktree $ location r) Just + <$> pathenv "GIT_WORK_TREE" prefix case wt of Nothing -> return r Just d -> do @@ -39,13 +47,18 @@ get = do setCurrentDirectory d return $ addworktree wt r where - pathenv s = do + getpathenv s = do v <- getEnv s case v of Just d -> do unsetEnv s - Just <$> absPath d + return (Just d) Nothing -> return Nothing + + pathenv s Nothing = getpathenv s + pathenv s (Just prefix) = getpathenv s >>= \case + Nothing -> return Nothing + Just d -> Just <$> absPath (prefix </> d) configure Nothing (Just r) = Git.Config.read r configure (Just d) _ = do diff --git a/doc/bugs/add_fails_with_v6_repo_when_four_levels_deep.mdwn b/doc/bugs/add_fails_with_v6_repo_when_four_levels_deep.mdwn index da246cda17..34798dc2d1 100644 --- a/doc/bugs/add_fails_with_v6_repo_when_four_levels_deep.mdwn +++ b/doc/bugs/add_fails_with_v6_repo_when_four_levels_deep.mdwn @@ -134,3 +134,5 @@ ok ### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders) I've been happily using git-annex on my laptop and server for almost a year; it's saved me a great deal of time and effort. Thanks for all your work! + +> [[fixed|done]] finally... --[[Joey]] diff --git a/doc/bugs/add_fails_with_v6_repo_when_four_levels_deep/comment_12_d54f9cd6470cbaf6f066513e6fc66f69._comment b/doc/bugs/add_fails_with_v6_repo_when_four_levels_deep/comment_12_d54f9cd6470cbaf6f066513e6fc66f69._comment new file mode 100644 index 0000000000..924e0a4c0b --- /dev/null +++ b/doc/bugs/add_fails_with_v6_repo_when_four_levels_deep/comment_12_d54f9cd6470cbaf6f066513e6fc66f69._comment @@ -0,0 +1,80 @@ +[[!comment format=mdwn + username="joey" + subject="""comment 12""" + date="2018-07-17T15:52:47Z" + content=""" +Reproduced this today. ext4, git 2.18.0, git-annex 6.20180627-gbd6799ebe. +In an adjusted unlocked v6 repository. + +Running git annex add in 1/2/3/4/5/6/ failed, I then cd'd down to the top +of the repository, and it worked there. + +The bug seems to be intermittent; I was then not able to reproduce it for +a while, and now can again. + + joey@darkstar:~/tmp/t2/1/2/3/4/5/6#master(unlocked)>git annex add meow --debug + [2018-07-17 12:15:35.536935635] read: git ["--git-dir=../../../../../../.git","--work-tree=../../../../../..","--literal-pathspecs","ls-files","--others","--exclude-standard","-z","--","meow"] + [2018-07-17 12:15:35.542108221] read: git ["--git-dir=../../../../../../.git","--work-tree=../../../../../..","--literal-pathspecs","ls-files","--modified","-z","--","meow"] + git-annex: 1/2/3/4/5/6/meow: getFileStatus: does not exist (No such file or directory) + git-annex: smudge: 1 failed + error: external filter 'git-annex smudge --clean %f' failed 1 + error: external filter 'git-annex smudge --clean %f' failed + +This is git ls-files running the smudge filter which then fails: + + joey@darkstar:~/tmp/t2/1/2/3/4/5/6#master(unlocked)>GIT_TRACE=1 git + --git-dir=../../../../../../.git --work-tree=../../../../../.. + --literal-pathspecs ls-files --modified + + 12:19:49.691639 git.c:415 trace: built-in: git ls-files --modified + 12:19:49.692166 run-command.c:637 trace: run_command: 'git-annex smudge --clean '\''1/2/3/4/5/6/meow'\''' + 12:19:49.700739 git.c:415 trace: built-in: git config --null --list + 12:19:49.704813 git.c:415 trace: built-in: git check-attr -z --stdin annex.backend annex.numcopies annex.largefiles -- + 12:19:49.705020 git.c:415 trace: built-in: git version + 12:19:49.707887 git.c:415 trace: built-in: git cat-file --batch + 12:19:49.707880 git.c:415 trace: built-in: git cat-file '--batch-check=%(objectname) %(objecttype) %(objectsize)' + git-annex: 1/2/3/4/5/6/meow: getFileStatus: does not exist (No such file or directory) + git-annex: smudge: 1 failed + +Note that the smudge filter is being passed the path from the top of the +repo to the file, despite being in the same directory as the file. +Same thing happens during a successful add though, so why is it +failing to process the filename here? Maybe git is normally running +the smudge filter with cwd in the top of the repo, but when this occurs +it's elsewhere? No, I checked and the smudge filter is always being run +at the top of the repository. + +Huh! It's somehow caused by the way that the path to the work-tree is +specified. + + joey@darkstar:~/tmp/t2/1/2/3/4/5/6#master(unlocked)>GIT_TRACE=1 git --work-tree=/home/joey/tmp/t2 --literal-pathspecs ls-files --modified12:32:34.639710 git.c:415 trace: built-in: git ls-files --modified + 12:32:34.640571 run-command.c:637 trace: run_command: 'git-annex smudge --clean '\''1/2/3/4/5/6/meow'\''' + # succeeds no error + +That's two different ways to specifiy the same path, one succeeds and one +fails. + +Hmm.. when git runs the smudge filter, pwd is the top of the repository +and `GIT_WORK_TREE=../../../../../..` +So the work tree in this case points outside the repository, +indeed it points to `/`. I guess this is why the smudge filter is +failing, since it's not finding the file in that wrong worktree. + +This is absolutely a bug in git, I posted to the git mailing list +in message-id 20180717165834.GA5615@kitenet.net about it. + +But why does this only happen sometimes? Well, running `git add` +in a subdirectory does not pass `GIT_WORK_TREE`, because none +was specified. So, the problem does not occur then. +When git-annex runs a git command such as ls-files --modified and passes +a relative work tree, the problem also sometimes doesn't occur. +Sometimes git doesn't need to run the smudge filter +(touching the file makes it need to). +I think it may have to do with the number of subdirectories somehow as +well. + +Since git 1.7.6, `GIT_PREFIX` is set when it runs these filters, +and it contains the path to the subdirectory of the working tree that +it was originally run in. So, git-annex can work around the +problem using that. Done. +"""]] |