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:
parent
c20143ee32
commit
f1b0a4b404
22 changed files with 90 additions and 70 deletions
6
Annex.hs
6
Annex.hs
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) $
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
50
Locations.hs
50
Locations.hs
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
2
debian/changelog
vendored
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue