Use lower case hash directories for storing files on crippled filesystems, same as is already done for bare repositories.

* since this is a crippled filesystem anyway, git-annex doesn't use
  symlinks on it
* so there's no reason to use the mixed case hash directories that we're
  stuck using to avoid breaking everyone's symlinks to the content
* so we can do what is already done for all bare repos, and make non-bare
  repos on crippled filesystems use the all-lower case hash directories
* which are, happily, all 3 letters long, so they cannot conflict with
  mixed case hash directories
* so I was able to 100% fix this and even resuming `git annex add` in the
  test case will recover and it will all just work.
This commit is contained in:
Joey Hess 2013-04-04 15:46:33 -04:00
parent c20143ee32
commit f1b0a4b404
22 changed files with 90 additions and 70 deletions

View file

@ -28,6 +28,7 @@ module Annex (
gitRepo, gitRepo,
inRepo, inRepo,
fromRepo, fromRepo,
calcRepo,
getGitConfig, getGitConfig,
changeGitConfig, changeGitConfig,
changeGitRepo, changeGitRepo,
@ -203,6 +204,11 @@ inRepo a = liftIO . a =<< gitRepo
fromRepo :: (Git.Repo -> a) -> Annex a fromRepo :: (Git.Repo -> a) -> Annex a
fromRepo a = a <$> gitRepo fromRepo a = a <$> gitRepo
calcRepo :: (Git.Repo -> GitConfig -> IO a) -> Annex a
calcRepo a = do
s <- getState id
liftIO $ a (repo s) (gitconfig s)
{- Gets the GitConfig settings. -} {- Gets the GitConfig settings. -}
getGitConfig :: Annex GitConfig getGitConfig :: Annex GitConfig
getGitConfig = getState gitconfig getGitConfig = getState gitconfig

View file

@ -9,7 +9,6 @@ module Annex.Content (
inAnnex, inAnnex,
inAnnexSafe, inAnnexSafe,
lockContent, lockContent,
calcGitLink,
getViaTmp, getViaTmp,
getViaTmpChecked, getViaTmpChecked,
getViaTmpUnchecked, getViaTmpUnchecked,
@ -101,7 +100,7 @@ inAnnexSafe = inAnnex' (fromMaybe False) (Just False) go
- it. (If the content is not present, no locking is done.) -} - it. (If the content is not present, no locking is done.) -}
lockContent :: Key -> Annex a -> Annex a lockContent :: Key -> Annex a -> Annex a
lockContent key a = do lockContent key a = do
file <- inRepo $ gitAnnexLocation key file <- calcRepo $ gitAnnexLocation key
bracketIO (openforlock file >>= lock) unlock a bracketIO (openforlock file >>= lock) unlock a
where where
{- Since files are stored with the write bit disabled, have {- Since files are stored with the write bit disabled, have
@ -123,16 +122,6 @@ lockContent key a = do
unlock Nothing = noop unlock Nothing = noop
unlock (Just l) = closeFd l unlock (Just l) = closeFd l
{- Calculates the relative path to use to link a file to a key. -}
calcGitLink :: FilePath -> Key -> Annex FilePath
calcGitLink file key = do
cwd <- liftIO getCurrentDirectory
let absfile = fromMaybe whoops $ absNormPath cwd file
loc <- inRepo $ gitAnnexLocation key
return $ relPathDirToFile (parentDir absfile) loc
where
whoops = error $ "unable to normalize " ++ file
{- Runs an action, passing it a temporary filename to get, {- Runs an action, passing it a temporary filename to get,
- and if the action succeeds, moves the temp file into - and if the action succeeds, moves the temp file into
- the annex as a key's content. -} - the annex as a key's content. -}
@ -251,7 +240,7 @@ moveAnnex key src = withObjectLoc key storeobject storedirect
storedirect fs = storedirect' =<< filterM validsymlink fs storedirect fs = storedirect' =<< filterM validsymlink fs
validsymlink f = (==) (Just key) <$> isAnnexLink f validsymlink f = (==) (Just key) <$> isAnnexLink f
storedirect' [] = storeobject =<< inRepo (gitAnnexLocation key) storedirect' [] = storeobject =<< calcRepo (gitAnnexLocation key)
storedirect' (dest:fs) = do storedirect' (dest:fs) = do
updateInodeCache key src updateInodeCache key src
thawContent src thawContent src
@ -341,11 +330,11 @@ withObjectLoc key indirect direct = ifM isDirect
, goindirect , goindirect
) )
where where
goindirect = indirect =<< inRepo (gitAnnexLocation key) goindirect = indirect =<< calcRepo (gitAnnexLocation key)
cleanObjectLoc :: Key -> Annex () cleanObjectLoc :: Key -> Annex ()
cleanObjectLoc key = do cleanObjectLoc key = do
file <- inRepo $ gitAnnexLocation key file <- calcRepo $ gitAnnexLocation key
unlessM crippledFileSystem $ unlessM crippledFileSystem $
void $ liftIO $ catchMaybeIO $ allowWrite $ parentDir file void $ liftIO $ catchMaybeIO $ allowWrite $ parentDir file
liftIO $ removeparents file (3 :: Int) liftIO $ removeparents file (3 :: Int)
@ -374,7 +363,7 @@ removeAnnex key = withObjectLoc key remove removedirect
removeInodeCache key removeInodeCache key
mapM_ (resetfile cache) fs mapM_ (resetfile cache) fs
resetfile cache f = whenM (sameInodeCache f cache) $ do resetfile cache f = whenM (sameInodeCache f cache) $ do
l <- calcGitLink f key l <- inRepo $ gitAnnexLink f key
top <- fromRepo Git.repoPath top <- fromRepo Git.repoPath
cwd <- liftIO getCurrentDirectory cwd <- liftIO getCurrentDirectory
let top' = fromMaybe top $ absNormPath cwd top let top' = fromMaybe top $ absNormPath cwd top
@ -384,7 +373,7 @@ removeAnnex key = withObjectLoc key remove removedirect
{- Moves a key's file out of .git/annex/objects/ -} {- Moves a key's file out of .git/annex/objects/ -}
fromAnnex :: Key -> FilePath -> Annex () fromAnnex :: Key -> FilePath -> Annex ()
fromAnnex key dest = do fromAnnex key dest = do
file <- inRepo $ gitAnnexLocation key file <- calcRepo $ gitAnnexLocation key
unlessM crippledFileSystem $ unlessM crippledFileSystem $
liftIO $ allowWrite $ parentDir file liftIO $ allowWrite $ parentDir file
thawContent file thawContent file
@ -395,7 +384,7 @@ fromAnnex key dest = do
- returns the file it was moved to. -} - returns the file it was moved to. -}
moveBad :: Key -> Annex FilePath moveBad :: Key -> Annex FilePath
moveBad key = do moveBad key = do
src <- inRepo $ gitAnnexLocation key src <- calcRepo $ gitAnnexLocation key
bad <- fromRepo gitAnnexBadDir bad <- fromRepo gitAnnexBadDir
let dest = bad </> takeFileName src let dest = bad </> takeFileName src
createAnnexDirectory (parentDir dest) createAnnexDirectory (parentDir dest)
@ -468,7 +457,7 @@ preseedTmp key file = go =<< inAnnex key
copy = ifM (liftIO $ doesFileExist file) copy = ifM (liftIO $ doesFileExist file)
( return True ( return True
, do , do
s <- inRepo $ gitAnnexLocation key s <- calcRepo $ gitAnnexLocation key
liftIO $ copyFileExternal s file liftIO $ copyFileExternal s file
) )

