where indentation

This commit is contained in:
Joey Hess 2012-11-12 01:05:04 -04:00
parent f0dd6d00d1
commit ebd576ebcb
30 changed files with 804 additions and 812 deletions

View file

@ -32,20 +32,20 @@ seek = [withFilesNotInGit start, withFilesUnlocked start]
- to its content. -} - to its content. -}
start :: FilePath -> CommandStart start :: FilePath -> CommandStart
start file = notBareRepo $ ifAnnexed file fixup add start file = notBareRepo $ ifAnnexed file fixup add
where where
add = do add = do
s <- liftIO $ getSymbolicLinkStatus file s <- liftIO $ getSymbolicLinkStatus file
if isSymbolicLink s || not (isRegularFile s) if isSymbolicLink s || not (isRegularFile s)
then stop then stop
else do else do
showStart "add" file showStart "add" file
next $ perform file next $ perform file
fixup (key, _) = do fixup (key, _) = do
-- fixup from an interrupted add; the symlink -- fixup from an interrupted add; the symlink
-- is present but not yet added to git -- is present but not yet added to git
showStart "add" file showStart "add" file
liftIO $ removeFile file liftIO $ removeFile file
next $ next $ cleanup file key =<< inAnnex key next $ next $ cleanup file key =<< inAnnex key
{- The file that's being added is locked down before a key is generated, {- The file that's being added is locked down before a key is generated,
- to prevent it from being modified in between. It's hard linked into a - to prevent it from being modified in between. It's hard linked into a
@ -67,15 +67,15 @@ ingest :: KeySource -> Annex (Maybe Key)
ingest source = do ingest source = do
backend <- chooseBackend $ keyFilename source backend <- chooseBackend $ keyFilename source
genKey source backend >>= go genKey source backend >>= go
where where
go Nothing = do go Nothing = do
liftIO $ nukeFile $ contentLocation source liftIO $ nukeFile $ contentLocation source
return Nothing return Nothing
go (Just (key, _)) = do go (Just (key, _)) = do
handle (undo (keyFilename source) key) $ handle (undo (keyFilename source) key) $
moveAnnex key $ contentLocation source moveAnnex key $ contentLocation source
liftIO $ nukeFile $ keyFilename source liftIO $ nukeFile $ keyFilename source
return $ Just key return $ Just key
perform :: FilePath -> CommandPerform perform :: FilePath -> CommandPerform
perform file = perform file =
@ -91,12 +91,12 @@ undo file key e = do
handle tryharder $ fromAnnex key file handle tryharder $ fromAnnex key file
logStatus key InfoMissing logStatus key InfoMissing
throw e throw e
where where
-- 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 <- inRepo $ 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

View file

@ -25,8 +25,8 @@ start = startUnused "addunused" perform (performOther "bad") (performOther "tmp"
perform :: Key -> CommandPerform perform :: Key -> CommandPerform
perform key = next $ Command.Add.cleanup file key True perform key = next $ Command.Add.cleanup file key True
where where
file = "unused." ++ key2file key file = "unused." ++ key2file key
{- The content is not in the annex, but in another directory, and {- The content is not in the annex, but in another directory, and
- it seems better to error out, rather than moving bad/tmp content into - it seems better to error out, rather than moving bad/tmp content into

View file

@ -40,31 +40,31 @@ seek = [withField fileOption return $ \f ->
start :: Maybe FilePath -> Maybe Int -> String -> CommandStart start :: Maybe FilePath -> Maybe Int -> String -> CommandStart
start optfile pathdepth s = notBareRepo $ go $ fromMaybe bad $ parseURI s start optfile pathdepth s = notBareRepo $ go $ fromMaybe bad $ parseURI s
where where
bad = fromMaybe (error $ "bad url " ++ s) $ bad = fromMaybe (error $ "bad url " ++ s) $
parseURI $ escapeURIString isUnescapedInURI s parseURI $ escapeURIString isUnescapedInURI s
go url = do go url = do
let file = fromMaybe (url2file url pathdepth) optfile let file = fromMaybe (url2file url pathdepth) optfile
showStart "addurl" file showStart "addurl" file
next $ perform s file next $ perform s file
perform :: String -> FilePath -> CommandPerform perform :: String -> FilePath -> CommandPerform
perform url file = ifAnnexed file addurl geturl perform url file = ifAnnexed file addurl geturl
where where
geturl = do geturl = do
liftIO $ createDirectoryIfMissing True (parentDir file) liftIO $ createDirectoryIfMissing True (parentDir file)
ifM (Annex.getState Annex.fast) ifM (Annex.getState Annex.fast)
( nodownload url file , download url file ) ( nodownload url file , download url file )
addurl (key, _backend) = do addurl (key, _backend) = do
headers <- getHttpHeaders headers <- getHttpHeaders
ifM (liftIO $ Url.check url headers $ keySize key) ifM (liftIO $ Url.check url headers $ keySize key)
( do ( do
setUrlPresent key url setUrlPresent key url
next $ return True next $ return True
, do , do
warning $ "failed to verify url: " ++ url warning $ "failed to verify url: " ++ url
stop stop
) )
download :: String -> FilePath -> CommandPerform download :: String -> FilePath -> CommandPerform
download url file = do download url file = do
@ -103,10 +103,10 @@ url2file url pathdepth = case pathdepth of
| depth > 0 -> frombits $ drop depth | depth > 0 -> frombits $ drop depth
| depth < 0 -> frombits $ reverse . take (negate depth) . reverse | depth < 0 -> frombits $ reverse . take (negate depth) . reverse
| otherwise -> error "bad --pathdepth" | otherwise -> error "bad --pathdepth"
where where
fullurl = uriRegName auth ++ uriPath url ++ uriQuery url fullurl = uriRegName auth ++ uriPath url ++ uriQuery url
frombits a = join "/" $ a urlbits frombits a = join "/" $ a urlbits
urlbits = map (filesize . escape) $ filter (not . null) $ split "/" fullurl urlbits = map (filesize . escape) $ filter (not . null) $ split "/" fullurl
auth = fromMaybe (error $ "bad url " ++ show url) $ uriAuthority url auth = fromMaybe (error $ "bad url " ++ show url) $ uriAuthority url
filesize = take 255 filesize = take 255
escape = replace "/" "_" . replace "?" "_" escape = replace "/" "_" . replace "?" "_"

View file

@ -65,7 +65,7 @@ autoStart = do
) )
, nothing , nothing
) )
where where
go program dir = do go program dir = do
changeWorkingDirectory dir changeWorkingDirectory dir
boolSystem program [Param "assistant"] boolSystem program [Param "assistant"]

View file

@ -24,6 +24,6 @@ start = next $ next $ do
Annex.Branch.commit "update" Annex.Branch.commit "update"
_ <- runhook <=< inRepo $ Git.hookPath "annex-content" _ <- runhook <=< inRepo $ Git.hookPath "annex-content"
return True return True
where where
runhook (Just hook) = liftIO $ boolSystem hook [] runhook (Just hook) = liftIO $ boolSystem hook []
runhook Nothing = return True runhook Nothing = return True

View file

@ -29,7 +29,7 @@ start :: Maybe Remote -> Maybe Remote -> FilePath -> (Key, Backend) -> CommandSt
start to from file (key, backend) = autoCopies file key (<) $ start to from file (key, backend) = autoCopies file key (<) $
stopUnless shouldCopy $ stopUnless shouldCopy $
Command.Move.start to from False file (key, backend) Command.Move.start to from False file (key, backend)
where where
shouldCopy = case to of shouldCopy = case to of
Nothing -> checkAuto $ wantGet (Just file) Nothing -> checkAuto $ wantGet (Just file)
Just r -> checkAuto $ wantSend (Just file) (Remote.uuid r) Just r -> checkAuto $ wantSend (Just file) (Remote.uuid r)

View file

@ -76,8 +76,8 @@ performRemote key numcopies remote = lockContent key $ do
stopUnless (canDropKey key numcopies have tocheck [uuid]) $ do stopUnless (canDropKey key numcopies have tocheck [uuid]) $ do
ok <- Remote.removeKey remote key ok <- Remote.removeKey remote key
next $ cleanupRemote key remote ok next $ cleanupRemote key remote ok
where where
uuid = Remote.uuid remote uuid = Remote.uuid remote
cleanupLocal :: Key -> CommandCleanup cleanupLocal :: Key -> CommandCleanup
cleanupLocal key = do cleanupLocal key = do
@ -106,20 +106,20 @@ canDropKey key numcopiesM have check skip = do
findCopies :: Key -> Int -> [UUID] -> [UUID] -> [Remote] -> Annex Bool findCopies :: Key -> Int -> [UUID] -> [UUID] -> [Remote] -> Annex Bool
findCopies key need skip = helper [] findCopies key need skip = helper []
where where
helper bad have [] helper bad have []
| length have >= need = return True | length have >= need = return True
| otherwise = notEnoughCopies key need have skip bad | otherwise = notEnoughCopies key need have skip bad
helper bad have (r:rs) helper bad have (r:rs)
| length have >= need = return True | length have >= need = return True
| otherwise = do | otherwise = do
let u = Remote.uuid r let u = Remote.uuid r
let duplicate = u `elem` have let duplicate = u `elem` have
haskey <- Remote.hasKey r key haskey <- Remote.hasKey r key
case (duplicate, haskey) of case (duplicate, haskey) of
(False, Right True) -> helper bad (u:have) rs (False, Right True) -> helper bad (u:have) rs
(False, Left _) -> helper (r:bad) have rs (False, Left _) -> helper (r:bad) have rs
_ -> helper bad have rs _ -> helper bad have rs
notEnoughCopies :: Key -> Int -> [UUID] -> [UUID] -> [Remote] -> Annex Bool notEnoughCopies :: Key -> Int -> [UUID] -> [UUID] -> [Remote] -> Annex Bool
notEnoughCopies key need have skip bad = do notEnoughCopies key need have skip bad = do
@ -132,6 +132,6 @@ notEnoughCopies key need have skip bad = do
Remote.showLocations key (have++skip) Remote.showLocations key (have++skip)
hint hint
return False return False
where where
unsafe = showNote "unsafe" unsafe = showNote "unsafe"
hint = showLongNote "(Use --force to override this check, or adjust annex.numcopies.)" hint = showLongNote "(Use --force to override this check, or adjust annex.numcopies.)"

View file

@ -29,13 +29,13 @@ start = startUnused "dropunused" perform (performOther gitAnnexBadLocation) (per
perform :: Key -> CommandPerform perform :: Key -> CommandPerform
perform key = maybe droplocal dropremote =<< Remote.byName =<< from perform key = maybe droplocal dropremote =<< Remote.byName =<< from
where where
dropremote r = do dropremote r = do
showAction $ "from " ++ Remote.name r showAction $ "from " ++ Remote.name r
ok <- Remote.removeKey r key ok <- Remote.removeKey r key
next $ Command.Drop.cleanupRemote key r ok next $ Command.Drop.cleanupRemote key r ok
droplocal = Command.Drop.performLocal key (Just 0) -- force drop droplocal = Command.Drop.performLocal key (Just 0) -- force drop
from = Annex.getField $ Option.name Command.Drop.fromOption from = Annex.getField $ Option.name Command.Drop.fromOption
performOther :: (Key -> Git.Repo -> FilePath) -> Key -> CommandPerform performOther :: (Key -> Git.Repo -> FilePath) -> Key -> CommandPerform
performOther filespec key = do performOther filespec key = do

View file

@ -29,14 +29,14 @@ formatOption = Option.field [] "format" paramFormat "control format of output"
print0Option :: Option print0Option :: Option
print0Option = Option.Option [] ["print0"] (Option.NoArg set) print0Option = Option.Option [] ["print0"] (Option.NoArg set)
"terminate output with null" "terminate output with null"
where where
set = Annex.setField (Option.name formatOption) "${file}\0" set = Annex.setField (Option.name formatOption) "${file}\0"
seek :: [CommandSeek] seek :: [CommandSeek]
seek = [withField formatOption formatconverter $ \f -> seek = [withField formatOption formatconverter $ \f ->
withFilesInGit $ whenAnnexed $ start f] withFilesInGit $ whenAnnexed $ start f]
where where
formatconverter = return . fmap Utility.Format.gen formatconverter = return . fmap Utility.Format.gen
start :: Maybe Utility.Format.Format -> FilePath -> (Key, Backend) -> CommandStart start :: Maybe Utility.Format.Format -> FilePath -> (Key, Backend) -> CommandStart
start format file (key, _) = do start format file (key, _) = do
@ -50,12 +50,12 @@ start format file (key, _) = do
Utility.Format.format formatter $ Utility.Format.format formatter $
M.fromList vars M.fromList vars
stop stop
where where
vars = vars =
[ ("file", file) [ ("file", file)
, ("key", key2file key) , ("key", key2file key)
, ("backend", keyBackendName key) , ("backend", keyBackendName key)
, ("bytesize", size show) , ("bytesize", size show)
, ("humansize", size $ roughSize storageUnits True) , ("humansize", size $ roughSize storageUnits True)
] ]
size c = maybe "unknown" c $ keySize key size c = maybe "unknown" c $ keySize key

View file

@ -78,22 +78,22 @@ withIncremental = withValue $ do
(True, _, _) -> (True, _, _) ->
maybe startIncremental (return . ContIncremental . Just) maybe startIncremental (return . ContIncremental . Just)
=<< getStartTime =<< getStartTime
where where
startIncremental = do startIncremental = do
recordStartTime recordStartTime
return StartIncremental return StartIncremental
checkschedule Nothing = error "bad --incremental-schedule value" checkschedule Nothing = error "bad --incremental-schedule value"
checkschedule (Just delta) = do checkschedule (Just delta) = do
Annex.addCleanup "" $ do Annex.addCleanup "" $ do
v <- getStartTime v <- getStartTime
case v of case v of
Nothing -> noop Nothing -> noop
Just started -> do Just started -> do
now <- liftIO getPOSIXTime now <- liftIO getPOSIXTime
when (now - realToFrac started >= delta) $ when (now - realToFrac started >= delta) $
resetStartTime resetStartTime
return True return True
start :: Maybe Remote -> Incremental -> FilePath -> (Key, Backend) -> CommandStart start :: Maybe Remote -> Incremental -> FilePath -> (Key, Backend) -> CommandStart
start from inc file (key, backend) = do start from inc file (key, backend) = do
@ -101,8 +101,8 @@ start from inc file (key, backend) = do
case from of case from of
Nothing -> go $ perform key file backend numcopies Nothing -> go $ perform key file backend numcopies
Just r -> go $ performRemote key file backend numcopies r Just r -> go $ performRemote key file backend numcopies r
where where
go = runFsck inc file key go = runFsck inc file key
perform :: Key -> FilePath -> Backend -> Maybe Int -> Annex Bool perform :: Key -> FilePath -> Backend -> Maybe Int -> Annex Bool
perform key file backend numcopies = check perform key file backend numcopies = check
@ -119,48 +119,48 @@ perform key file backend numcopies = check
performRemote :: Key -> FilePath -> Backend -> Maybe Int -> Remote -> Annex Bool performRemote :: Key -> FilePath -> Backend -> Maybe Int -> Remote -> Annex Bool
performRemote key file backend numcopies remote = performRemote key file backend numcopies remote =
dispatch =<< Remote.hasKey remote key dispatch =<< Remote.hasKey remote key
where where
dispatch (Left err) = do dispatch (Left err) = do
showNote err showNote err
return False return False
dispatch (Right True) = withtmp $ \tmpfile -> dispatch (Right True) = withtmp $ \tmpfile ->
ifM (getfile tmpfile) ifM (getfile tmpfile)
( go True (Just tmpfile) ( go True (Just tmpfile)
, go True Nothing , go True Nothing
) )
dispatch (Right False) = go False Nothing dispatch (Right False) = go False Nothing
go present localcopy = check go present localcopy = check
[ verifyLocationLogRemote key file remote present [ verifyLocationLogRemote key file remote present
, checkKeySizeRemote key remote localcopy , checkKeySizeRemote key remote localcopy
, checkBackendRemote backend key remote localcopy , checkBackendRemote backend key remote localcopy
, checkKeyNumCopies key file numcopies , checkKeyNumCopies key file numcopies
] ]
withtmp a = do withtmp a = do
pid <- liftIO getProcessID pid <- liftIO getProcessID
t <- fromRepo gitAnnexTmpDir t <- fromRepo gitAnnexTmpDir
createAnnexDirectory t createAnnexDirectory t
let tmp = t </> "fsck" ++ show pid ++ "." ++ keyFile key let tmp = t </> "fsck" ++ show pid ++ "." ++ keyFile key
let cleanup = liftIO $ catchIO (removeFile tmp) (const noop) let cleanup = liftIO $ catchIO (removeFile tmp) (const noop)
cleanup cleanup
cleanup `after` a tmp cleanup `after` a tmp
getfile tmp = getfile tmp =
ifM (Remote.retrieveKeyFileCheap remote key tmp) ifM (Remote.retrieveKeyFileCheap remote key tmp)
( return True ( return True
, ifM (Annex.getState Annex.fast) , ifM (Annex.getState Annex.fast)
( return False ( return False
, Remote.retrieveKeyFile remote key Nothing tmp , Remote.retrieveKeyFile remote key Nothing tmp
)
) )
)
{- To fsck a bare repository, fsck each key in the location log. -} {- To fsck a bare repository, fsck each key in the location log. -}
withBarePresentKeys :: (Key -> CommandStart) -> CommandSeek withBarePresentKeys :: (Key -> CommandStart) -> CommandSeek
withBarePresentKeys a params = isBareRepo >>= go withBarePresentKeys a params = isBareRepo >>= go
where where
go False = return [] go False = return []
go True = do go True = do
unless (null params) $ unless (null params) $
error "fsck should be run without parameters in a bare repository" error "fsck should be run without parameters in a bare repository"
map a <$> loggedKeys map a <$> loggedKeys
startBare :: Incremental -> Key -> CommandStart startBare :: Incremental -> Key -> CommandStart
startBare inc key = case Backend.maybeLookupBackendName (Types.Key.keyBackendName key) of startBare inc key = case Backend.maybeLookupBackendName (Types.Key.keyBackendName key) of
@ -242,10 +242,10 @@ verifyLocationLog' key desc present u bad = do
"but its content is missing." "but its content is missing."
return False return False
_ -> return True _ -> return True
where where
fix s = do fix s = do
showNote "fixing location log" showNote "fixing location log"
bad s bad s
{- The size of the data for a key is checked against the size encoded in {- The size of the data for a key is checked against the size encoded in
- the key's metadata, if available. -} - the key's metadata, if available. -}
@ -269,19 +269,19 @@ checkKeySizeOr bad key file = case Types.Key.keySize key of
size' <- fromIntegral . fileSize size' <- fromIntegral . fileSize
<$> liftIO (getFileStatus file) <$> liftIO (getFileStatus file)
comparesizes size size' comparesizes size size'
where where
comparesizes a b = do comparesizes a b = do
let same = a == b let same = a == b
unless same $ badsize a b unless same $ badsize a b
return same return same
badsize a b = do badsize a b = do
msg <- bad key msg <- bad key
warning $ concat warning $ concat
[ "Bad file size (" [ "Bad file size ("
, compareSizes storageUnits True a b , compareSizes storageUnits True a b
, "); " , "); "
, msg , msg
] ]
checkBackend :: Backend -> Key -> Annex Bool checkBackend :: Backend -> Key -> Annex Bool
checkBackend backend key = do checkBackend backend key = do
@ -290,8 +290,8 @@ checkBackend backend key = do
checkBackendRemote :: Backend -> Key -> Remote -> Maybe FilePath -> Annex Bool checkBackendRemote :: Backend -> Key -> Remote -> Maybe FilePath -> Annex Bool
checkBackendRemote backend key remote = maybe (return True) go checkBackendRemote backend key remote = maybe (return True) go
where where
go = checkBackendOr (badContentRemote remote) backend key go = checkBackendOr (badContentRemote remote) backend key
checkBackendOr :: (Key -> Annex String) -> Backend -> Key -> FilePath -> Annex Bool checkBackendOr :: (Key -> Annex String) -> Backend -> Key -> FilePath -> Annex Bool
checkBackendOr bad backend key file = checkBackendOr bad backend key file =
@ -414,9 +414,9 @@ recordStartTime = do
t <- modificationTime <$> getFileStatus f t <- modificationTime <$> getFileStatus f
hPutStr h $ showTime $ realToFrac t hPutStr h $ showTime $ realToFrac t
hClose h hClose h
where where
showTime :: POSIXTime -> String showTime :: POSIXTime -> String
showTime = show showTime = show
resetStartTime :: Annex () resetStartTime :: Annex ()
resetStartTime = liftIO . nukeFile =<< fromRepo gitAnnexFsckState resetStartTime = liftIO . nukeFile =<< fromRepo gitAnnexFsckState
@ -431,7 +431,7 @@ getStartTime = do
return $ if Just (realToFrac timestamp) == t return $ if Just (realToFrac timestamp) == t
then Just timestamp then Just timestamp
else Nothing else Nothing
where where
readishTime :: String -> Maybe POSIXTime readishTime :: String -> Maybe POSIXTime
readishTime s = utcTimeToPOSIXSeconds <$> readishTime s = utcTimeToPOSIXSeconds <$>
parseTime defaultTimeLocale "%s%Qs" s parseTime defaultTimeLocale "%s%Qs" s

View file

@ -32,10 +32,10 @@ start from file (key, _) = stopUnless ((not <$> inAnnex key) <&&> checkAuto (wan
-- get --from = copy --from -- get --from = copy --from
stopUnless (Command.Move.fromOk src key) $ stopUnless (Command.Move.fromOk src key) $
go $ Command.Move.fromPerform src False key file go $ Command.Move.fromPerform src False key file
where where
go a = do go a = do
showStart "get" file showStart "get" file
next a next a
perform :: Key -> FilePath -> CommandPerform perform :: Key -> FilePath -> CommandPerform
perform key file = stopUnless (getViaTmp key $ getKeyFile key file) $ perform key file = stopUnless (getViaTmp key $ getKeyFile key file) $
@ -45,29 +45,29 @@ perform key file = stopUnless (getViaTmp key $ getKeyFile key file) $
- and copy it to here. -} - and copy it to here. -}
getKeyFile :: Key -> FilePath -> FilePath -> Annex Bool getKeyFile :: Key -> FilePath -> FilePath -> Annex Bool
getKeyFile key file dest = dispatch =<< Remote.keyPossibilities key getKeyFile key file dest = dispatch =<< Remote.keyPossibilities key
where where
dispatch [] = do dispatch [] = do
showNote "not available" showNote "not available"
Remote.showLocations key [] Remote.showLocations key []
return False return False
dispatch remotes = trycopy remotes remotes dispatch remotes = trycopy remotes remotes
trycopy full [] = do trycopy full [] = do
Remote.showTriedRemotes full Remote.showTriedRemotes full
Remote.showLocations key [] Remote.showLocations key []
return False return False
trycopy full (r:rs) = trycopy full (r:rs) =
ifM (probablyPresent r) ifM (probablyPresent r)
( docopy r (trycopy full rs) ( docopy r (trycopy full rs)
, trycopy full rs , trycopy full rs
) )
-- This check is to avoid an ugly message if a remote is a -- This check is to avoid an ugly message if a remote is a
-- drive that is not mounted. -- drive that is not mounted.
probablyPresent r probablyPresent r
| Remote.hasKeyCheap r = | Remote.hasKeyCheap r =
either (const False) id <$> Remote.hasKey r key either (const False) id <$> Remote.hasKey r key
| otherwise = return True | otherwise = return True
docopy r continue = do docopy r continue = do
ok <- download (Remote.uuid r) key (Just file) noRetry $ do ok <- download (Remote.uuid r) key (Just file) noRetry $ do
showAction $ "from " ++ Remote.name r showAction $ "from " ++ Remote.name r
Remote.retrieveKeyFile r key (Just file) dest Remote.retrieveKeyFile r key (Just file) dest
if ok then return ok else continue if ok then return ok else continue

View file

@ -47,5 +47,5 @@ showHelp = liftIO $ putStrLn $ unlines
] ]
, "Run git-annex without any options for a complete command and option list." , "Run git-annex without any options for a complete command and option list."
] ]
where where
cmdline c = "\t" ++ cmdname c ++ "\t" ++ cmddesc c cmdline c = "\t" ++ cmdname c ++ "\t" ++ cmddesc c

