From 2d00523609def535588b693a00d4092768e1c3c6 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 10 May 2016 15:00:19 -0400 Subject: [PATCH] In the unusual configuration where annex.crippledfilesystem=true but core.symlinks=true, store object contents in mixed case hash directories so that symlinks will point to them. Contents are searched for in both locations, same as before, so this does not add any overhead. --- Annex/Locations.hs | 35 ++++++++++--------- debian/changelog | 3 ++ ..._e5a152cef3c48ef05cb183907377f128._comment | 24 +++++++++++++ 3 files changed, 46 insertions(+), 16 deletions(-) create mode 100644 doc/forum/Wrong_symlink_target_on_usb_drive/comment_5_e5a152cef3c48ef05cb183907377f128._comment diff --git a/Annex/Locations.hs b/Annex/Locations.hs index 52753fca87..bdd603d945 100644 --- a/Annex/Locations.hs +++ b/Annex/Locations.hs @@ -137,25 +137,28 @@ gitAnnexLocationDepth config = hashlevels + 1 - the actual location of the file's content. -} gitAnnexLocation :: Key -> Git.Repo -> GitConfig -> IO FilePath -gitAnnexLocation key r config = gitAnnexLocation' key r config (annexCrippledFileSystem config) doesFileExist (Git.localGitDir r) -gitAnnexLocation' :: Key -> Git.Repo -> GitConfig -> Bool -> (FilePath -> IO Bool) -> FilePath -> IO FilePath -gitAnnexLocation' key r config crippled checker gitdir +gitAnnexLocation key r config = gitAnnexLocation' key r config (annexCrippledFileSystem config) (coreSymlinks config) doesFileExist (Git.localGitDir r) +gitAnnexLocation' :: Key -> Git.Repo -> GitConfig -> Bool -> Bool -> (FilePath -> IO Bool) -> FilePath -> IO FilePath +gitAnnexLocation' key r config crippled symlinkssupported checker gitdir {- Bare repositories default to hashDirLower for new - - content, as it's more portable. - - - - Repositories on filesystems that are crippled also use - - hashDirLower, since they do not use symlinks and it's - - more portable. - -} - | Git.repoIsLocalBare r || crippled = - check $ map inrepo $ annexLocations config key - | hasDifference ObjectHashLower (annexDifferences config) = - return $ inrepo $ annexLocation config key hashDirLower - {- Non-bare repositories only use hashDirMixed, so + - content, as it's more portable. But check all locations. -} + | Git.repoIsLocalBare r = checkall + | hasDifference ObjectHashLower (annexDifferences config) = + only hashDirLower + {- Repositories on crippled filesystems use hashDirLower + - for new content, unless symlinks are supported too. + - Then hashDirMixed is used. But, the content could be + - in either location so check both. -} + | symlinkssupported = check $ map inrepo $ reverse $ annexLocations config key + | crippled = checkall + {- Regular repositories only use hashDirMixed, so - don't need to do any work to check if the file is - present. -} - | otherwise = return $ inrepo $ annexLocation config key hashDirMixed + | otherwise = only hashDirMixed where + only = return . inrepo . annexLocation config key + checkall = check $ map inrepo $ annexLocations config key + inrepo d = gitdir d check locs@(l:_) = fromMaybe l <$> firstM checker locs check [] = error "internal" @@ -166,7 +169,7 @@ gitAnnexLink file key r config = do currdir <- getCurrentDirectory let absfile = fromMaybe whoops $ absNormPathUnix currdir file let gitdir = getgitdir currdir - loc <- gitAnnexLocation' key r config False (\_ -> return True) gitdir + loc <- gitAnnexLocation' key r config False False (\_ -> return True) gitdir toInternalGitPath <$> relPathDirToFile (parentDir absfile) loc where getgitdir currdir diff --git a/debian/changelog b/debian/changelog index 6a031b7e87..4381f58105 100644 --- a/debian/changelog +++ b/debian/changelog @@ -25,6 +25,9 @@ git-annex (6.20160420) UNRELEASED; urgency=medium when it's decrypting data. * fsck: When a key is not previously known in the location log, record something so that reinject --known will work. + * In the unusual configuration where annex.crippledfilesystem=true but + core.symlinks=true, store object contents in mixed case hash + directories so that symlinks will point to them. -- Joey Hess Thu, 28 Apr 2016 13:17:04 -0400 diff --git a/doc/forum/Wrong_symlink_target_on_usb_drive/comment_5_e5a152cef3c48ef05cb183907377f128._comment b/doc/forum/Wrong_symlink_target_on_usb_drive/comment_5_e5a152cef3c48ef05cb183907377f128._comment new file mode 100644 index 0000000000..8a5dd5530d --- /dev/null +++ b/doc/forum/Wrong_symlink_target_on_usb_drive/comment_5_e5a152cef3c48ef05cb183907377f128._comment @@ -0,0 +1,24 @@ +[[!comment format=mdwn + username="joey" + subject="""comment 5""" + date="2016-05-10T18:08:10Z" + content=""" +Ok, I reproduced the problem. Normally core.symlinks will be false +by on NTFS. You have to manually set it to true to experience +this problem AFAICS. + +I was able to lock a file (resulting in a broken symlink) and then successfully +unlock it and the content was back in place. + +git-annex always uses the lower case hash directory names when on a +crippled filesystem, since that's more portable and avoids lots of +potential problems. By configuring core.symlinks=true, you make git-annex +support locking files using symlinks, but these symlinks can't point to the +actual content location. + +I think it makes sense for git-annex to use the the mixed case hash +directory names when core.symlinks=true even if the filesystem is crippled. +There's some foot-shooting potential, since some crippled fileystems +don't support the mixed-case hash directories. But, you have to manually +set up this configuration. I've made a change along these lines. +"""]]