View file

@ -42,7 +42,7 @@ associatedFiles key = do
- the top of the repo. -} - the top of the repo. -}
associatedFilesRelative :: Key -> Annex [FilePath] associatedFilesRelative :: Key -> Annex [FilePath]
associatedFilesRelative key = do associatedFilesRelative key = do
mapping <- inRepo $ gitAnnexMapping key mapping <- calcRepo $ gitAnnexMapping key
liftIO $ catchDefaultIO [] $ do liftIO $ catchDefaultIO [] $ do
h <- openFile mapping ReadMode h <- openFile mapping ReadMode
fileEncoding h fileEncoding h
@ -52,7 +52,7 @@ associatedFilesRelative key = do
- transformation to the list. Returns new associatedFiles value. -} - transformation to the list. Returns new associatedFiles value. -}
changeAssociatedFiles :: Key -> ([FilePath] -> [FilePath]) -> Annex [FilePath] changeAssociatedFiles :: Key -> ([FilePath] -> [FilePath]) -> Annex [FilePath]
changeAssociatedFiles key transform = do changeAssociatedFiles key transform = do
mapping <- inRepo $ gitAnnexMapping key mapping <- calcRepo $ gitAnnexMapping key
files <- associatedFilesRelative key files <- associatedFilesRelative key
let files' = transform files let files' = transform files
when (files /= files') $ do when (files /= files') $ do
@ -124,7 +124,7 @@ removeInodeCache key = withInodeCacheFile key $ \f -> do
liftIO $ nukeFile f liftIO $ nukeFile f
withInodeCacheFile :: Key -> (FilePath -> Annex a) -> Annex a withInodeCacheFile :: Key -> (FilePath -> Annex a) -> Annex a
withInodeCacheFile key a = a =<< inRepo (gitAnnexInodeCache key) withInodeCacheFile key a = a =<< calcRepo (gitAnnexInodeCache key)
{- Checks if a InodeCache matches the current version of a file. -} {- Checks if a InodeCache matches the current version of a file. -}
sameInodeCache :: FilePath -> Maybe InodeCache -> Annex Bool sameInodeCache :: FilePath -> Maybe InodeCache -> Annex Bool