View file

@ -20,8 +20,8 @@ seek = [withKeys start]
start :: Key -> CommandStart start :: Key -> CommandStart
start key = inAnnexSafe key >>= dispatch start key = inAnnexSafe key >>= dispatch
where where
dispatch (Just True) = stop dispatch (Just True) = stop
dispatch (Just False) = exit 1 dispatch (Just False) = exit 1
dispatch Nothing = exit 100 dispatch Nothing = exit 100
exit n = liftIO $ exitWith $ ExitFailure n exit n = liftIO $ exitWith $ ExitFailure n

View file

@ -22,8 +22,8 @@ start :: [String] -> CommandStart
start ws = do start ws = do
showStart "init" description showStart "init" description
next $ perform description next $ perform description
where where
description = unwords ws description = unwords ws
perform :: String -> CommandPerform perform :: String -> CommandPerform
perform description = do perform description = do

View file

@ -40,8 +40,8 @@ start (name:ws) = do
showStart "initremote" name showStart "initremote" name
next $ perform t u name $ M.union config c next $ perform t u name $ M.union config c
where where
config = Logs.Remote.keyValToConfig ws config = Logs.Remote.keyValToConfig ws
perform :: RemoteType -> UUID -> String -> R.RemoteConfig -> CommandPerform perform :: RemoteType -> UUID -> String -> R.RemoteConfig -> CommandPerform
perform t u name c = do perform t u name c = do
@ -59,19 +59,19 @@ findByName :: String -> Annex (UUID, R.RemoteConfig)
findByName name = do findByName name = do
m <- Logs.Remote.readRemoteLog m <- Logs.Remote.readRemoteLog
maybe generate return $ findByName' name m maybe generate return $ findByName' name m
where where
generate = do generate = do
uuid <- liftIO genUUID uuid <- liftIO genUUID
return (uuid, M.insert nameKey name M.empty) return (uuid, M.insert nameKey name M.empty)
findByName' :: String -> M.Map UUID R.RemoteConfig -> Maybe (UUID, R.RemoteConfig) findByName' :: String -> M.Map UUID R.RemoteConfig -> Maybe (UUID, R.RemoteConfig)
findByName' n = headMaybe . filter (matching . snd) . M.toList findByName' n = headMaybe . filter (matching . snd) . M.toList
where where
matching c = case M.lookup nameKey c of matching c = case M.lookup nameKey c of
Nothing -> False Nothing -> False
Just n' Just n'
| n' == n -> True | n' == n -> True
| otherwise -> False | otherwise -> False
remoteNames :: Annex [String] remoteNames :: Annex [String]
remoteNames = do remoteNames = do
@ -81,12 +81,12 @@ remoteNames = do
{- find the specified remote type -} {- find the specified remote type -}
findType :: R.RemoteConfig -> Annex RemoteType findType :: R.RemoteConfig -> Annex RemoteType
findType config = maybe unspecified specified $ M.lookup typeKey config findType config = maybe unspecified specified $ M.lookup typeKey config
where where
unspecified = error "Specify the type of remote with type=" unspecified = error "Specify the type of remote with type="
specified s = case filter (findtype s) Remote.remoteTypes of specified s = case filter (findtype s) Remote.remoteTypes of
[] -> error $ "Unknown remote type " ++ s [] -> error $ "Unknown remote type " ++ s
(t:_) -> return t (t:_) -> return t
findtype s i = R.typename i == s findtype s i = R.typename i == s
{- The name of a configured remote is stored in its config using this key. -} {- The name of a configured remote is stored in its config using this key. -}
nameKey :: String nameKey :: String

