summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG4
-rw-r--r--Git/CurrentRepo.hs21
-rw-r--r--doc/bugs/add_fails_with_v6_repo_when_four_levels_deep.mdwn2
-rw-r--r--doc/bugs/add_fails_with_v6_repo_when_four_levels_deep/comment_12_d54f9cd6470cbaf6f066513e6fc66f69._comment80
4 files changed, 103 insertions, 4 deletions
diff --git a/CHANGELOG b/CHANGELOG
index e9d3906655..26136ff194 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -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.
+"""]]