View file

@ -89,7 +89,8 @@ addDirect file cache = do
return False return False
got (Just (key, _)) = ifM (sameInodeCache file $ Just cache) got (Just (key, _)) = ifM (sameInodeCache file $ Just cache)
( do ( do
stageSymlink file =<< hashSymlink =<< calcGitLink file key l <- inRepo $ gitAnnexLink file key
stageSymlink file =<< hashSymlink l
writeInodeCache key cache writeInodeCache key cache
void $ addAssociatedFile key file void $ addAssociatedFile key file
logStatus key InfoPresent logStatus key InfoPresent
@ -152,7 +153,7 @@ mergeDirectCleanup d oldsha newsha = do
- -
- Symlinks are replaced with their content, if it's available. -} - Symlinks are replaced with their content, if it's available. -}
movein k f = do movein k f = do
l <- calcGitLink f k l <- inRepo $ gitAnnexLink f k
replaceFile f $ makeAnnexLink l replaceFile f $ makeAnnexLink l
toDirect k f toDirect k f
@ -169,7 +170,7 @@ toDirect k f = fromMaybe noop =<< toDirectGen k f
toDirectGen :: Key -> FilePath -> Annex (Maybe (Annex ())) toDirectGen :: Key -> FilePath -> Annex (Maybe (Annex ()))
toDirectGen k f = do toDirectGen k f = do
loc <- inRepo $ gitAnnexLocation k loc <- calcRepo $ gitAnnexLocation k
absf <- liftIO $ absPath f absf <- liftIO $ absPath f
locs <- filter (/= absf) <$> addAssociatedFile k f locs <- filter (/= absf) <$> addAssociatedFile k f
case locs of case locs of

View file

@ -312,7 +312,7 @@ handleAdds delayadd cs = returnWhen (null incomplete) $ do
done change file key = liftAnnex $ do done change file key = liftAnnex $ do
logStatus key InfoPresent logStatus key InfoPresent
link <- ifM isDirect link <- ifM isDirect
( calcGitLink file key ( inRepo $ gitAnnexLink file key
, Command.Add.link file key True , Command.Add.link file key True
) )
whenM (pure DirWatcher.eventsCoalesce <||> isDirect) $ do whenM (pure DirWatcher.eventsCoalesce <||> isDirect) $ do

View file

@ -201,7 +201,7 @@ onAddDirect matcher file fs = do
- just been deleted and been put back, - just been deleted and been put back,
- so it symlink is restaged to make sure. -} - so it symlink is restaged to make sure. -}
( do ( do
link <- liftAnnex $ calcGitLink file key link <- liftAnnex $ inRepo $ gitAnnexLink file key
addLink file link (Just key) addLink file link (Just key)
, do , do
debug ["changed direct", file] debug ["changed direct", file]
@ -222,7 +222,7 @@ onAddSymlink isdirect file filestatus = go =<< liftAnnex (Backend.lookupFile fil
go (Just (key, _)) = do go (Just (key, _)) = do
when isdirect $ when isdirect $
liftAnnex $ void $ addAssociatedFile key file liftAnnex $ void $ addAssociatedFile key file
link <- liftAnnex $ calcGitLink file key link <- liftAnnex $ inRepo $ gitAnnexLink file key
ifM ((==) (Just link) <$> liftIO (catchMaybeIO $ readSymbolicLink file)) ifM ((==) (Just link) <$> liftIO (catchMaybeIO $ readSymbolicLink file))
( ensurestaged (Just link) (Just key) =<< getDaemonStatus ( ensurestaged (Just link) (Just key) =<< getDaemonStatus
, do , do

View file

@ -168,13 +168,13 @@ undo file key e = do
-- fromAnnex could fail if the file ownership is weird -- fromAnnex could fail if the file ownership is weird
tryharder :: IOException -> Annex () tryharder :: IOException -> Annex ()
tryharder _ = do tryharder _ = do
src <- inRepo $ gitAnnexLocation key src <- calcRepo $ gitAnnexLocation key
liftIO $ moveFile src file liftIO $ moveFile src file
{- Creates the symlink to the annexed content, returns the link target. -} {- Creates the symlink to the annexed content, returns the link target. -}
link :: FilePath -> Key -> Bool -> Annex String link :: FilePath -> Key -> Bool -> Annex String
link file key hascontent = handle (undo file key) $ do link file key hascontent = handle (undo file key) $ do
l <- calcGitLink file key l <- inRepo $ gitAnnexLink file key
replaceFile file $ makeAnnexLink l replaceFile file $ makeAnnexLink l
#ifndef __ANDROID__ #ifndef __ANDROID__
@ -206,7 +206,9 @@ cleanup file key hascontent = do
when hascontent $ when hascontent $
logStatus key InfoPresent logStatus key InfoPresent
ifM (isDirect <&&> pure hascontent) ifM (isDirect <&&> pure hascontent)
( stageSymlink file =<< hashSymlink =<< calcGitLink file key ( do
l <- inRepo $ gitAnnexLink file key
stageSymlink file =<< hashSymlink l
, ifM (coreSymlinks <$> Annex.getGitConfig) , ifM (coreSymlinks <$> Annex.getGitConfig)
( do ( do
_ <- link file key hascontent _ <- link file key hascontent

View file

@ -10,7 +10,6 @@ module Command.Fix where
import Common.Annex import Common.Annex
import Command import Command
import qualified Annex.Queue import qualified Annex.Queue
import Annex.Content
def :: [Command] def :: [Command]
def = [notDirect $ noCommit $ command "fix" paramPaths seek def = [notDirect $ noCommit $ command "fix" paramPaths seek
@ -22,7 +21,7 @@ seek = [withFilesInGit $ whenAnnexed start]
{- Fixes the symlink to an annexed file. -} {- Fixes the symlink to an annexed file. -}
start :: FilePath -> (Key, Backend) -> CommandStart start :: FilePath -> (Key, Backend) -> CommandStart
start file (key, _) = do start file (key, _) = do
link <- calcGitLink file key link <- inRepo $ gitAnnexLink file key
stopUnless ((/=) (Just link) <$> liftIO (catchMaybeIO $ readSymbolicLink file)) $ do stopUnless ((/=) (Just link) <$> liftIO (catchMaybeIO $ readSymbolicLink file)) $ do
showStart "fix" file showStart "fix" file
next $ perform file link next $ perform file link

View file

@ -33,7 +33,7 @@ start _ = error "specify a key and a dest file"
perform :: Key -> FilePath -> CommandPerform perform :: Key -> FilePath -> CommandPerform
perform key file = do perform key file = do
link <- calcGitLink file key link <- inRepo $ gitAnnexLink file key
liftIO $ createDirectoryIfMissing True (parentDir file) liftIO $ createDirectoryIfMissing True (parentDir file)
liftIO $ createSymbolicLink link file liftIO $ createSymbolicLink link file
next $ cleanup file next $ cleanup file

View file

@ -188,7 +188,7 @@ check cs = all id <$> sequence cs
-} -}
fixLink :: Key -> FilePath -> Annex Bool fixLink :: Key -> FilePath -> Annex Bool
fixLink key file = do fixLink key file = do
want <- calcGitLink file key want <- inRepo $ gitAnnexLink file key
have <- getAnnexLinkTarget file have <- getAnnexLinkTarget file
maybe noop (go want) have maybe noop (go want) have
return True return True
@ -223,7 +223,7 @@ verifyLocationLog key desc = do
{- Since we're checking that a key's file is present, throw {- Since we're checking that a key's file is present, throw
- in a permission fixup here too. -} - in a permission fixup here too. -}
when (present && not direct) $ do when (present && not direct) $ do
file <- inRepo $ gitAnnexLocation key file <- calcRepo $ gitAnnexLocation key
freezeContent file freezeContent file
freezeContentDir file freezeContentDir file
@ -281,7 +281,7 @@ checkKeySize :: Key -> Annex Bool
checkKeySize key = ifM isDirect checkKeySize key = ifM isDirect
( return True ( return True
, do , do
file <- inRepo $ gitAnnexLocation key file <- calcRepo $ gitAnnexLocation key
ifM (liftIO $ doesFileExist file) ifM (liftIO $ doesFileExist file)
( checkKeySizeOr badContent key file ( checkKeySizeOr badContent key file
, return True , return True
@ -322,7 +322,7 @@ checkKeySizeOr bad key file = case Types.Key.keySize key of
-} -}
checkBackend :: Backend -> Key -> Annex Bool checkBackend :: Backend -> Key -> Annex Bool
checkBackend backend key = do checkBackend backend key = do
file <- inRepo $ gitAnnexLocation key file <- calcRepo $ gitAnnexLocation key
ifM isDirect ifM isDirect
( ifM (goodContent key file) ( ifM (goodContent key file)
( checkBackendOr' (badContentDirect file) backend key file ( checkBackendOr' (badContentDirect file) backend key file
@ -443,14 +443,14 @@ needFsck _ _ = return True
-} -}
recordFsckTime :: Key -> Annex () recordFsckTime :: Key -> Annex ()
recordFsckTime key = do recordFsckTime key = do
parent <- parentDir <$> inRepo (gitAnnexLocation key) parent <- parentDir <$> calcRepo (gitAnnexLocation key)
liftIO $ void $ tryIO $ do liftIO $ void $ tryIO $ do
touchFile parent touchFile parent
setSticky parent setSticky parent
getFsckTime :: Key -> Annex (Maybe EpochTime) getFsckTime :: Key -> Annex (Maybe EpochTime)
getFsckTime key = do getFsckTime key = do
parent <- parentDir <$> inRepo (gitAnnexLocation key) parent <- parentDir <$> calcRepo (gitAnnexLocation key)
liftIO $ catchDefaultIO Nothing $ do liftIO $ catchDefaultIO Nothing $ do
s <- getFileStatus parent s <- getFileStatus parent
return $ if isSticky $ fileMode s return $ if isSticky $ fileMode s

View file

@ -82,13 +82,13 @@ perform = do
cleandirect k -- clean before content directory gets frozen cleandirect k -- clean before content directory gets frozen
whenM (liftIO $ not . isSymbolicLink <$> getSymbolicLinkStatus f) $ do whenM (liftIO $ not . isSymbolicLink <$> getSymbolicLinkStatus f) $ do
moveAnnex k f moveAnnex k f
l <- calcGitLink f k l <- inRepo $ gitAnnexLink f k
liftIO $ createSymbolicLink l f liftIO $ createSymbolicLink l f
showEndOk showEndOk
cleandirect k = do cleandirect k = do
liftIO . nukeFile =<< inRepo (gitAnnexInodeCache k) liftIO . nukeFile =<< calcRepo (gitAnnexInodeCache k)
liftIO . nukeFile =<< inRepo (gitAnnexMapping k) liftIO . nukeFile =<< calcRepo (gitAnnexMapping k)
cleanup :: CommandCleanup cleanup :: CommandCleanup
cleanup = do cleanup = do

View file

@ -63,7 +63,7 @@ perform file oldkey oldbackend newbackend = do
go newkey = stopUnless (Command.ReKey.linkKey oldkey newkey) $ go newkey = stopUnless (Command.ReKey.linkKey oldkey newkey) $
next $ Command.ReKey.cleanup file oldkey newkey next $ Command.ReKey.cleanup file oldkey newkey
genkey = do genkey = do
content <- inRepo $ gitAnnexLocation oldkey content <- calcRepo $ gitAnnexLocation oldkey
let source = KeySource let source = KeySource
{ keyFilename = file { keyFilename = file
, contentLocation = content , contentLocation = content

View file

@ -49,7 +49,7 @@ perform file oldkey newkey = do
{- Make a hard link to the old key content, to avoid wasting disk space. -} {- Make a hard link to the old key content, to avoid wasting disk space. -}
linkKey :: Key -> Key -> Annex Bool linkKey :: Key -> Key -> Annex Bool
linkKey oldkey newkey = getViaTmpUnchecked newkey $ \tmp -> do linkKey oldkey newkey = getViaTmpUnchecked newkey $ \tmp -> do
src <- inRepo $ gitAnnexLocation oldkey src <- calcRepo $ gitAnnexLocation oldkey
ifM (liftIO $ doesFileExist tmp) ifM (liftIO $ doesFileExist tmp)
( return True ( return True
, ifM crippledFileSystem , ifM crippledFileSystem

View file

@ -14,7 +14,6 @@ import qualified Remote
import qualified Annex import qualified Annex
import qualified Annex.Branch import qualified Annex.Branch
import qualified Annex.Queue import qualified Annex.Queue
import Annex.Content
import Annex.Direct import Annex.Direct
import Annex.CatFile import Annex.CatFile
import Annex.Link import Annex.Link
@ -268,7 +267,7 @@ resolveMerge' u
[Just SymlinkBlob, Nothing] [Just SymlinkBlob, Nothing]
makelink (Just key) = do makelink (Just key) = do
let dest = mergeFile file key let dest = mergeFile file key
l <- calcGitLink dest key l <- inRepo $ gitAnnexLink dest key
liftIO $ nukeFile dest liftIO $ nukeFile dest
addAnnexLink l dest addAnnexLink l dest
whenM (isDirect) $ whenM (isDirect) $

View file

@ -60,7 +60,7 @@ cleanup file key = do
where where
goFast = do goFast = do
-- fast mode: hard link to content in annex -- fast mode: hard link to content in annex
src <- inRepo $ gitAnnexLocation key src <- calcRepo $ gitAnnexLocation key
-- creating a hard link could fall; fall back to non fast mode -- creating a hard link could fall; fall back to non fast mode
ifM (liftIO $ catchBoolIO $ createLink src file >> return True) ifM (liftIO $ catchBoolIO $ createLink src file >> return True)
( thawContent file ( thawContent file

View file

@ -35,7 +35,7 @@ perform dest key = do
unlessM (inAnnex key) $ error "content not present" unlessM (inAnnex key) $ error "content not present"
unlessM (checkDiskSpace Nothing key 0) $ error "cannot unlock" unlessM (checkDiskSpace Nothing key 0) $ error "cannot unlock"
src <- inRepo $ gitAnnexLocation key src <- calcRepo $ gitAnnexLocation key
tmpdest <- fromRepo $ gitAnnexTmpLocation key tmpdest <- fromRepo $ gitAnnexTmpLocation key
liftIO $ createDirectoryIfMissing True (parentDir tmpdest) liftIO $ createDirectoryIfMissing True (parentDir tmpdest)
showAction "copying" showAction "copying"

View file

@ -3,6 +3,6 @@ module Common.Annex (module X) where
import Common as X import Common as X
import Types as X import Types as X
import Types.UUID as X (toUUID, fromUUID) import Types.UUID as X (toUUID, fromUUID)
import Annex as X (gitRepo, inRepo, fromRepo) import Annex as X (gitRepo, inRepo, fromRepo, calcRepo)
import Locations as X import Locations as X
import Messages as X import Messages as X

View file

@ -11,6 +11,7 @@ module Locations (
keyPaths, keyPaths,
keyPath, keyPath,
gitAnnexLocation, gitAnnexLocation,
gitAnnexLink,
gitAnnexMapping, gitAnnexMapping,
gitAnnexInodeCache, gitAnnexInodeCache,
gitAnnexInodeSentinal, gitAnnexInodeSentinal,
@ -88,7 +89,7 @@ annexLocations key = map (annexLocation key) annexHashes
annexLocation :: Key -> Hasher -> FilePath annexLocation :: Key -> Hasher -> FilePath
annexLocation key hasher = objectDir </> keyPath key hasher annexLocation key hasher = objectDir </> keyPath key hasher
{- Annexed file's absolute location in a repository. {- Annexed object's absolute location in a repository.
- -
- When there are multiple possible locations, returns the one where the - When there are multiple possible locations, returns the one where the
- file is actually present. - file is actually present.
@ -99,35 +100,50 @@ annexLocation key hasher = objectDir </> keyPath key hasher
- This does not take direct mode into account, so in direct mode it is not - This does not take direct mode into account, so in direct mode it is not
- the actual location of the file's content. - the actual location of the file's content.
-} -}
gitAnnexLocation :: Key -> Git.Repo -> IO FilePath gitAnnexLocation :: Key -> Git.Repo -> GitConfig -> IO FilePath
gitAnnexLocation key r gitAnnexLocation key r config = gitAnnexLocation' key r (annexCrippledFileSystem config)
| Git.repoIsLocalBare r = gitAnnexLocation' :: Key -> Git.Repo -> Bool -> IO FilePath
{- Bare repositories default to hashDirLower for new gitAnnexLocation' key r crippled
- content, as it's more portable. -} {- 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 key check $ map inrepo $ annexLocations key
| otherwise = {- Non-bare repositories only use hashDirMixed, so
{- Non-bare repositories only use hashDirMixed, so - don't need to do any work to check if the file is
- don't need to do any work to check if the file is - present. -}
- present. -} | otherwise = return $ inrepo $ annexLocation key hashDirMixed
return $ inrepo $ annexLocation key hashDirMixed
where where
inrepo d = Git.localGitDir r </> d inrepo d = Git.localGitDir r </> d
check locs@(l:_) = fromMaybe l <$> firstM doesFileExist locs check locs@(l:_) = fromMaybe l <$> firstM doesFileExist locs
check [] = error "internal" check [] = error "internal"
{- Calculates a symlink to link a file to an annexed object. -}
gitAnnexLink :: FilePath -> Key -> Git.Repo -> IO FilePath
gitAnnexLink file key r = do
cwd <- getCurrentDirectory
let absfile = fromMaybe whoops $ absNormPath cwd file
loc <- gitAnnexLocation' key r False
return $ relPathDirToFile (parentDir absfile) loc
where
whoops = error $ "unable to normalize " ++ file
{- File that maps from a key to the file(s) in the git repository. {- File that maps from a key to the file(s) in the git repository.
- Used in direct mode. -} - Used in direct mode. -}
gitAnnexMapping :: Key -> Git.Repo -> IO FilePath gitAnnexMapping :: Key -> Git.Repo -> GitConfig -> IO FilePath
gitAnnexMapping key r = do gitAnnexMapping key r config = do
loc <- gitAnnexLocation key r loc <- gitAnnexLocation key r config
return $ loc ++ ".map" return $ loc ++ ".map"
{- File that caches information about a key's content, used to determine {- File that caches information about a key's content, used to determine
- if a file has changed. - if a file has changed.
- Used in direct mode. -} - Used in direct mode. -}
gitAnnexInodeCache :: Key -> Git.Repo -> IO FilePath gitAnnexInodeCache :: Key -> Git.Repo -> GitConfig -> IO FilePath
gitAnnexInodeCache key r = do gitAnnexInodeCache key r config = do
loc <- gitAnnexLocation key r loc <- gitAnnexLocation key r config
return $ loc ++ ".cache" return $ loc ++ ".cache"
gitAnnexInodeSentinal :: Git.Repo -> FilePath gitAnnexInodeSentinal :: Git.Repo -> FilePath

View file

@ -111,6 +111,7 @@ gen r u _ gc = go <$> remoteCost gc defcst
else Nothing else Nothing
, repo = r , repo = r
, gitconfig = gc , gitconfig = gc
{ remoteGitConfig = Just $ extractGitConfig r }
, readonly = Git.repoIsHttp r , readonly = Git.repoIsHttp r
, globallyAvailable = not $ Git.repoIsLocal r || Git.repoIsLocalUnknown r , globallyAvailable = not $ Git.repoIsLocal r || Git.repoIsLocalUnknown r
, remotetype = remote , remotetype = remote
@ -332,7 +333,8 @@ copyFromRemote r key file dest
copyFromRemoteCheap :: Remote -> Key -> FilePath -> Annex Bool copyFromRemoteCheap :: Remote -> Key -> FilePath -> Annex Bool
copyFromRemoteCheap r key file copyFromRemoteCheap r key file
| not $ Git.repoIsUrl (repo r) = guardUsable (repo r) False $ do | not $ Git.repoIsUrl (repo r) = guardUsable (repo r) False $ do
loc <- liftIO $ gitAnnexLocation key (repo r) loc <- liftIO $ gitAnnexLocation key (repo r) $
fromJust $ remoteGitConfig $ gitconfig r
liftIO $ catchBoolIO $ createSymbolicLink loc file >> return True liftIO $ catchBoolIO $ createSymbolicLink loc file >> return True
| Git.repoIsSsh (repo r) = | Git.repoIsSsh (repo r) =
ifM (Annex.Content.preseedTmp key file) ifM (Annex.Content.preseedTmp key file)

View file

@ -88,7 +88,8 @@ data RemoteGitConfig = RemoteGitConfig
, remoteAnnexStartCommand :: Maybe String , remoteAnnexStartCommand :: Maybe String
, remoteAnnexStopCommand :: Maybe String , remoteAnnexStopCommand :: Maybe String
-- these settings are specific to particular types of remotes {- These settings are specific to particular types of remotes
- including special remotes. -}
, remoteAnnexSshOptions :: [String] , remoteAnnexSshOptions :: [String]
, remoteAnnexRsyncOptions :: [String] , remoteAnnexRsyncOptions :: [String]
, remoteAnnexGnupgOptions :: [String] , remoteAnnexGnupgOptions :: [String]
@ -97,6 +98,8 @@ data RemoteGitConfig = RemoteGitConfig
, remoteAnnexBupSplitOptions :: [String] , remoteAnnexBupSplitOptions :: [String]
, remoteAnnexDirectory :: Maybe FilePath , remoteAnnexDirectory :: Maybe FilePath
, remoteAnnexHookType :: Maybe String , remoteAnnexHookType :: Maybe String
{- A regular git remote's git repository config. -}
, remoteGitConfig :: Maybe GitConfig
} }
extractRemoteGitConfig :: Git.Repo -> String -> RemoteGitConfig extractRemoteGitConfig :: Git.Repo -> String -> RemoteGitConfig
@ -117,6 +120,7 @@ extractRemoteGitConfig r remotename = RemoteGitConfig
, remoteAnnexBupSplitOptions = getoptions "bup-split-options" , remoteAnnexBupSplitOptions = getoptions "bup-split-options"
, remoteAnnexDirectory = notempty $ getmaybe "directory" , remoteAnnexDirectory = notempty $ getmaybe "directory"
, remoteAnnexHookType = notempty $ getmaybe "hooktype" , remoteAnnexHookType = notempty $ getmaybe "hooktype"
, remoteGitConfig = Nothing
} }
where where
getbool k def = fromMaybe def $ getmaybebool k getbool k def = fromMaybe def $ getmaybebool k

View file

@ -92,7 +92,7 @@ updateSymlinks = do
case r of case r of
Nothing -> noop Nothing -> noop
Just (k, _) -> do Just (k, _) -> do
link <- calcGitLink f k link <- inRepo $ gitAnnexLink f k
liftIO $ removeFile f liftIO $ removeFile f
liftIO $ createSymbolicLink link f liftIO $ createSymbolicLink link f
Annex.Queue.addCommand "add" [Param "--"] [f] Annex.Queue.addCommand "add" [Param "--"] [f]

2
debian/changelog vendored
View file

@ -30,6 +30,8 @@ git-annex (4.20130324) UNRELEASED; urgency=low
* webapp: Improved transfer queue management. * webapp: Improved transfer queue management.
* init: Probe whether the filesystem supports fifos, and if not, * init: Probe whether the filesystem supports fifos, and if not,
disable ssh connection caching. disable ssh connection caching.
* Use lower case hash directories for storing files on crippled filesystems,
same as is already done for bare repositories.
-- Joey Hess <joeyh@debian.org> Mon, 25 Mar 2013 10:21:46 -0400 -- Joey Hess <joeyh@debian.org> Mon, 25 Mar 2013 10:21:46 -0400