View file

@ -47,9 +47,8 @@ passthruOptions = map odate ["since", "after", "until", "before"] ++
[ Option.field ['n'] "max-count" paramNumber [ Option.field ['n'] "max-count" paramNumber
"limit number of logs displayed" "limit number of logs displayed"
] ]
where where
odate n = Option.field [] n paramDate $ odate n = Option.field [] n paramDate $ "show log " ++ n ++ " date"
"show log " ++ n ++ " date"
gourceOption :: Option gourceOption :: Option
gourceOption = Option.flag [] "gource" "format output for gource" gourceOption = Option.flag [] "gource" "format output for gource"
@ -60,10 +59,10 @@ seek = [withValue Remote.uuidDescriptions $ \m ->
withValue (concat <$> mapM getoption passthruOptions) $ \os -> withValue (concat <$> mapM getoption passthruOptions) $ \os ->
withFlag gourceOption $ \gource -> withFlag gourceOption $ \gource ->
withFilesInGit $ whenAnnexed $ start m zone os gource] withFilesInGit $ whenAnnexed $ start m zone os gource]
where where
getoption o = maybe [] (use o) <$> getoption o = maybe [] (use o) <$>
Annex.getField (Option.name o) Annex.getField (Option.name o)
use o v = [Param ("--" ++ Option.name o), Param v] use o v = [Param ("--" ++ Option.name o), Param v]
start :: M.Map UUID String -> TimeZone -> [CommandParam] -> Bool -> start :: M.Map UUID String -> TimeZone -> [CommandParam] -> Bool ->
FilePath -> (Key, Backend) -> CommandStart FilePath -> (Key, Backend) -> CommandStart
@ -72,41 +71,41 @@ start m zone os gource file (key, _) = do
-- getLog produces a zombie; reap it -- getLog produces a zombie; reap it
liftIO reapZombies liftIO reapZombies
stop stop
where where
output output
| gource = gourceOutput lookupdescription file | gource = gourceOutput lookupdescription file
| otherwise = normalOutput lookupdescription file zone | otherwise = normalOutput lookupdescription file zone
lookupdescription u = fromMaybe (fromUUID u) $ M.lookup u m lookupdescription u = fromMaybe (fromUUID u) $ M.lookup u m
showLog :: Outputter -> [RefChange] -> Annex () showLog :: Outputter -> [RefChange] -> Annex ()
showLog outputter ps = do showLog outputter ps = do
sets <- mapM (getset newref) ps sets <- mapM (getset newref) ps
previous <- maybe (return genesis) (getset oldref) (lastMaybe ps) previous <- maybe (return genesis) (getset oldref) (lastMaybe ps)
sequence_ $ compareChanges outputter $ sets ++ [previous] sequence_ $ compareChanges outputter $ sets ++ [previous]
where where
genesis = (0, S.empty) genesis = (0, S.empty)
getset select change = do getset select change = do
s <- S.fromList <$> get (select change) s <- S.fromList <$> get (select change)
return (changetime change, s) return (changetime change, s)
get ref = map toUUID . Logs.Presence.getLog . L.unpack <$> get ref = map toUUID . Logs.Presence.getLog . L.unpack <$>
catObject ref catObject ref
normalOutput :: (UUID -> String) -> FilePath -> TimeZone -> Outputter normalOutput :: (UUID -> String) -> FilePath -> TimeZone -> Outputter
normalOutput lookupdescription file zone present ts us = normalOutput lookupdescription file zone present ts us =
liftIO $ mapM_ (putStrLn . format) us liftIO $ mapM_ (putStrLn . format) us
where where
time = showTimeStamp zone ts time = showTimeStamp zone ts
addel = if present then "+" else "-" addel = if present then "+" else "-"
format u = unwords [ addel, time, file, "|", format u = unwords [ addel, time, file, "|",
fromUUID u ++ " -- " ++ lookupdescription u ] fromUUID u ++ " -- " ++ lookupdescription u ]
gourceOutput :: (UUID -> String) -> FilePath -> Outputter gourceOutput :: (UUID -> String) -> FilePath -> Outputter
gourceOutput lookupdescription file present ts us = gourceOutput lookupdescription file present ts us =
liftIO $ mapM_ (putStrLn . intercalate "|" . format) us liftIO $ mapM_ (putStrLn . intercalate "|" . format) us
where where
time = takeWhile isDigit $ show ts time = takeWhile isDigit $ show ts
addel = if present then "A" else "M" addel = if present then "A" else "M"
format u = [ time, lookupdescription u, addel, file ] format u = [ time, lookupdescription u, addel, file ]
{- Generates a display of the changes (which are ordered with newest first), {- Generates a display of the changes (which are ordered with newest first),
- by comparing each change with the previous change. - by comparing each change with the previous change.
@ -114,12 +113,12 @@ gourceOutput lookupdescription file present ts us =
- removed. -} - removed. -}
compareChanges :: Ord a => (Bool -> POSIXTime -> [a] -> b) -> [(POSIXTime, S.Set a)] -> [b] compareChanges :: Ord a => (Bool -> POSIXTime -> [a] -> b) -> [(POSIXTime, S.Set a)] -> [b]
compareChanges format changes = concatMap diff $ zip changes (drop 1 changes) compareChanges format changes = concatMap diff $ zip changes (drop 1 changes)
where where
diff ((ts, new), (_, old)) = diff ((ts, new), (_, old)) =
[format True ts added, format False ts removed] [format True ts added, format False ts removed]
where where
added = S.toList $ S.difference new old added = S.toList $ S.difference new old
removed = S.toList $ S.difference old new removed = S.toList $ S.difference old new
{- Gets the git log for a given location log file. {- Gets the git log for a given location log file.
- -
@ -148,21 +147,21 @@ getLog key os = do
readLog :: [String] -> [RefChange] readLog :: [String] -> [RefChange]
readLog = mapMaybe (parse . lines) readLog = mapMaybe (parse . lines)
where where
parse (ts:raw:[]) = let (old, new) = parseRaw raw in parse (ts:raw:[]) = let (old, new) = parseRaw raw in
Just RefChange Just RefChange
{ changetime = parseTimeStamp ts { changetime = parseTimeStamp ts
, oldref = old , oldref = old
, newref = new , newref = new
} }
parse _ = Nothing parse _ = Nothing
-- Parses something like ":100644 100644 oldsha newsha M" -- Parses something like ":100644 100644 oldsha newsha M"
parseRaw :: String -> (Git.Ref, Git.Ref) parseRaw :: String -> (Git.Ref, Git.Ref)
parseRaw l = go $ words l parseRaw l = go $ words l
where where
go (_:_:oldsha:newsha:_) = (Git.Ref oldsha, Git.Ref newsha) go (_:_:oldsha:newsha:_) = (Git.Ref oldsha, Git.Ref newsha)
go _ = error $ "unable to parse git log output: " ++ l go _ = error $ "unable to parse git log output: " ++ l
parseTimeStamp :: String -> POSIXTime parseTimeStamp :: String -> POSIXTime
parseTimeStamp = utcTimeToPOSIXSeconds . fromMaybe (error "bad timestamp") . parseTimeStamp = utcTimeToPOSIXSeconds . fromMaybe (error "bad timestamp") .

View file

@ -63,14 +63,13 @@ start = do
-} -}
drawMap :: [Git.Repo] -> M.Map UUID String -> [UUID] -> String drawMap :: [Git.Repo] -> M.Map UUID String -> [UUID] -> String
drawMap rs umap ts = Dot.graph $ repos ++ trusted ++ others drawMap rs umap ts = Dot.graph $ repos ++ trusted ++ others
where where
repos = map (node umap rs) rs repos = map (node umap rs) rs
ruuids = ts ++ map getUncachedUUID rs ruuids = ts ++ map getUncachedUUID rs
others = map (unreachable . uuidnode) $ others = map (unreachable . uuidnode) $
filter (`notElem` ruuids) (M.keys umap) filter (`notElem` ruuids) (M.keys umap)
trusted = map (trustworthy . uuidnode) ts trusted = map (trustworthy . uuidnode) ts
uuidnode u = Dot.graphNode (fromUUID u) $ uuidnode u = Dot.graphNode (fromUUID u) $ M.findWithDefault "" u umap
M.findWithDefault "" u umap
hostname :: Git.Repo -> String hostname :: Git.Repo -> String
hostname r hostname r
@ -86,9 +85,9 @@ repoName :: M.Map UUID String -> Git.Repo -> String
repoName umap r repoName umap r
| repouuid == NoUUID = fallback | repouuid == NoUUID = fallback
| otherwise = M.findWithDefault fallback repouuid umap | otherwise = M.findWithDefault fallback repouuid umap
where where
repouuid = getUncachedUUID r repouuid = getUncachedUUID r
fallback = fromMaybe "unknown" $ Git.remoteName r fallback = fromMaybe "unknown" $ Git.remoteName r
{- A unique id for the node for a repo. Uses the annex.uuid if available. -} {- A unique id for the node for a repo. Uses the annex.uuid if available. -}
nodeId :: Git.Repo -> String nodeId :: Git.Repo -> String
@ -100,32 +99,32 @@ nodeId r =
{- A node representing a repo. -} {- A node representing a repo. -}
node :: M.Map UUID String -> [Git.Repo] -> Git.Repo -> String node :: M.Map UUID String -> [Git.Repo] -> Git.Repo -> String
node umap fullinfo r = unlines $ n:edges node umap fullinfo r = unlines $ n:edges
where where
n = Dot.subGraph (hostname r) (basehostname r) "lightblue" $ n = Dot.subGraph (hostname r) (basehostname r) "lightblue" $
decorate $ Dot.graphNode (nodeId r) (repoName umap r) decorate $ Dot.graphNode (nodeId r) (repoName umap r)
edges = map (edge umap fullinfo r) (Git.remotes r) edges = map (edge umap fullinfo r) (Git.remotes r)
decorate decorate
| Git.config r == M.empty = unreachable | Git.config r == M.empty = unreachable
| otherwise = reachable | otherwise = reachable
{- An edge between two repos. The second repo is a remote of the first. -} {- An edge between two repos. The second repo is a remote of the first. -}
edge :: M.Map UUID String -> [Git.Repo] -> Git.Repo -> Git.Repo -> String edge :: M.Map UUID String -> [Git.Repo] -> Git.Repo -> Git.Repo -> String
edge umap fullinfo from to = edge umap fullinfo from to =
Dot.graphEdge (nodeId from) (nodeId fullto) edgename Dot.graphEdge (nodeId from) (nodeId fullto) edgename
where where
-- get the full info for the remote, to get its UUID -- get the full info for the remote, to get its UUID
fullto = findfullinfo to fullto = findfullinfo to
findfullinfo n = findfullinfo n =
case filter (same n) fullinfo of case filter (same n) fullinfo of
[] -> n [] -> n
(n':_) -> n' (n':_) -> n'
{- Only name an edge if the name is different than the name {- Only name an edge if the name is different than the name
- that will be used for the destination node, and is - that will be used for the destination node, and is
- different from its hostname. (This reduces visual clutter.) -} - different from its hostname. (This reduces visual clutter.) -}
edgename = maybe Nothing calcname $ Git.remoteName to edgename = maybe Nothing calcname $ Git.remoteName to
calcname n calcname n
| n `elem` [repoName umap fullto, hostname fullto] = Nothing | n `elem` [repoName umap fullto, hostname fullto] = Nothing
| otherwise = Just n | otherwise = Just n
unreachable :: String -> String unreachable :: String -> String
unreachable = Dot.fillColor "red" unreachable = Dot.fillColor "red"
@ -165,11 +164,10 @@ same a b
| both Git.repoIsUrl && neither Git.repoIsSsh = matching show | both Git.repoIsUrl && neither Git.repoIsSsh = matching show
| neither Git.repoIsSsh = matching Git.repoPath | neither Git.repoIsSsh = matching Git.repoPath
| otherwise = False | otherwise = False
where
where matching t = t a == t b
matching t = t a == t b both t = t a && t b
both t = t a && t b neither t = not (t a) && not (t b)
neither t = not (t a) && not (t b)
{- reads the config of a remote, with progress display -} {- reads the config of a remote, with progress display -}
scan :: Git.Repo -> Annex Git.Repo scan :: Git.Repo -> Annex Git.Repo
@ -192,50 +190,49 @@ tryScan r
| Git.repoIsSsh r = sshscan | Git.repoIsSsh r = sshscan
| Git.repoIsUrl r = return Nothing | Git.repoIsUrl r = return Nothing
| otherwise = safely $ Git.Config.read r | otherwise = safely $ Git.Config.read r
where where
safely a = do safely a = do
result <- liftIO (try a :: IO (Either SomeException Git.Repo)) result <- liftIO (try a :: IO (Either SomeException Git.Repo))
case result of case result of
Left _ -> return Nothing Left _ -> return Nothing
Right r' -> return $ Just r' Right r' -> return $ Just r'
pipedconfig cmd params = safely $ pipedconfig cmd params = safely $
withHandle StdoutHandle createProcessSuccess p $ withHandle StdoutHandle createProcessSuccess p $
Git.Config.hRead r Git.Config.hRead r
where where
p = proc cmd $ toCommand params p = proc cmd $ toCommand params
configlist = configlist = onRemote r (pipedconfig, Nothing) "configlist" [] []
onRemote r (pipedconfig, Nothing) "configlist" [] [] manualconfiglist = do
manualconfiglist = do sshparams <- sshToRepo r [Param sshcmd]
sshparams <- sshToRepo r [Param sshcmd] liftIO $ pipedconfig "ssh" sshparams
liftIO $ pipedconfig "ssh" sshparams where
where sshcmd = cddir ++ " && " ++
sshcmd = cddir ++ " && " ++ "git config --null --list"
"git config --null --list" dir = Git.repoPath r
dir = Git.repoPath r cddir
cddir | "/~" `isPrefixOf` dir =
| "/~" `isPrefixOf` dir = let (userhome, reldir) = span (/= '/') (drop 1 dir)
let (userhome, reldir) = span (/= '/') (drop 1 dir) in "cd " ++ userhome ++ " && cd " ++ shellEscape (drop 1 reldir)
in "cd " ++ userhome ++ " && cd " ++ shellEscape (drop 1 reldir) | otherwise = "cd " ++ shellEscape dir
| otherwise = "cd " ++ shellEscape dir
-- First, try sshing and running git config manually, -- First, try sshing and running git config manually,
-- only fall back to git-annex-shell configlist if that -- only fall back to git-annex-shell configlist if that
-- fails. -- fails.
-- --
-- This is done for two reasons, first I'd like this -- This is done for two reasons, first I'd like this
-- subcommand to be usable on non-git-annex repos. -- subcommand to be usable on non-git-annex repos.
-- Secondly, configlist doesn't include information about -- Secondly, configlist doesn't include information about
-- the remote's remotes. -- the remote's remotes.
sshscan = do sshscan = do
sshnote sshnote
v <- manualconfiglist v <- manualconfiglist
case v of case v of
Nothing -> do Nothing -> do
sshnote sshnote
configlist configlist
ok -> return ok ok -> return ok
sshnote = do sshnote = do
showAction "sshing" showAction "sshing"
showOutput showOutput

View file

@ -31,9 +31,9 @@ start file (key, oldbackend) = do
showStart "migrate" file showStart "migrate" file
next $ perform file key oldbackend newbackend next $ perform file key oldbackend newbackend
else stop else stop
where where
choosebackend Nothing = Prelude.head <$> orderedList choosebackend Nothing = Prelude.head <$> orderedList
choosebackend (Just backend) = return backend choosebackend (Just backend) = return backend
{- Checks if a key is upgradable to a newer representation. -} {- Checks if a key is upgradable to a newer representation. -}
{- Ideally, all keys have file size metadata. Old keys may not. -} {- Ideally, all keys have file size metadata. Old keys may not. -}
@ -49,10 +49,10 @@ perform file oldkey oldbackend newbackend = do
( maybe stop go =<< genkey ( maybe stop go =<< genkey
, stop , stop
) )
where where
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 <- inRepo $ gitAnnexLocation oldkey
let source = KeySource { keyFilename = file, contentLocation = content } let source = KeySource { keyFilename = file, contentLocation = content }
liftM fst <$> genKey source (Just newbackend) liftM fst <$> genKey source (Just newbackend)

View file

@ -44,9 +44,9 @@ start to from move file (key, _) = do
(Nothing, Just dest) -> toStart dest move file key (Nothing, Just dest) -> toStart dest move file key
(Just src, Nothing) -> fromStart src move file key (Just src, Nothing) -> fromStart src move file key
(_ , _) -> error "only one of --from or --to can be specified" (_ , _) -> error "only one of --from or --to can be specified"
where where
noAuto = when move $ whenM (Annex.getState Annex.auto) $ error noAuto = when move $ whenM (Annex.getState Annex.auto) $ error
"--auto is not supported for move" "--auto is not supported for move"
showMoveAction :: Bool -> FilePath -> Annex () showMoveAction :: Bool -> FilePath -> Annex ()
showMoveAction True file = showStart "move" file showMoveAction True file = showStart "move" file
@ -98,15 +98,15 @@ toPerform dest move key file = moveLock move key $ do
warning "This could have failed because --fast is enabled." warning "This could have failed because --fast is enabled."
stop stop
Right True -> finish False Right True -> finish False
where where
finish remotechanged = do finish remotechanged = do
when remotechanged $ when remotechanged $
Remote.logStatus dest key InfoPresent Remote.logStatus dest key InfoPresent
if move if move
then do then do
whenM (inAnnex key) $ removeAnnex key whenM (inAnnex key) $ removeAnnex key
next $ Command.Drop.cleanupLocal key next $ Command.Drop.cleanupLocal key
else next $ return True else next $ return True
{- Moves (or copies) the content of an annexed file from a remote {- Moves (or copies) the content of an annexed file from a remote
- to the current repository. - to the current repository.
@ -118,35 +118,37 @@ fromStart :: Remote -> Bool -> FilePath -> Key -> CommandStart
fromStart src move file key fromStart src move file key
| move = go | move = go
| otherwise = stopUnless (not <$> inAnnex key) go | otherwise = stopUnless (not <$> inAnnex key) go
where where
go = stopUnless (fromOk src key) $ do go = stopUnless (fromOk src key) $ do
showMoveAction move file showMoveAction move file
next $ fromPerform src move key file next $ fromPerform src move key file
fromOk :: Remote -> Key -> Annex Bool fromOk :: Remote -> Key -> Annex Bool
fromOk src key fromOk src key
| Remote.hasKeyCheap src = | Remote.hasKeyCheap src =
either (const expensive) return =<< Remote.hasKey src key either (const expensive) return =<< Remote.hasKey src key
| otherwise = expensive | otherwise = expensive
where where
expensive = do expensive = do
u <- getUUID u <- getUUID
remotes <- Remote.keyPossibilities key remotes <- Remote.keyPossibilities key
return $ u /= Remote.uuid src && elem src remotes return $ u /= Remote.uuid src && elem src remotes
fromPerform :: Remote -> Bool -> Key -> FilePath -> CommandPerform fromPerform :: Remote -> Bool -> Key -> FilePath -> CommandPerform
fromPerform src move key file = moveLock move key $ fromPerform src move key file = moveLock move key $
ifM (inAnnex key) ifM (inAnnex key)
( handle move True ( handle move True
, handle move =<< go , handle move =<< go
) )
where where
go = download (Remote.uuid src) key (Just file) noRetry $ do go = download (Remote.uuid src) key (Just file) noRetry $ do
showAction $ "from " ++ Remote.name src showAction $ "from " ++ Remote.name src
getViaTmp key $ Remote.retrieveKeyFile src key (Just file) getViaTmp key $ Remote.retrieveKeyFile src key (Just file)
handle _ False = stop -- failed handle _ False = stop -- failed
handle False True = next $ return True -- copy complete handle False True = next $ return True -- copy complete
handle True True = do -- finish moving handle True True = do -- finish moving
ok <- Remote.removeKey src key ok <- Remote.removeKey src key
next $ Command.Drop.cleanupRemote key src ok next $ Command.Drop.cleanupRemote key src ok
{- Locks a key in order for it to be moved. {- Locks a key in order for it to be moved.
- No lock is needed when a key is being copied. -} - No lock is needed when a key is being copied. -}

View file

@ -25,13 +25,13 @@ seek = [withPairs start]
start :: (FilePath, String) -> CommandStart start :: (FilePath, String) -> CommandStart
start (file, keyname) = ifAnnexed file go stop start (file, keyname) = ifAnnexed file go stop
where where
newkey = fromMaybe (error "bad key") $ file2key keyname newkey = fromMaybe (error "bad key") $ file2key keyname
go (oldkey, _) go (oldkey, _)
| oldkey == newkey = stop | oldkey == newkey = stop
| otherwise = do | otherwise = do
showStart "rekey" file showStart "rekey" file
next $ perform file oldkey newkey next $ perform file oldkey newkey
perform :: FilePath -> Key -> Key -> CommandPerform perform :: FilePath -> Key -> Key -> CommandPerform
perform file oldkey newkey = do perform file oldkey newkey = do

View file

@ -27,10 +27,10 @@ start (src:dest:[])
ifAnnexed src ifAnnexed src
(error $ "cannot used annexed file as src: " ++ src) (error $ "cannot used annexed file as src: " ++ src)
go go
where where
go = do go = do
showStart "reinject" dest showStart "reinject" dest
next $ whenAnnexed (perform src) dest next $ whenAnnexed (perform src) dest
start _ = error "specify a src file and a dest file" start _ = error "specify a src file and a dest file"
perform :: FilePath -> FilePath -> (Key, Backend) -> CommandPerform perform :: FilePath -> FilePath -> (Key, Backend) -> CommandPerform
@ -43,14 +43,14 @@ perform src _dest (key, backend) = do
next $ cleanup key next $ cleanup key
, error "not reinjecting" , error "not reinjecting"
) )
where where
-- the file might be on a different filesystem, -- the file might be on a different filesystem,
-- so mv is used rather than simply calling -- so mv is used rather than simply calling
-- moveToObjectDir; disk space is also -- moveToObjectDir; disk space is also
-- checked this way. -- checked this way.
move = getViaTmp key $ \tmp -> move = getViaTmp key $ \tmp ->
liftIO $ boolSystem "mv" [File src, File tmp] liftIO $ boolSystem "mv" [File src, File tmp]
reject = const $ return "wrong file?" reject = const $ return "wrong file?"
cleanup :: Key -> CommandCleanup cleanup :: Key -> CommandCleanup
cleanup key = do cleanup key = do

View file

@ -114,10 +114,10 @@ nojson a _ = a
showStat :: Stat -> StatState () showStat :: Stat -> StatState ()
showStat s = maybe noop calc =<< s showStat s = maybe noop calc =<< s
where where
calc (desc, a) = do calc (desc, a) = do
(lift . showHeader) desc (lift . showHeader) desc
lift . showRaw =<< a lift . showRaw =<< a
supported_backends :: Stat supported_backends :: Stat
supported_backends = stat "supported backends" $ json unwords $ supported_backends = stat "supported backends" $ json unwords $
@ -133,8 +133,8 @@ remote_list level = stat n $ nojson $ lift $ do
rs <- fst <$> trustPartition level us rs <- fst <$> trustPartition level us
s <- prettyPrintUUIDs n rs s <- prettyPrintUUIDs n rs
return $ if null s then "0" else show (length rs) ++ "\n" ++ beginning s return $ if null s then "0" else show (length rs) ++ "\n" ++ beginning s
where where
n = showTrustLevel level ++ " repositories" n = showTrustLevel level ++ " repositories"
local_annex_size :: Stat local_annex_size :: Stat
local_annex_size = stat "local annex size" $ json id $ local_annex_size = stat "local annex size" $ json id $
@ -182,42 +182,42 @@ transfer_list = stat "transfers in progress" $ nojson $ lift $ do
then return "none" then return "none"
else return $ multiLine $ else return $ multiLine $
map (\(t, i) -> line uuidmap t i) $ sort ts map (\(t, i) -> line uuidmap t i) $ sort ts
where where
line uuidmap t i = unwords line uuidmap t i = unwords
[ showLcDirection (transferDirection t) ++ "ing" [ showLcDirection (transferDirection t) ++ "ing"
, fromMaybe (key2file $ transferKey t) (associatedFile i) , fromMaybe (key2file $ transferKey t) (associatedFile i)
, if transferDirection t == Upload then "to" else "from" , if transferDirection t == Upload then "to" else "from"
, maybe (fromUUID $ transferUUID t) Remote.name $ , maybe (fromUUID $ transferUUID t) Remote.name $
M.lookup (transferUUID t) uuidmap M.lookup (transferUUID t) uuidmap
] ]
disk_size :: Stat disk_size :: Stat
disk_size = stat "available local disk space" $ json id $ lift $ disk_size = stat "available local disk space" $ json id $ lift $
calcfree calcfree
<$> getDiskReserve <$> getDiskReserve
<*> inRepo (getDiskFree . gitAnnexDir) <*> inRepo (getDiskFree . gitAnnexDir)
where where
calcfree reserve (Just have) = unwords calcfree reserve (Just have) = unwords
[ roughSize storageUnits False $ nonneg $ have - reserve [ roughSize storageUnits False $ nonneg $ have - reserve
, "(+" ++ roughSize storageUnits False reserve , "(+" ++ roughSize storageUnits False reserve
, "reserved)" , "reserved)"
] ]
calcfree _ _ = "unknown"
calcfree _ _ = "unknown"
nonneg x nonneg x
| x >= 0 = x | x >= 0 = x
| otherwise = 0 | otherwise = 0
backend_usage :: Stat backend_usage :: Stat
backend_usage = stat "backend usage" $ nojson $ backend_usage = stat "backend usage" $ nojson $
calc calc
<$> (backendsKeys <$> cachedReferencedData) <$> (backendsKeys <$> cachedReferencedData)
<*> (backendsKeys <$> cachedPresentData) <*> (backendsKeys <$> cachedPresentData)
where where
calc x y = multiLine $ calc x y = multiLine $
map (\(n, b) -> b ++ ": " ++ show n) $ map (\(n, b) -> b ++ ": " ++ show n) $
reverse $ sort $ map swap $ M.toList $ reverse $ sort $ map swap $ M.toList $
M.unionWith (+) x y M.unionWith (+) x y
cachedPresentData :: StatState KeyData cachedPresentData :: StatState KeyData
cachedPresentData = do cachedPresentData = do
@ -249,39 +249,38 @@ foldKeys = foldl' (flip addKey) emptyKeyData
addKey :: Key -> KeyData -> KeyData addKey :: Key -> KeyData -> KeyData
addKey key (KeyData count size unknownsize backends) = addKey key (KeyData count size unknownsize backends) =
KeyData count' size' unknownsize' backends' KeyData count' size' unknownsize' backends'
where where
{- All calculations strict to avoid thunks when repeatedly {- All calculations strict to avoid thunks when repeatedly
- applied to many keys. -} - applied to many keys. -}
!count' = count + 1 !count' = count + 1
!backends' = M.insertWith' (+) (keyBackendName key) 1 backends !backends' = M.insertWith' (+) (keyBackendName key) 1 backends
!size' = maybe size (+ size) ks !size' = maybe size (+ size) ks
!unknownsize' = maybe (unknownsize + 1) (const unknownsize) ks !unknownsize' = maybe (unknownsize + 1) (const unknownsize) ks
ks = keySize key ks = keySize key
showSizeKeys :: KeyData -> String showSizeKeys :: KeyData -> String
showSizeKeys d = total ++ missingnote showSizeKeys d = total ++ missingnote
where where
total = roughSize storageUnits False $ sizeKeys d total = roughSize storageUnits False $ sizeKeys d
missingnote missingnote
| unknownSizeKeys d == 0 = "" | unknownSizeKeys d == 0 = ""
| otherwise = aside $ | otherwise = aside $
"+ " ++ show (unknownSizeKeys d) ++ "+ " ++ show (unknownSizeKeys d) ++
" keys of unknown size" " keys of unknown size"
staleSize :: String -> (Git.Repo -> FilePath) -> Stat staleSize :: String -> (Git.Repo -> FilePath) -> Stat
staleSize label dirspec = go =<< lift (Command.Unused.staleKeys dirspec) staleSize label dirspec = go =<< lift (Command.Unused.staleKeys dirspec)
where where
go [] = nostat go [] = nostat
go keys = onsize =<< sum <$> keysizes keys go keys = onsize =<< sum <$> keysizes keys
onsize 0 = nostat onsize 0 = nostat
onsize size = stat label $ onsize size = stat label $
json (++ aside "clean up with git-annex unused") $ json (++ aside "clean up with git-annex unused") $
return $ roughSize storageUnits False size return $ roughSize storageUnits False size
keysizes keys = map (fromIntegral . fileSize) <$> stats keys keysizes keys = map (fromIntegral . fileSize) <$> stats keys
stats keys = do stats keys = do
dir <- lift $ fromRepo dirspec dir <- lift $ fromRepo dirspec
liftIO $ forM keys $ \k -> liftIO $ forM keys $ \k -> getFileStatus (dir </> keyFile k)
getFileStatus (dir </> keyFile k)
aside :: String -> String aside :: String -> String
aside s = " (" ++ s ++ ")" aside s = " (" ++ s ++ ")"

View file

@ -48,8 +48,8 @@ seek rs = do
, [ pushLocal branch ] , [ pushLocal branch ]
, [ pushRemote remote branch | remote <- remotes ] , [ pushRemote remote branch | remote <- remotes ]
] ]
where where
nobranch = error "no branch is checked out" nobranch = error "no branch is checked out"
syncBranch :: Git.Ref -> Git.Ref syncBranch :: Git.Ref -> Git.Ref
syncBranch = Git.Ref.under "refs/heads/synced/" syncBranch = Git.Ref.under "refs/heads/synced/"
@ -59,23 +59,23 @@ remoteBranch remote = Git.Ref.under $ "refs/remotes/" ++ Remote.name remote
syncRemotes :: [String] -> Annex [Remote] syncRemotes :: [String] -> Annex [Remote]
syncRemotes rs = ifM (Annex.getState Annex.fast) ( nub <$> pickfast , wanted ) syncRemotes rs = ifM (Annex.getState Annex.fast) ( nub <$> pickfast , wanted )
where where
pickfast = (++) <$> listed <*> (good =<< fastest <$> available) pickfast = (++) <$> listed <*> (good =<< fastest <$> available)
wanted wanted
| null rs = good =<< concat . Remote.byCost <$> available | null rs = good =<< concat . Remote.byCost <$> available
| otherwise = listed | otherwise = listed
listed = do listed = do
l <- catMaybes <$> mapM (Remote.byName . Just) rs l <- catMaybes <$> mapM (Remote.byName . Just) rs
let s = filter Remote.specialRemote l let s = filter Remote.specialRemote l
unless (null s) $ unless (null s) $
error $ "cannot sync special remotes: " ++ error $ "cannot sync special remotes: " ++
unwords (map Types.Remote.name s) unwords (map Types.Remote.name s)
return l return l
available = filter (not . Remote.specialRemote) available = filter (not . Remote.specialRemote)
<$> (filterM (repoSyncable . Types.Remote.repo) <$> (filterM (repoSyncable . Types.Remote.repo)
=<< Remote.enabledRemoteList) =<< Remote.enabledRemoteList)
good = filterM $ Remote.Git.repoAvail . Types.Remote.repo good = filterM $ Remote.Git.repoAvail . Types.Remote.repo
fastest = fromMaybe [] . headMaybe . Remote.byCost fastest = fromMaybe [] . headMaybe . Remote.byCost
commit :: CommandStart commit :: CommandStart
commit = do commit = do
@ -90,16 +90,16 @@ commit = do
mergeLocal :: Git.Ref -> CommandStart mergeLocal :: Git.Ref -> CommandStart
mergeLocal branch = go =<< needmerge mergeLocal branch = go =<< needmerge
where where
syncbranch = syncBranch branch syncbranch = syncBranch branch
needmerge = do needmerge = do
unlessM (inRepo $ Git.Ref.exists syncbranch) $ unlessM (inRepo $ Git.Ref.exists syncbranch) $
inRepo $ updateBranch syncbranch inRepo $ updateBranch syncbranch
inRepo $ Git.Branch.changed branch syncbranch inRepo $ Git.Branch.changed branch syncbranch
go False = stop go False = stop
go True = do go True = do
showStart "merge" $ Git.Ref.describe syncbranch showStart "merge" $ Git.Ref.describe syncbranch
next $ next $ mergeFrom syncbranch next $ next $ mergeFrom syncbranch
pushLocal :: Git.Ref -> CommandStart pushLocal :: Git.Ref -> CommandStart
pushLocal branch = do pushLocal branch = do
@ -109,11 +109,11 @@ pushLocal branch = do
updateBranch :: Git.Ref -> Git.Repo -> IO () updateBranch :: Git.Ref -> Git.Repo -> IO ()
updateBranch syncbranch g = updateBranch syncbranch g =
unlessM go $ error $ "failed to update " ++ show syncbranch unlessM go $ error $ "failed to update " ++ show syncbranch
where where
go = Git.Command.runBool "branch" go = Git.Command.runBool "branch"
[ Param "-f" [ Param "-f"
, Param $ show $ Git.Ref.base syncbranch , Param $ show $ Git.Ref.base syncbranch
] g ] g
pullRemote :: Remote -> Git.Ref -> CommandStart pullRemote :: Remote -> Git.Ref -> CommandStart
pullRemote remote branch = do pullRemote remote branch = do
@ -122,9 +122,9 @@ pullRemote remote branch = do
showOutput showOutput
stopUnless fetch $ stopUnless fetch $
next $ mergeRemote remote (Just branch) next $ mergeRemote remote (Just branch)
where where
fetch = inRepo $ Git.Command.runBool "fetch" fetch = inRepo $ Git.Command.runBool "fetch"
[Param $ Remote.name remote] [Param $ Remote.name remote]
{- The remote probably has both a master and a synced/master branch. {- The remote probably has both a master and a synced/master branch.
- Which to merge from? Well, the master has whatever latest changes - Which to merge from? Well, the master has whatever latest changes
@ -136,22 +136,22 @@ mergeRemote remote b = case b of
branch <- inRepo Git.Branch.currentUnsafe branch <- inRepo Git.Branch.currentUnsafe
all id <$> (mapM merge $ branchlist branch) all id <$> (mapM merge $ branchlist branch)
Just _ -> all id <$> (mapM merge =<< tomerge (branchlist b)) Just _ -> all id <$> (mapM merge =<< tomerge (branchlist b))
where where
merge = mergeFrom . remoteBranch remote merge = mergeFrom . remoteBranch remote
tomerge branches = filterM (changed remote) branches tomerge branches = filterM (changed remote) branches
branchlist Nothing = [] branchlist Nothing = []
branchlist (Just branch) = [branch, syncBranch branch] branchlist (Just branch) = [branch, syncBranch branch]
pushRemote :: Remote -> Git.Ref -> CommandStart pushRemote :: Remote -> Git.Ref -> CommandStart
pushRemote remote branch = go =<< needpush pushRemote remote branch = go =<< needpush
where where
needpush = anyM (newer remote) [syncBranch branch, Annex.Branch.name] needpush = anyM (newer remote) [syncBranch branch, Annex.Branch.name]
go False = stop go False = stop
go True = do go True = do
showStart "push" (Remote.name remote) showStart "push" (Remote.name remote)
next $ next $ do next $ next $ do
showOutput showOutput
inRepo $ pushBranch remote branch inRepo $ pushBranch remote branch
pushBranch :: Remote -> Git.Ref -> Git.Repo -> IO Bool pushBranch :: Remote -> Git.Ref -> Git.Repo -> IO Bool
pushBranch remote branch g = pushBranch remote branch g =
@ -160,12 +160,12 @@ pushBranch remote branch g =
, Param $ refspec Annex.Branch.name , Param $ refspec Annex.Branch.name
, Param $ refspec branch , Param $ refspec branch
] g ] g
where where
refspec b = concat refspec b = concat
[ show $ Git.Ref.base b [ show $ Git.Ref.base b
, ":" , ":"
, show $ Git.Ref.base $ syncBranch b , show $ Git.Ref.base $ syncBranch b
] ]
mergeAnnex :: CommandStart mergeAnnex :: CommandStart
mergeAnnex = do mergeAnnex = do
@ -213,37 +213,37 @@ resolveMerge' u
withKey LsFiles.valUs $ \keyUs -> withKey LsFiles.valUs $ \keyUs ->
withKey LsFiles.valThem $ \keyThem -> go keyUs keyThem withKey LsFiles.valThem $ \keyThem -> go keyUs keyThem
| otherwise = return False | otherwise = return False
where where
go keyUs keyThem go keyUs keyThem
| keyUs == keyThem = do | keyUs == keyThem = do
makelink keyUs makelink keyUs
return True return True
| otherwise = do | otherwise = do
liftIO $ nukeFile file liftIO $ nukeFile file
Annex.Queue.addCommand "rm" [Params "--quiet -f --"] [file] Annex.Queue.addCommand "rm" [Params "--quiet -f --"] [file]
makelink keyUs makelink keyUs
makelink keyThem makelink keyThem
return True return True
file = LsFiles.unmergedFile u file = LsFiles.unmergedFile u
issymlink select = any (select (LsFiles.unmergedBlobType u) ==) issymlink select = any (select (LsFiles.unmergedBlobType 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 <- calcGitLink dest key
liftIO $ do liftIO $ do
nukeFile dest nukeFile dest
createSymbolicLink l dest createSymbolicLink l dest
Annex.Queue.addCommand "add" [Param "--force", Param "--"] [dest] Annex.Queue.addCommand "add" [Param "--force", Param "--"] [dest]
makelink _ = noop makelink _ = noop
withKey select a = do withKey select a = do
let msha = select $ LsFiles.unmergedSha u let msha = select $ LsFiles.unmergedSha u
case msha of case msha of
Nothing -> a Nothing Nothing -> a Nothing
Just sha -> do Just sha -> do
key <- fileKey . takeFileName key <- fileKey . takeFileName
. encodeW8 . L.unpack . encodeW8 . L.unpack
<$> catObject sha <$> catObject sha
maybe (return False) (a . Just) key maybe (return False) (a . Just) key
{- The filename to use when resolving a conflicted merge of a file, {- The filename to use when resolving a conflicted merge of a file,
- that points to a key. - that points to a key.
@ -262,13 +262,13 @@ mergeFile :: FilePath -> Key -> FilePath
mergeFile file key mergeFile file key
| doubleconflict = go $ key2file key | doubleconflict = go $ key2file key
| otherwise = go $ shortHash $ key2file key | otherwise = go $ shortHash $ key2file key
where where
varmarker = ".variant-" varmarker = ".variant-"
doubleconflict = varmarker `isSuffixOf` (dropExtension file) doubleconflict = varmarker `isSuffixOf` (dropExtension file)
go v = takeDirectory file go v = takeDirectory file
</> dropExtension (takeFileName file) </> dropExtension (takeFileName file)
++ varmarker ++ v ++ varmarker ++ v
++ takeExtension file ++ takeExtension file
shortHash :: String -> String shortHash :: String -> String
shortHash = take 4 . md5s . md5FilePath shortHash = take 4 . md5s . md5FilePath

View file

@ -30,10 +30,10 @@ check = do
cwd <- liftIO getCurrentDirectory cwd <- liftIO getCurrentDirectory
whenM ((/=) <$> liftIO (absPath top) <*> liftIO (absPath cwd)) $ whenM ((/=) <$> liftIO (absPath top) <*> liftIO (absPath cwd)) $
error "can only run uninit from the top of the git repository" error "can only run uninit from the top of the git repository"
where where
current_branch = Git.Ref . Prelude.head . lines <$> revhead current_branch = Git.Ref . Prelude.head . lines <$> revhead
revhead = inRepo $ Git.Command.pipeReadStrict revhead = inRepo $ Git.Command.pipeReadStrict
[Params "rev-parse --abbrev-ref HEAD"] [Params "rev-parse --abbrev-ref HEAD"]
seek :: [CommandSeek] seek :: [CommandSeek]
seek = [ seek = [

View file

@ -17,8 +17,8 @@ def =
[ c "unlock" "unlock files for modification" [ c "unlock" "unlock files for modification"
, c "edit" "same as unlock" , c "edit" "same as unlock"
] ]
where where
c n = command n paramPaths seek c n = command n paramPaths seek
seek :: [CommandSeek] seek :: [CommandSeek]
seek = [withFilesInGit $ whenAnnexed start] seek = [withFilesInGit $ whenAnnexed start]

View file

@ -64,27 +64,26 @@ checkUnused = chain 0
, check "bad" staleBadMsg $ staleKeysPrune gitAnnexBadDir , check "bad" staleBadMsg $ staleKeysPrune gitAnnexBadDir
, check "tmp" staleTmpMsg $ staleKeysPrune gitAnnexTmpDir , check "tmp" staleTmpMsg $ staleKeysPrune gitAnnexTmpDir
] ]
where where
findunused True = do findunused True = do
showNote "fast mode enabled; only finding stale files" showNote "fast mode enabled; only finding stale files"
return [] return []
findunused False = do findunused False = do
showAction "checking for unused data" showAction "checking for unused data"
excludeReferenced =<< getKeysPresent excludeReferenced =<< getKeysPresent
chain _ [] = next $ return True chain _ [] = next $ return True
chain v (a:as) = do chain v (a:as) = do
v' <- a v v' <- a v
chain v' as chain v' as
checkRemoteUnused :: String -> CommandPerform checkRemoteUnused :: String -> CommandPerform
checkRemoteUnused name = go =<< fromJust <$> Remote.byName (Just name) checkRemoteUnused name = go =<< fromJust <$> Remote.byName (Just name)
where where
go r = do go r = do
showAction "checking for unused data" showAction "checking for unused data"
_ <- check "" (remoteUnusedMsg r) (remoteunused r) 0 _ <- check "" (remoteUnusedMsg r) (remoteunused r) 0
next $ return True next $ return True
remoteunused r = remoteunused r = excludeReferenced <=< loggedKeysFor $ Remote.uuid r
excludeReferenced <=< loggedKeysFor $ Remote.uuid r
check :: FilePath -> ([(Int, Key)] -> String) -> Annex [Key] -> Int -> Annex Int check :: FilePath -> ([(Int, Key)] -> String) -> Annex [Key] -> Int -> Annex Int
check file msg a c = do check file msg a c = do
@ -100,9 +99,9 @@ number n (x:xs) = (n+1, x) : number (n+1) xs
table :: [(Int, Key)] -> [String] table :: [(Int, Key)] -> [String]
table l = " NUMBER KEY" : map cols l table l = " NUMBER KEY" : map cols l
where where
cols (n,k) = " " ++ pad 6 (show n) ++ " " ++ key2file k cols (n,k) = " " ++ pad 6 (show n) ++ " " ++ key2file k
pad n s = s ++ replicate (n - length s) ' ' pad n s = s ++ replicate (n - length s) ' '
staleTmpMsg :: [(Int, Key)] -> String staleTmpMsg :: [(Int, Key)] -> String
staleTmpMsg t = unlines $ staleTmpMsg t = unlines $
@ -129,8 +128,8 @@ remoteUnusedMsg :: Remote -> [(Int, Key)] -> String
remoteUnusedMsg r u = unusedMsg' u remoteUnusedMsg r u = unusedMsg' u
["Some annexed data on " ++ name ++ " is not used by any files:"] ["Some annexed data on " ++ name ++ " is not used by any files:"]
[dropMsg $ Just r] [dropMsg $ Just r]
where where
name = Remote.name r name = Remote.name r
dropMsg :: Maybe Remote -> String dropMsg :: Maybe Remote -> String
dropMsg Nothing = dropMsg' "" dropMsg Nothing = dropMsg' ""
@ -159,11 +158,11 @@ dropMsg' s = "\nTo remove unwanted data: git-annex dropunused" ++ s ++ " NUMBER\
-} -}
excludeReferenced :: [Key] -> Annex [Key] excludeReferenced :: [Key] -> Annex [Key]
excludeReferenced ks = runfilter firstlevel ks >>= runfilter secondlevel excludeReferenced ks = runfilter firstlevel ks >>= runfilter secondlevel
where where
runfilter _ [] = return [] -- optimisation runfilter _ [] = return [] -- optimisation
runfilter a l = bloomFilter show l <$> genBloomFilter show a runfilter a l = bloomFilter show l <$> genBloomFilter show a
firstlevel = withKeysReferencedM firstlevel = withKeysReferencedM
secondlevel = withKeysReferencedInGit secondlevel = withKeysReferencedInGit
{- Finds items in the first, smaller list, that are not {- Finds items in the first, smaller list, that are not
- present in the second, larger list. - present in the second, larger list.
@ -174,8 +173,8 @@ excludeReferenced ks = runfilter firstlevel ks >>= runfilter secondlevel
exclude :: Ord a => [a] -> [a] -> [a] exclude :: Ord a => [a] -> [a] -> [a]
exclude [] _ = [] -- optimisation exclude [] _ = [] -- optimisation
exclude smaller larger = S.toList $ remove larger $ S.fromList smaller exclude smaller larger = S.toList $ remove larger $ S.fromList smaller
where where
remove a b = foldl (flip S.delete) b a remove a b = foldl (flip S.delete) b a
{- A bloom filter capable of holding half a million keys with a {- A bloom filter capable of holding half a million keys with a
- false positive rate of 1 in 1000 uses around 8 mb of memory, - false positive rate of 1 in 1000 uses around 8 mb of memory,
@ -208,8 +207,8 @@ genBloomFilter convert populate = do
bloom <- lift $ newMB (cheapHashes numhashes) numbits bloom <- lift $ newMB (cheapHashes numhashes) numbits
_ <- populate $ \v -> lift $ insertMB bloom (convert v) _ <- populate $ \v -> lift $ insertMB bloom (convert v)
lift $ unsafeFreezeMB bloom lift $ unsafeFreezeMB bloom
where where
lift = liftIO . stToIO lift = liftIO . stToIO
bloomFilter :: Hashable t => (v -> t) -> [v] -> Bloom t -> [v] bloomFilter :: Hashable t => (v -> t) -> [v] -> Bloom t -> [v]
bloomFilter convert l bloom = filter (\k -> convert k `notElemB` bloom) l bloomFilter convert l bloom = filter (\k -> convert k `notElemB` bloom) l
@ -218,14 +217,14 @@ bloomFilter convert l bloom = filter (\k -> convert k `notElemB` bloom) l
- symlinks in the git repo. -} - symlinks in the git repo. -}
withKeysReferenced :: v -> (Key -> v -> v) -> Annex v withKeysReferenced :: v -> (Key -> v -> v) -> Annex v
withKeysReferenced initial a = withKeysReferenced' initial folda withKeysReferenced initial a = withKeysReferenced' initial folda
where where
folda k v = return $ a k v folda k v = return $ a k v
{- Runs an action on each referenced key in the git repo. -} {- Runs an action on each referenced key in the git repo. -}
withKeysReferencedM :: (Key -> Annex ()) -> Annex () withKeysReferencedM :: (Key -> Annex ()) -> Annex ()
withKeysReferencedM a = withKeysReferenced' () calla withKeysReferencedM a = withKeysReferenced' () calla
where where
calla k _ = a k calla k _ = a k
withKeysReferenced' :: v -> (Key -> v -> Annex v) -> Annex v withKeysReferenced' :: v -> (Key -> v -> Annex v) -> Annex v
withKeysReferenced' initial a = do withKeysReferenced' initial a = do
@ -233,54 +232,53 @@ withKeysReferenced' initial a = do
r <- go initial files r <- go initial files
liftIO $ void clean liftIO $ void clean
return r return r
where where
getfiles = ifM isBareRepo getfiles = ifM isBareRepo
( return ([], return True) ( return ([], return True)
, do , do
top <- fromRepo Git.repoPath top <- fromRepo Git.repoPath
inRepo $ LsFiles.inRepo [top] inRepo $ LsFiles.inRepo [top]
) )
go v [] = return v go v [] = return v
go v (f:fs) = do go v (f:fs) = do
x <- Backend.lookupFile f x <- Backend.lookupFile f
case x of case x of
Nothing -> go v fs Nothing -> go v fs
Just (k, _) -> do Just (k, _) -> do
!v' <- a k v !v' <- a k v
go v' fs go v' fs
withKeysReferencedInGit :: (Key -> Annex ()) -> Annex () withKeysReferencedInGit :: (Key -> Annex ()) -> Annex ()
withKeysReferencedInGit a = do withKeysReferencedInGit a = do
rs <- relevantrefs <$> showref rs <- relevantrefs <$> showref
forM_ rs (withKeysReferencedInGitRef a) forM_ rs (withKeysReferencedInGitRef a)
where where
showref = inRepo $ Git.Command.pipeReadStrict [Param "show-ref"] showref = inRepo $ Git.Command.pipeReadStrict [Param "show-ref"]
relevantrefs = map (Git.Ref . snd) . relevantrefs = map (Git.Ref . snd) .
nubBy uniqref . nubBy uniqref .
filter ourbranches . filter ourbranches .
map (separate (== ' ')) . lines map (separate (== ' ')) . lines
uniqref (x, _) (y, _) = x == y uniqref (x, _) (y, _) = x == y
ourbranchend = '/' : show Annex.Branch.name ourbranchend = '/' : show Annex.Branch.name
ourbranches (_, b) = not (ourbranchend `isSuffixOf` b) ourbranches (_, b) = not (ourbranchend `isSuffixOf` b)
&& not ("refs/synced/" `isPrefixOf` b) && not ("refs/synced/" `isPrefixOf` b)
withKeysReferencedInGitRef :: (Key -> Annex ()) -> Git.Ref -> Annex () withKeysReferencedInGitRef :: (Key -> Annex ()) -> Git.Ref -> Annex ()
withKeysReferencedInGitRef a ref = do withKeysReferencedInGitRef a ref = do
showAction $ "checking " ++ Git.Ref.describe ref showAction $ "checking " ++ Git.Ref.describe ref
go <=< inRepo $ LsTree.lsTree ref go <=< inRepo $ LsTree.lsTree ref
where where
go [] = noop go [] = noop
go (l:ls) go (l:ls)
| isSymLink (LsTree.mode l) = do | isSymLink (LsTree.mode l) = do
content <- encodeW8 . L.unpack content <- encodeW8 . L.unpack
<$> catFile ref (LsTree.file l) <$> catFile ref (LsTree.file l)
case fileKey (takeFileName content) of case fileKey (takeFileName content) of
Nothing -> go ls Nothing -> go ls
Just k -> do Just k -> do
a k a k
go ls go ls
| otherwise = go ls | otherwise = go ls
{- Looks in the specified directory for bad/tmp keys, and returns a list {- Looks in the specified directory for bad/tmp keys, and returns a list
- of those that might still have value, or might be stale and removable. - of those that might still have value, or might be stale and removable.

View file

@ -29,8 +29,8 @@ start = do
putStrLn $ "supported repository versions: " ++ vs supportedVersions putStrLn $ "supported repository versions: " ++ vs supportedVersions
putStrLn $ "upgrade supported from repository versions: " ++ vs upgradableVersions putStrLn $ "upgrade supported from repository versions: " ++ vs upgradableVersions
stop stop
where where
vs = join " " vs = join " "
showPackageVersion :: IO () showPackageVersion :: IO ()
showPackageVersion = putStrLn $ "git-annex version: " ++ SysConfig.packageversion showPackageVersion = putStrLn $ "git-annex version: " ++ SysConfig.packageversion

View file

@ -75,119 +75,116 @@ setCfg curcfg newcfg = do
diffCfg :: Cfg -> Cfg -> (TrustMap, M.Map UUID (S.Set Group), M.Map UUID String) diffCfg :: Cfg -> Cfg -> (TrustMap, M.Map UUID (S.Set Group), M.Map UUID String)
diffCfg curcfg newcfg = (diff cfgTrustMap, diff cfgGroupMap, diff cfgPreferredContentMap) diffCfg curcfg newcfg = (diff cfgTrustMap, diff cfgGroupMap, diff cfgPreferredContentMap)
where where
diff f = M.differenceWith (\x y -> if x == y then Nothing else Just x) diff f = M.differenceWith (\x y -> if x == y then Nothing else Just x)
(f newcfg) (f curcfg) (f newcfg) (f curcfg)
genCfg :: Cfg -> M.Map UUID String -> String genCfg :: Cfg -> M.Map UUID String -> String
genCfg cfg descs = unlines $ concat [intro, trust, groups, preferredcontent] genCfg cfg descs = unlines $ concat [intro, trust, groups, preferredcontent]
where where
intro = intro =
[ com "git-annex configuration" [ com "git-annex configuration"
, com "" , com ""
, com "Changes saved to this file will be recorded in the git-annex branch." , com "Changes saved to this file will be recorded in the git-annex branch."
, com "" , com ""
, com "Lines in this file have the format:" , com "Lines in this file have the format:"
, com " setting uuid = value" , com " setting uuid = value"
] ]
trust = settings cfgTrustMap trust = settings cfgTrustMap
[ "" [ ""
, com "Repository trust configuration" , com "Repository trust configuration"
, com "(Valid trust levels: " ++ , com "(Valid trust levels: " ++
unwords (map showTrustLevel [Trusted .. DeadTrusted]) ++ unwords (map showTrustLevel [Trusted .. DeadTrusted]) ++
")" ")"
] ]
(\(t, u) -> line "trust" u $ showTrustLevel t) (\(t, u) -> line "trust" u $ showTrustLevel t)
(\u -> lcom $ line "trust" u $ showTrustLevel SemiTrusted) (\u -> lcom $ line "trust" u $ showTrustLevel SemiTrusted)
groups = settings cfgGroupMap groups = settings cfgGroupMap
[ "" [ ""
, com "Repository groups" , com "Repository groups"
, com "(Separate group names with spaces)" , com "(Separate group names with spaces)"
] ]
(\(s, u) -> line "group" u $ unwords $ S.toList s) (\(s, u) -> line "group" u $ unwords $ S.toList s)
(\u -> lcom $ line "group" u "") (\u -> lcom $ line "group" u "")
preferredcontent = settings cfgPreferredContentMap preferredcontent = settings cfgPreferredContentMap
[ "" [ ""
, com "Repository preferred contents" , com "Repository preferred contents"
] ]
(\(s, u) -> line "preferred-content" u s) (\(s, u) -> line "preferred-content" u s)
(\u -> line "preferred-content" u "") (\u -> line "preferred-content" u "")
settings field desc showvals showdefaults = concat settings field desc showvals showdefaults = concat
[ desc [ desc
, concatMap showvals $ , concatMap showvals $ sort $ map swap $ M.toList $ field cfg
sort $ map swap $ M.toList $ field cfg , concatMap (\u -> lcom $ showdefaults u) $ missing field
, concatMap (\u -> lcom $ showdefaults u) $ ]
missing field
]
line setting u value = line setting u value =
[ com $ "(for " ++ (fromMaybe "" $ M.lookup u descs) ++ ")" [ com $ "(for " ++ (fromMaybe "" $ M.lookup u descs) ++ ")"
, unwords [setting, fromUUID u, "=", value] , unwords [setting, fromUUID u, "=", value]
] ]
lcom = map (\l -> if "#" `isPrefixOf` l then l else "#" ++ l) lcom = map (\l -> if "#" `isPrefixOf` l then l else "#" ++ l)
missing field = S.toList $ M.keysSet descs `S.difference` M.keysSet (field cfg) missing field = S.toList $ M.keysSet descs `S.difference` M.keysSet (field cfg)
{- If there's a parse error, returns a new version of the file, {- If there's a parse error, returns a new version of the file,
- with the problem lines noted. -} - with the problem lines noted. -}
parseCfg :: Cfg -> String -> Either String Cfg parseCfg :: Cfg -> String -> Either String Cfg
parseCfg curcfg = go [] curcfg . lines parseCfg curcfg = go [] curcfg . lines
where where
go c cfg [] go c cfg []
| null (catMaybes $ map fst c) = Right cfg | null (catMaybes $ map fst c) = Right cfg
| otherwise = Left $ unlines $ | otherwise = Left $ unlines $
badheader ++ concatMap showerr (reverse c) badheader ++ concatMap showerr (reverse c)
go c cfg (l:ls) = case parse (dropWhile isSpace l) cfg of go c cfg (l:ls) = case parse (dropWhile isSpace l) cfg of
Left msg -> go ((Just msg, l):c) cfg ls Left msg -> go ((Just msg, l):c) cfg ls
Right cfg' -> go ((Nothing, l):c) cfg' ls Right cfg' -> go ((Nothing, l):c) cfg' ls
parse l cfg parse l cfg
| null l = Right cfg | null l = Right cfg
| "#" `isPrefixOf` l = Right cfg | "#" `isPrefixOf` l = Right cfg
| null setting || null u = Left "missing repository uuid" | null setting || null u = Left "missing repository uuid"
| otherwise = handle cfg (toUUID u) setting value' | otherwise = handle cfg (toUUID u) setting value'
where where
(setting, rest) = separate isSpace l (setting, rest) = separate isSpace l
(r, value) = separate (== '=') rest (r, value) = separate (== '=') rest
value' = trimspace value value' = trimspace value
u = reverse $ trimspace $ u = reverse $ trimspace $ reverse $ trimspace r
reverse $ trimspace r trimspace = dropWhile isSpace
trimspace = dropWhile isSpace
handle cfg u setting value handle cfg u setting value
| setting == "trust" = case readTrustLevel value of | setting == "trust" = case readTrustLevel value of
Nothing -> badval "trust value" value Nothing -> badval "trust value" value
Just t -> Just t ->
let m = M.insert u t (cfgTrustMap cfg) let m = M.insert u t (cfgTrustMap cfg)
in Right $ cfg { cfgTrustMap = m } in Right $ cfg { cfgTrustMap = m }
| setting == "group" = | setting == "group" =
let m = M.insert u (S.fromList $ words value) (cfgGroupMap cfg) let m = M.insert u (S.fromList $ words value) (cfgGroupMap cfg)
in Right $ cfg { cfgGroupMap = m } in Right $ cfg { cfgGroupMap = m }
| setting == "preferred-content" = | setting == "preferred-content" =
case checkPreferredContentExpression value of case checkPreferredContentExpression value of
Just e -> Left e Just e -> Left e
Nothing -> Nothing ->
let m = M.insert u value (cfgPreferredContentMap cfg) let m = M.insert u value (cfgPreferredContentMap cfg)
in Right $ cfg { cfgPreferredContentMap = m } in Right $ cfg { cfgPreferredContentMap = m }
| otherwise = badval "setting" setting | otherwise = badval "setting" setting
showerr (Just msg, l) = [parseerr ++ msg, l] showerr (Just msg, l) = [parseerr ++ msg, l]
showerr (Nothing, l) showerr (Nothing, l)
-- filter out the header and parse error lines -- filter out the header and parse error lines
-- from any previous parse failure -- from any previous parse failure
| any (`isPrefixOf` l) (parseerr:badheader) = [] | any (`isPrefixOf` l) (parseerr:badheader) = []
| otherwise = [l] | otherwise = [l]
badval desc val = Left $ "unknown " ++ desc ++ " \"" ++ val ++ "\"" badval desc val = Left $ "unknown " ++ desc ++ " \"" ++ val ++ "\""
badheader = badheader =
[ com "There was a problem parsing your input." [ com "There was a problem parsing your input."
, com "Search for \"Parse error\" to find the bad lines." , com "Search for \"Parse error\" to find the bad lines."
, com "Either fix the bad lines, or delete them (to discard your changes)." , com "Either fix the bad lines, or delete them (to discard your changes)."
] ]
parseerr = com "Parse error in next line: " parseerr = com "Parse error in next line: "
com :: String -> String com :: String -> String
com s = "# " ++ s com s = "# " ++ s

View file

@ -43,24 +43,24 @@ start' allowauto = notBareRepo $ do
liftIO $ ensureInstalled liftIO $ ensureInstalled
ifM isInitialized ( go , auto ) ifM isInitialized ( go , auto )
stop stop
where where
go = do go = do
browser <- fromRepo webBrowser browser <- fromRepo webBrowser
f <- liftIO . absPath =<< fromRepo gitAnnexHtmlShim f <- liftIO . absPath =<< fromRepo gitAnnexHtmlShim
ifM (checkpid <&&> checkshim f) ifM (checkpid <&&> checkshim f)
( liftIO $ openBrowser browser f ( liftIO $ openBrowser browser f
, startDaemon True True $ Just $ , startDaemon True True $ Just $
const $ openBrowser browser const $ openBrowser browser
) )
auto auto
| allowauto = liftIO startNoRepo | allowauto = liftIO startNoRepo
| otherwise = do | otherwise = do
d <- liftIO getCurrentDirectory d <- liftIO getCurrentDirectory
error $ "no git repository in " ++ d error $ "no git repository in " ++ d
checkpid = do checkpid = do
pidfile <- fromRepo gitAnnexPidFile pidfile <- fromRepo gitAnnexPidFile
liftIO $ isJust <$> checkDaemon pidfile liftIO $ isJust <$> checkDaemon pidfile
checkshim f = liftIO $ doesFileExist f checkshim f = liftIO $ doesFileExist f
{- When run without a repo, see if there is an autoStartFile, {- When run without a repo, see if there is an autoStartFile,
- and if so, start the first available listed repository. - and if so, start the first available listed repository.
@ -111,35 +111,35 @@ firstRun = do
webAppThread d urlrenderer True webAppThread d urlrenderer True
(callback signaler) (callback signaler)
(callback mainthread) (callback mainthread)
where where
signaler v = do signaler v = do
putMVar v "" putMVar v ""
takeMVar v takeMVar v
mainthread v _url htmlshim = do mainthread v _url htmlshim = do
browser <- maybe Nothing webBrowser <$> Git.Config.global browser <- maybe Nothing webBrowser <$> Git.Config.global
openBrowser browser htmlshim openBrowser browser htmlshim
_wait <- takeMVar v _wait <- takeMVar v
state <- Annex.new =<< Git.CurrentRepo.get state <- Annex.new =<< Git.CurrentRepo.get
Annex.eval state $ do Annex.eval state $ do
dummydaemonize dummydaemonize
startAssistant True id $ Just $ sendurlback v startAssistant True id $ Just $ sendurlback v
sendurlback v url _htmlshim = putMVar v url sendurlback v url _htmlshim = putMVar v url
{- Set up the pid file in the new repo. -}
dummydaemonize = {- Set up the pid file in the new repo. -}
liftIO . lockPidFile =<< fromRepo gitAnnexPidFile dummydaemonize = liftIO . lockPidFile =<< fromRepo gitAnnexPidFile
openBrowser :: Maybe FilePath -> FilePath -> IO () openBrowser :: Maybe FilePath -> FilePath -> IO ()
openBrowser cmd htmlshim = go $ maybe runBrowser runCustomBrowser cmd openBrowser cmd htmlshim = go $ maybe runBrowser runCustomBrowser cmd
where where
url = fileUrl htmlshim url = fileUrl htmlshim
go a = do go a = do
putStrLn "" putStrLn ""
putStrLn $ "Launching web browser on " ++ url putStrLn $ "Launching web browser on " ++ url
unlessM (a url) $ unlessM (a url) $
error $ "failed to start web browser" error $ "failed to start web browser"
runCustomBrowser c u = boolSystem c [Param u] runCustomBrowser c u = boolSystem c [Param u]
{- web.browser is a generic git config setting for a web browser program -} {- web.browser is a generic git config setting for a web browser program -}
webBrowser :: Git.Repo -> Maybe FilePath webBrowser :: Git.Repo -> Maybe FilePath

View file

@ -40,15 +40,15 @@ perform remotemap key = do
forM_ (mapMaybe (`M.lookup` remotemap) locations) $ forM_ (mapMaybe (`M.lookup` remotemap) locations) $
performRemote key performRemote key
if null safelocations then stop else next $ return True if null safelocations then stop else next $ return True
where where
copiesplural 1 = "copy" copiesplural 1 = "copy"
copiesplural _ = "copies" copiesplural _ = "copies"
untrustedheader = "The following untrusted locations may also have copies:\n" untrustedheader = "The following untrusted locations may also have copies:\n"
performRemote :: Key -> Remote -> Annex () performRemote :: Key -> Remote -> Annex ()
performRemote key remote = maybe noop go $ whereisKey remote performRemote key remote = maybe noop go $ whereisKey remote
where where
go a = do go a = do
ls <- a key ls <- a key
unless (null ls) $ showLongNote $ unlines $ unless (null ls) $ showLongNote $ unlines $
map (\l -> name remote ++ ": " ++ l) ls map (\l -> name remote ++ ": " ++ l) ls