git-annex 3.20111231 → 3.20120113
raw patch · 116 files changed
+1867/−1040 lines, 116 filesdep +quickcheckbinary-added
Dependencies added: quickcheck
Files
- .gitignore +0/−1
- Annex.hs +28/−10
- Annex/Branch.hs +4/−3
- Annex/Content.hs +10/−1
- Annex/Ssh.hs +0/−65
- CHANGELOG +37/−0
- Checks.hs +3/−14
- CmdLine.hs +15/−26
- Command.hs +10/−4
- Command/AddUrl.hs +1/−2
- Command/Copy.hs +8/−6
- Command/Drop.hs +10/−7
- Command/DropUnused.hs +7/−5
- Command/Find.hs +21/−8
- Command/Fsck.hs +4/−4
- Command/Get.hs +6/−8
- Command/Log.hs +172/−0
- Command/Map.hs +2/−1
- Command/Move.hs +18/−13
- Command/Status.hs +2/−2
- Command/Sync.hs +1/−1
- Command/Unused.hs +8/−4
- Command/Whereis.hs +0/−1
- Config.hs +6/−4
- Git.hs +2/−2
- Git/Config.hs +4/−0
- Git/Construct.hs +46/−6
- Git/Sha.hs +3/−0
- Git/UnionMerge.hs +1/−2
- GitAnnex.hs +7/−17
- INSTALL +4/−1
- Limit.hs +2/−3
- Logs/Location.hs +4/−10
- Logs/Presence.hs +6/−1
- Logs/Trust.hs +30/−15
- Makefile +11/−19
- Option.hs +79/−0
- Options.hs +0/−96
- Remote.hs +46/−74
- Remote/Bup.hs +1/−1
- Remote/Git.hs +7/−14
- Remote/Helper/Ssh.hs +65/−0
- Remote/List.hs +58/−0
- Remote/Rsync.hs +1/−3
- Remote/S3.hs +311/−0
- Remote/S3real.hs +0/−311
- Remote/S3stub.hs +0/−13
- Remote/Web.hs +2/−1
- Seek.hs +31/−21
- Types.hs +3/−1
- Types/Command.hs +9/−8
- Types/Option.hs +17/−0
- Upgrade.hs +6/−8
- Usage.hs +88/−0
- Utility/Gpg.hs +6/−2
- Utility/Monad.hs +6/−3
- Utility/Path.hs +11/−0
- Utility/Url.hs +7/−6
- debian/changelog +37/−0
- debian/control +2/−1
- debian/copyright +1/−1
- doc/NixOS.mdwn +5/−0
- doc/bugs/Lost_S3_Remote.mdwn +59/−0
- doc/bugs/Lost_S3_Remote/comment_1_6e80e6db6671581d471fc9a54181c04c._comment +10/−0
- doc/bugs/Lost_S3_Remote/comment_2_c99c65882a3924f4890e500f9492b442._comment +8/−0
- doc/bugs/Lost_S3_Remote/comment_3_1e434d5a20a692cd9dc7f6f8f20f30dd._comment +8/−0
- doc/bugs/__34__make_test__34___fails_silently.mdwn +4/−0
- doc/bugs/conq:_invalid_command_syntax.mdwn +30/−0
- doc/bugs/conq:_invalid_command_syntax/comment_1_f33b83025ce974e496f83f248275a66a._comment +10/−0
- doc/bugs/conq:_invalid_command_syntax/comment_2_195106ca8dedad5f4d755f625e38e8af._comment +9/−0
- doc/bugs/conq:_invalid_command_syntax/comment_3_55af43e2f43a4c373f7a0a33678d0b1c._comment +15/−0
- doc/bugs/on--git-dir_and_--work-tree_options.mdwn +2/−0
- doc/bugs/signal_weirdness.mdwn +38/−0
- doc/feeds.mdwn +2/−0
- doc/forum/Auto_archiving.mdwn +17/−0
- doc/forum/Handling_web_special_remote_when_content_changes__63__.mdwn +19/−0
- doc/forum/git-subtree_support__63__.mdwn +9/−0
- doc/forum/git-subtree_support__63__/comment_1_4f333cb71ed1ff259bbfd86704806aa6._comment +10/−0
- doc/forum/git-subtree_support__63__/comment_2_73d2a015b1ac79ec99e071a8b1e29034._comment +8/−0
- doc/forum/git-subtree_support__63__/comment_3_c533400e22c306c033fcd56e64761b0b._comment +8/−0
- doc/forum/git-subtree_support__63__/comment_4_75b0e072e668aa46ff0a8d62a6620306._comment +8/−0
- doc/forum/git-subtree_support__63__/comment_5_f5ec9649d9f1dc122e715de5533bc674._comment +8/−0
- doc/forum/git-subtree_support__63__/comment_6_85df530f7b6d76b74ac8017c6034f95e._comment +8/−0
- doc/forum/unlock__47__lock_always_gets_me.mdwn +11/−0
- doc/forum/unlock__47__lock_always_gets_me/comment_1_dee73a7ea3e1a5154601adb59782831f._comment +12/−0
- doc/git-annex.mdwn +31/−6
- doc/how_it_works.mdwn +41/−0
- doc/index.mdwn +4/−2
- doc/install.mdwn +4/−1
- doc/install/ArchLinux.mdwn +9/−0
- doc/install/comment_3_cff163ea3e7cad926f4ed9e78b896598._comment +0/−10
- doc/install/comment_4_82a17eee4a076c6c79fddeda347e0c9a._comment +0/−69
- doc/news.mdwn +1/−1
- doc/news/version_3.20111107.mdwn +0/−8
- doc/news/version_3.20111111.mdwn +0/−10
- doc/news/version_3.20111122.mdwn +0/−22
- doc/news/version_3.20111122~bpo60+2.mdwn +0/−22
- doc/news/version_3.20111203.mdwn +0/−19
- doc/news/version_3.20111211.mdwn +0/−20
- doc/news/version_3.20120105.mdwn +14/−0
- doc/news/version_3.20120106.mdwn +6/−0
- doc/news/version_3.20120106/comment_1_fb1a3135e2d9f39f2c372ccc2c50c85a._comment +8/−0
- doc/news/version_3.20120106/comment_2_ae292ca7294b6790233e545086c3ac2f._comment +10/−0
- doc/news/version_3.20120106/comment_3_29ccda9ac458fd5cc9ec5508c62df6ea._comment +12/−0
- doc/news/version_3.20120113.mdwn +8/−0
- doc/news/version_backport.mdwn +0/−6
- doc/sitemap.mdwn +3/−0
- doc/tips/using_gitolite_with_git-annex/comment_9_28418635a6ed7231b89e02211cd3c236._comment +8/−0
- doc/tips/visualizing_repositories_with_gource.mdwn +22/−0
- doc/tips/visualizing_repositories_with_gource/screenshot.jpg binary
- doc/todo/windows_support.mdwn +65/−0
- doc/transferring_data.mdwn +1/−1
- git-annex-shell.hs +5/−2
- git-annex.cabal +3/−3
- git-union-merge.hs +3/−5
- test.hs +4/−3
.gitignore view
@@ -15,5 +15,4 @@ .hpc Utility/Touch.hs Utility/StatFS.hs-Remote/S3.hs dist
Annex.hs view
@@ -17,6 +17,10 @@ eval, getState, changeState,+ setFlag,+ setField,+ getFlag,+ getField, gitRepo, inRepo, fromRepo,@@ -36,9 +40,7 @@ import Types.Crypto import Types.BranchState import Types.TrustLevel-import Types.UUID import qualified Utility.Matcher-import qualified Utility.Format import qualified Data.Map as M -- git-annex's monad@@ -76,17 +78,16 @@ , force :: Bool , fast :: Bool , auto :: Bool- , format :: Maybe Utility.Format.Format , branchstate :: BranchState , catfilehandle :: Maybe CatFileHandle , forcebackend :: Maybe String , forcenumcopies :: Maybe Int- , toremote :: Maybe String- , fromremote :: Maybe String , limit :: Matcher (FilePath -> Annex Bool)- , forcetrust :: [(UUID, TrustLevel)]+ , forcetrust :: TrustMap , trustmap :: Maybe TrustMap , ciphers :: M.Map EncryptedCipher Cipher+ , flags :: M.Map String Bool+ , fields :: M.Map String String } newState :: Git.Repo -> AnnexState@@ -99,17 +100,16 @@ , force = False , fast = False , auto = False- , format = Nothing , branchstate = startBranchState , catfilehandle = Nothing , forcebackend = Nothing , forcenumcopies = Nothing- , toremote = Nothing- , fromremote = Nothing , limit = Left []- , forcetrust = []+ , forcetrust = M.empty , trustmap = Nothing , ciphers = M.empty+ , flags = M.empty+ , fields = M.empty } {- Create and returns an Annex state object for the specified git repo. -}@@ -133,6 +133,24 @@ -} changeState :: (AnnexState -> AnnexState) -> Annex () changeState = modify++{- Sets a flag to True -}+setFlag :: String -> Annex ()+setFlag flag = changeState $ \s ->+ s { flags = M.insert flag True $ flags s }++{- Sets a field to a value -}+setField :: String -> String -> Annex ()+setField field value = changeState $ \s ->+ s { fields = M.insert field value $ fields s }++{- Checks if a flag was set. -}+getFlag :: String -> Annex Bool+getFlag flag = fromMaybe False . M.lookup flag <$> getState flags++{- Gets the value of a field. -}+getField :: String -> Annex (Maybe String)+getField field = M.lookup field <$> getState fields {- Returns the annex's git repository. -} gitRepo :: Annex Git.Repo
Annex/Branch.hs view
@@ -6,6 +6,7 @@ -} module Annex.Branch (+ fullname, name, hasOrigin, hasSibling,@@ -67,15 +68,15 @@ return () {- Returns the ref of the branch, creating it first if necessary. -}-getBranch :: Annex (Git.Ref)-getBranch = maybe (hasOrigin >>= go >>= use) (return) =<< branchsha+getBranch :: Annex Git.Ref+getBranch = maybe (hasOrigin >>= go >>= use) return =<< branchsha where go True = do inRepo $ Git.Command.run "branch" [Param $ show name, Param $ show originname] fromMaybe (error $ "failed to create " ++ show name) <$> branchsha- go False = withIndex' True $ do+ go False = withIndex' True $ inRepo $ Git.Branch.commit "branch created" fullname [] use sha = do setIndexSha sha
Annex/Content.hs view
@@ -20,7 +20,8 @@ fromAnnex, moveBad, getKeysPresent,- saveState+ saveState,+ downloadUrl, ) where import System.IO.Error (try)@@ -36,6 +37,7 @@ import qualified Annex.Branch import Utility.StatFS import Utility.FileMode+import qualified Utility.Url as Url import Types.Key import Utility.DataUnits import Config@@ -281,3 +283,10 @@ saveState = do Annex.Queue.flush False Annex.Branch.commit "update"++{- Downloads content from any of a list of urls. -}+downloadUrl :: [Url.URLString] -> FilePath -> Annex Bool+downloadUrl urls file = do+ g <- gitRepo+ o <- map Param . words <$> getConfig g "web-options" ""+ liftIO $ anyM (\u -> Url.download u o file) urls
− Annex/Ssh.hs
@@ -1,65 +0,0 @@-{- git-annex remote access with ssh- -- - Copyright 2011 Joey Hess <joey@kitenet.net>- -- - Licensed under the GNU GPL version 3 or higher.- -}--module Annex.Ssh where--import Common-import qualified Git-import qualified Git.Url-import Types-import Config-import Annex.UUID--{- Generates parameters to ssh to a repository's host and run a command.- - Caller is responsible for doing any neccessary shellEscaping of the- - passed command. -}-sshToRepo :: Git.Repo -> [CommandParam] -> Annex [CommandParam]-sshToRepo repo sshcmd = do- s <- getConfig repo "ssh-options" ""- let sshoptions = map Param (words s)- let sshport = case Git.Url.port repo of- Nothing -> []- Just p -> [Param "-p", Param (show p)]- let sshhost = Param $ Git.Url.hostuser repo- return $ sshoptions ++ sshport ++ [sshhost] ++ sshcmd--{- Generates parameters to run a git-annex-shell command on a remote- - repository. -}-git_annex_shell :: Git.Repo -> String -> [CommandParam] -> Annex (Maybe (FilePath, [CommandParam]))-git_annex_shell r command params- | not $ Git.repoIsUrl r = return $ Just (shellcmd, shellopts)- | Git.repoIsSsh r = do- uuid <- getRepoUUID r- sshparams <- sshToRepo r [Param $ sshcmd uuid ]- return $ Just ("ssh", sshparams)- | otherwise = return Nothing- where- dir = Git.workTree r- shellcmd = "git-annex-shell"- shellopts = Param command : File dir : params- sshcmd uuid = unwords $- shellcmd : map shellEscape (toCommand shellopts) ++- uuidcheck uuid- uuidcheck NoUUID = []- uuidcheck (UUID u) = ["--uuid", u]--{- Uses a supplied function (such as boolSystem) to run a git-annex-shell- - command on a remote.- -- - Or, if the remote does not support running remote commands, returns- - a specified error value. -}-onRemote - :: Git.Repo- -> (FilePath -> [CommandParam] -> IO a, a)- -> String- -> [CommandParam]- -> Annex a-onRemote r (with, errorval) command params = do- s <- git_annex_shell r command params- case s of- Just (c, ps) -> liftIO $ with c ps- Nothing -> return errorval
CHANGELOG view
@@ -1,3 +1,40 @@+git-annex (3.20120113) unstable; urgency=low++ * log: Add --gource mode, which generates output usable by gource.+ * map: Fix display of remote repos+ * Add annex-trustlevel configuration settings, which can be used to + override the trust level of a remote.+ * git-annex, git-union-merge: Support GIT_DIR and GIT_WORK_TREE.+ * Add libghc-testpack-dev to build depends on all arches.++ -- Joey Hess <joeyh@debian.org> Fri, 13 Jan 2012 15:35:17 -0400++git-annex (3.20120106) unstable; urgency=low++ * Support unescaped repository urls, like git does.+ * log: New command that displays the location log for files,+ showing each repository they were added to and removed from.+ * Fix overbroad gpg --no-tty fix from last release.++ -- Joey Hess <joeyh@debian.org> Sat, 07 Jan 2012 13:16:23 -0400++git-annex (3.20120105) unstable; urgency=low++ * Added annex-web-options configuration settings, which can be+ used to provide parameters to whichever of wget or curl git-annex uses+ (depends on which is available, but most of their important options+ suitable for use here are the same).+ * Dotfiles, and files inside dotdirs are not added by "git annex add"+ unless the dotfile or directory is explicitly listed. So "git annex add ."+ will add all untracked files in the current directory except for those in+ dotdirs.+ * Added quickcheck to build dependencies, and fail if test suite cannot be+ built.+ * fsck: Do backend-specific check before checking numcopies is satisfied.+ * Run gpg with --no-tty. Closes: #654721++ -- Joey Hess <joeyh@debian.org> Thu, 05 Jan 2012 13:44:12 -0400+ git-annex (3.20111231) unstable; urgency=low * sync: Improved to work well without a central bare repository.
Checks.hs view
@@ -13,30 +13,19 @@ import Common.Annex import Types.Command import Init-import qualified Annex commonChecks :: [CommandCheck]-commonChecks = [fromOpt, toOpt, repoExists]+commonChecks = [repoExists] repoExists :: CommandCheck repoExists = CommandCheck 0 ensureInitialized -fromOpt :: CommandCheck-fromOpt = CommandCheck 1 $ do- v <- Annex.getState Annex.fromremote- unless (isNothing v) $ error "cannot use --from with this command"--toOpt :: CommandCheck-toOpt = CommandCheck 2 $ do- v <- Annex.getState Annex.toremote- unless (isNothing v) $ error "cannot use --to with this command"- dontCheck :: CommandCheck -> Command -> Command dontCheck check cmd = mutateCheck cmd $ \c -> filter (/= check) c addCheck :: Annex () -> Command -> Command-addCheck check cmd = mutateCheck cmd $- \c -> CommandCheck (length c + 100) check : c+addCheck check cmd = mutateCheck cmd $ \c ->+ CommandCheck (length c + 100) check : c mutateCheck :: Command -> ([CommandCheck] -> [CommandCheck]) -> Command mutateCheck cmd@(Command { cmdcheck = c }) a = cmd { cmdcheck = a c }
CmdLine.hs view
@@ -29,7 +29,7 @@ {- Runs the passed command line. -} dispatch :: Params -> [Command] -> [Option] -> String -> IO Git.Repo -> IO ()-dispatch args cmds options header getgitrepo = do+dispatch args cmds commonoptions header getgitrepo = do setupConsole r <- E.try getgitrepo :: IO (Either E.SomeException Git.Repo) case r of@@ -41,37 +41,26 @@ prepCommand cmd params tryRun state' cmd $ [startup] ++ actions ++ [shutdown] where- (flags, cmd, params) = parseCmd args cmds options header+ (flags, cmd, params) = parseCmd args cmds commonoptions header {- Parses command line, and returns actions to run to configure flags, - the Command being run, and the remaining parameters for the command. -} parseCmd :: Params -> [Command] -> [Option] -> String -> (Flags, Command, Params)-parseCmd argv cmds options header = check $ getOpt Permute options argv+parseCmd argv cmds commonoptions header+ | isNothing name = err "missing command"+ | null matches = err $ "unknown command " ++ fromJust name+ | otherwise = check $ getOpt Permute (commonoptions ++ cmdoptions cmd) args where- check (_, [], []) = err "missing command"- check (flags, name:rest, [])- | null matches = err $ "unknown command " ++ name- | otherwise = (flags, Prelude.head matches, rest)- where- matches = filter (\c -> name == cmdname c) cmds+ (name, args) = findname argv []+ findname [] c = (Nothing, reverse c)+ findname (a:as) c+ | "-" `isPrefixOf` a = findname as (a:c)+ | otherwise = (Just a, reverse c ++ as)+ matches = filter (\c -> name == Just (cmdname c)) cmds+ cmd = Prelude.head matches+ check (flags, rest, []) = (flags, cmd, rest) check (_, _, errs) = err $ concat errs- err msg = error $ msg ++ "\n\n" ++ usage header cmds options--{- Usage message with lists of commands and options. -}-usage :: String -> [Command] -> [Option] -> String-usage header cmds options = usageInfo top options ++ commands- where- top = header ++ "\n\nOptions:"- commands = "\nCommands:\n" ++ cmddescs- cmddescs = unlines $ map (indent . showcmd) cmds- showcmd c =- cmdname c ++- pad (longest cmdname + 1) (cmdname c) ++- cmdparams c ++- pad (longest cmdparams + 2) (cmdparams c) ++- cmddesc c- pad n s = replicate (n - length s) ' '- longest f = foldl max 0 $ map (length . f) cmds+ err msg = error $ msg ++ "\n\n" ++ usage header cmds commonoptions {- Runs a list of Annex actions. Catches IO errors and continues - (but explicitly thrown errors terminate the whole command).
Command.hs view
@@ -8,6 +8,7 @@ module Command ( command, noRepo,+ withOptions, next, stop, stopUnless,@@ -25,23 +26,28 @@ import qualified Backend import qualified Annex import qualified Git+import qualified Remote import Types.Command as ReExported+import Types.Option as ReExported import Seek as ReExported import Checks as ReExported-import Options as ReExported+import Usage as ReExported import Logs.Trust-import Logs.Location import Config {- Generates a normal command -} command :: String -> String -> [CommandSeek] -> String -> Command-command = Command Nothing commonChecks+command = Command [] Nothing commonChecks {- Adds a fallback action to a command, that will be run if it's used - outside a git repository. -} noRepo :: IO () -> Command -> Command noRepo a c = c { cmdnorepo = Just a } +{- Adds options to a command. -}+withOptions :: [Option] -> Command -> Command+withOptions o c = c { cmdoptions = o }+ {- For start and perform stages to indicate what step to run next. -} next :: a -> Annex (Maybe a) next a = return $ Just a@@ -104,5 +110,5 @@ auto False = a auto True = do needed <- getNumCopies numcopiesattr- (_, have) <- trustPartition UnTrusted =<< keyLocations key+ (_, have) <- trustPartition UnTrusted =<< Remote.keyLocations key if length have `vs` needed then a else stop
Command/AddUrl.hs view
@@ -12,7 +12,6 @@ import Common.Annex import Command import qualified Backend-import qualified Utility.Url as Url import qualified Command.Add import qualified Annex import qualified Backend.URL@@ -45,7 +44,7 @@ let dummykey = Backend.URL.fromUrl url tmp <- fromRepo $ gitAnnexTmpLocation dummykey liftIO $ createDirectoryIfMissing True (parentDir tmp)- stopUnless (liftIO $ Url.download url tmp) $ do+ stopUnless (downloadUrl [url] tmp) $ do [(backend, _)] <- Backend.chooseBackends [file] k <- Backend.genKey tmp backend case k of
Command/Copy.hs view
@@ -10,17 +10,19 @@ import Common.Annex import Command import qualified Command.Move+import qualified Remote def :: [Command]-def = [dontCheck toOpt $ dontCheck fromOpt $ - command "copy" paramPaths seek+def = [withOptions Command.Move.options $ command "copy" paramPaths seek "copy content of files to/from another repository"] seek :: [CommandSeek]-seek = [withNumCopies $ \n -> whenAnnexed $ start n]+seek = [withField Command.Move.toOption Remote.byName $ \to ->+ withField Command.Move.fromOption Remote.byName $ \from ->+ withNumCopies $ \n -> whenAnnexed $ start to from n] -- A copy is just a move that does not delete the source file. -- However, --auto mode avoids unnecessary copies.-start :: Maybe Int -> FilePath -> (Key, Backend) -> CommandStart-start numcopies file (key, backend) = autoCopies key (<) numcopies $- Command.Move.start False file (key, backend)+start :: Maybe Remote -> Maybe Remote -> Maybe Int -> FilePath -> (Key, Backend) -> CommandStart+start to from numcopies file (key, backend) = autoCopies key (<) numcopies $+ Command.Move.start to from False file (key, backend)
Command/Drop.hs view
@@ -16,21 +16,24 @@ import Logs.Trust import Annex.Content import Config+import qualified Option def :: [Command]-def = [dontCheck fromOpt $ command "drop" paramPaths seek+def = [withOptions [fromOption] $ command "drop" paramPaths seek "indicate content of files not currently wanted"] +fromOption :: Option+fromOption = Option.field ['f'] "from" paramRemote "drop content from a remote"+ seek :: [CommandSeek]-seek = [withNumCopies $ \n -> whenAnnexed $ start n]+seek = [withField fromOption Remote.byName $ \from -> withNumCopies $ \n ->+ whenAnnexed $ start from n] -start :: Maybe Int -> FilePath -> (Key, Backend) -> CommandStart-start numcopies file (key, _) = autoCopies key (>) numcopies $ do- from <- Annex.getState Annex.fromremote+start :: Maybe Remote -> Maybe Int -> FilePath -> (Key, Backend) -> CommandStart+start from numcopies file (key, _) = autoCopies key (>) numcopies $ do case from of Nothing -> startLocal file numcopies key- Just name -> do- remote <- Remote.byName name+ Just remote -> do u <- getUUID if Remote.uuid remote == u then startLocal file numcopies key
Command/DropUnused.hs view
@@ -15,13 +15,15 @@ import qualified Command.Drop import qualified Remote import qualified Git+import qualified Option import Types.Key type UnusedMap = M.Map String Key def :: [Command]-def = [dontCheck fromOpt $ command "dropunused" (paramRepeating paramNumber)- seek "drop unused file content"]+def = [withOptions [Command.Drop.fromOption] $+ command "dropunused" (paramRepeating paramNumber)+ seek "drop unused file content"] seek :: [CommandSeek] seek = [withUnusedMaps]@@ -50,14 +52,14 @@ next $ a key perform :: Key -> CommandPerform-perform key = maybe droplocal dropremote =<< Annex.getState Annex.fromremote+perform key = maybe droplocal dropremote =<< Remote.byName =<< from where- dropremote name = do- r <- Remote.byName name+ dropremote r = do showAction $ "from " ++ Remote.name r ok <- Remote.removeKey r key next $ Command.Drop.cleanupRemote key r ok droplocal = Command.Drop.performLocal key (Just 0) -- force drop+ from = Annex.getField $ Option.name Command.Drop.fromOption performOther :: (Key -> Git.Repo -> FilePath) -> Key -> CommandPerform performOther filespec key = do
Command/Find.hs view
@@ -1,6 +1,6 @@ {- git-annex command -- - Copyright 2010 Joey Hess <joey@kitenet.net>+ - Copyright 2010-2012 Joey Hess <joey@kitenet.net> - - Licensed under the GNU GPL version 3 or higher. -}@@ -17,21 +17,34 @@ import qualified Utility.Format import Utility.DataUnits import Types.Key+import qualified Option def :: [Command]-def = [command "find" paramPaths seek "lists available files"]+def = [withOptions [formatOption, print0Option] $+ command "find" paramPaths seek "lists available files"] +formatOption :: Option+formatOption = Option.field [] "format" paramFormat "control format of output"++print0Option :: Option+print0Option = Option.Option [] ["print0"] (Option.NoArg set)+ "terminate output with null"+ where+ set = Annex.setField (Option.name formatOption) "${file}\0"+ seek :: [CommandSeek]-seek = [withFilesInGit $ whenAnnexed start]+seek = [withField formatOption formatconverter $ \f ->+ withFilesInGit $ whenAnnexed $ start f]+ where+ formatconverter = return . maybe Nothing (Just . Utility.Format.gen) -start :: FilePath -> (Key, Backend) -> CommandStart-start file (key, _) = do+start :: Maybe Utility.Format.Format -> FilePath -> (Key, Backend) -> CommandStart+start format file (key, _) = do -- only files inAnnex are shown, unless the user has requested -- others via a limit whenM (liftM2 (||) limited (inAnnex key)) $- unlessM (showFullJSON vars) $ do- f <- Annex.getState Annex.format- case f of+ unlessM (showFullJSON vars) $+ case format of Nothing -> liftIO $ putStrLn file Just formatter -> liftIO $ putStr $ Utility.Format.format formatter $
Command/Fsck.hs view
@@ -40,8 +40,8 @@ -- order matters [ verifyLocationLog key file , checkKeySize key- , checkKeyNumCopies key file numcopies , checkBackend backend key+ , checkKeyNumCopies key file numcopies ] {- To fsck a bare repository, fsck each key in the location log. -}@@ -52,7 +52,7 @@ go True = do unless (null params) $ error "fsck should be run without parameters in a bare repository"- prepStart a loggedKeys+ map a <$> loggedKeys startBare :: Key -> CommandStart startBare key = case Backend.maybeLookupBackendName (Types.Key.keyBackendName key) of@@ -93,7 +93,7 @@ preventWrite (parentDir f) u <- getUUID- uuids <- keyLocations key+ uuids <- Remote.keyLocations key case (present, u `elem` uuids) of (True, False) -> do@@ -142,7 +142,7 @@ checkKeyNumCopies :: Key -> FilePath -> Maybe Int -> Annex Bool checkKeyNumCopies key file numcopies = do needed <- getNumCopies numcopies- (untrustedlocations, safelocations) <- trustPartition UnTrusted =<< keyLocations key+ (untrustedlocations, safelocations) <- trustPartition UnTrusted =<< Remote.keyLocations key let present = length safelocations if present < needed then do
Command/Get.hs view
@@ -9,27 +9,25 @@ import Common.Annex import Command-import qualified Annex import qualified Remote import Annex.Content import qualified Command.Move def :: [Command]-def = [dontCheck fromOpt $ command "get" paramPaths seek+def = [withOptions [Command.Move.fromOption] $ command "get" paramPaths seek "make content of annexed files available"] seek :: [CommandSeek]-seek = [withNumCopies $ \n -> whenAnnexed $ start n]+seek = [withField Command.Move.fromOption Remote.byName $ \from ->+ withNumCopies $ \n -> whenAnnexed $ start from n] -start :: Maybe Int -> FilePath -> (Key, Backend) -> CommandStart-start numcopies file (key, _) = stopUnless (not <$> inAnnex key) $+start :: Maybe Remote -> Maybe Int -> FilePath -> (Key, Backend) -> CommandStart+start from numcopies file (key, _) = stopUnless (not <$> inAnnex key) $ autoCopies key (<) numcopies $ do- from <- Annex.getState Annex.fromremote case from of Nothing -> go $ perform key- Just name -> do+ Just src -> do -- get --from = copy --from- src <- Remote.byName name stopUnless (Command.Move.fromOk src key) $ go $ Command.Move.fromPerform src False key where
+ Command/Log.hs view
@@ -0,0 +1,172 @@+{- git-annex command+ -+ - Copyright 2012 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++module Command.Log where++import qualified Data.Set as S+import qualified Data.Map as M+import qualified Data.ByteString.Lazy.Char8 as L+import Data.Time.Clock.POSIX+import Data.Time+import System.Locale+import Data.Char++import Common.Annex+import Command+import qualified Logs.Location+import qualified Logs.Presence+import Annex.CatFile+import qualified Annex.Branch+import qualified Git+import Git.Command+import qualified Remote+import qualified Option+import qualified Annex++data RefChange = RefChange + { changetime :: POSIXTime+ , oldref :: Git.Ref+ , newref :: Git.Ref+ }++type Outputter = Bool -> POSIXTime -> [UUID] -> Annex ()++def :: [Command]+def = [withOptions options $+ command "log" paramPaths seek "shows location log"]++options :: [Option]+options = passthruOptions ++ [gourceOption]++passthruOptions :: [Option]+passthruOptions = map odate ["since", "after", "until", "before"] +++ [ Option.field ['n'] "max-count" paramNumber+ "limit number of logs displayed"+ ]+ where+ odate n = Option.field [] n paramDate $+ "show log " ++ n ++ " date"++gourceOption :: Option+gourceOption = Option.flag [] "gource" "format output for gource"++seek :: [CommandSeek]+seek = [withValue (Remote.uuidDescriptions) $ \m ->+ withValue (liftIO getCurrentTimeZone) $ \zone ->+ withValue (concat <$> mapM getoption passthruOptions) $ \os ->+ withFlag gourceOption $ \gource ->+ withFilesInGit $ whenAnnexed $ start m zone os gource]+ where+ getoption o = maybe [] (use o) <$>+ Annex.getField (Option.name o)+ use o v = [Param ("--" ++ Option.name o), Param v]++start :: (M.Map UUID String) -> TimeZone -> [CommandParam] -> Bool ->+ FilePath -> (Key, Backend) -> CommandStart+start m zone os gource file (key, _) = do+ showLog output =<< readLog <$> getLog key os+ liftIO Git.Command.reap+ stop+ where+ output+ | gource = gourceOutput lookupdescription file+ | otherwise = normalOutput lookupdescription file zone+ lookupdescription u = fromMaybe (fromUUID u) $ M.lookup u m++showLog :: Outputter -> [RefChange] -> Annex ()+showLog outputter ps = do+ sets <- mapM (getset newref) ps+ previous <- maybe (return genesis) (getset oldref) (lastMaybe ps)+ sequence_ $ compareChanges outputter $ sets ++ [previous]+ where+ genesis = (0, S.empty)+ getset select change = do+ s <- S.fromList <$> get (select change)+ return (changetime change, s)+ get ref = map toUUID . Logs.Presence.getLog . L.unpack <$>+ catObject ref++normalOutput :: (UUID -> String) -> FilePath -> TimeZone -> Outputter+normalOutput lookupdescription file zone present ts us = do+ liftIO $ mapM_ (putStrLn . format) us+ where+ time = showTimeStamp zone ts+ addel = if present then "+" else "-"+ format u = unwords [ addel, time, file, "|", + fromUUID u ++ " -- " ++ lookupdescription u ]++gourceOutput :: (UUID -> String) -> FilePath -> Outputter+gourceOutput lookupdescription file present ts us = do+ liftIO $ mapM_ (putStrLn . intercalate "|" . format) us+ where+ time = takeWhile isDigit $ show ts+ addel = if present then "A" else "M"+ format u = [ time, lookupdescription u, addel, file ]++{- Generates a display of the changes (which are ordered with newest first),+ - by comparing each change with the previous change.+ - Uses a formatter to generate a display of items that are added and+ - removed. -}+compareChanges :: Ord a => (Bool -> POSIXTime -> [a] -> b) -> [(POSIXTime, S.Set a)] -> [b]+compareChanges format changes = concatMap diff $ zip changes (drop 1 changes)+ where+ diff ((ts, new), (_, old)) =+ [format True ts added, format False ts removed]+ where+ added = S.toList $ S.difference new old+ removed = S.toList $ S.difference old new++{- Gets the git log for a given location log file.+ -+ - This is complicated by git log using paths relative to the current+ - directory, even when looking at files in a different branch. A wacky+ - relative path to the log file has to be used.+ -+ - The --remove-empty is a significant optimisation. It relies on location+ - log files never being deleted in normal operation. Letting git stop+ - once the location log file is gone avoids it checking all the way back+ - to commit 0 to see if it used to exist, so generally speeds things up a+ - *lot* for newish files. -}+getLog :: Key -> [CommandParam] -> Annex [String]+getLog key os = do+ top <- fromRepo Git.workTree+ p <- liftIO $ relPathCwdToFile top+ let logfile = p </> Logs.Location.logFile key+ inRepo $ pipeNullSplit $+ [ Params "log -z --pretty=format:%ct --raw --abbrev=40"+ , Param "--remove-empty"+ ] ++ os +++ [ Param $ show Annex.Branch.fullname+ , Param "--"+ , Param logfile+ ]++readLog :: [String] -> [RefChange]+readLog = mapMaybe (parse . lines)+ where+ parse (ts:raw:[]) = let (old, new) = parseRaw raw in+ Just RefChange+ { changetime = parseTimeStamp ts+ , oldref = old+ , newref = new+ }+ parse _ = Nothing++-- Parses something like ":100644 100644 oldsha newsha M"+parseRaw :: String -> (Git.Ref, Git.Ref)+parseRaw l = (Git.Ref oldsha, Git.Ref newsha)+ where+ ws = words l+ oldsha = ws !! 2+ newsha = ws !! 3++parseTimeStamp :: String -> POSIXTime+parseTimeStamp = utcTimeToPOSIXSeconds . fromMaybe (error "bad timestamp") .+ parseTime defaultTimeLocale "%s"++showTimeStamp :: TimeZone -> POSIXTime -> String+showTimeStamp zone = show . utcToLocalTime zone . posixSecondsToUTCTime
Command/Map.hs view
@@ -20,7 +20,7 @@ import Annex.UUID import Logs.UUID import Logs.Trust-import Annex.Ssh+import Remote.Helper.Ssh import qualified Utility.Dot as Dot -- a link from the first repository to the second (its remote)@@ -155,6 +155,7 @@ absRepo :: Git.Repo -> Git.Repo -> Annex Git.Repo absRepo reference r | Git.repoIsUrl reference = return $ Git.Construct.localToUrl reference r+ | Git.repoIsUrl r = return r | otherwise = liftIO $ Git.Construct.fromAbsPath =<< absPath (Git.workTree r) {- Checks if two repos are the same. -}
Command/Move.hs view
@@ -14,28 +14,33 @@ import Annex.Content import qualified Remote import Annex.UUID+import qualified Option def :: [Command]-def = [dontCheck toOpt $ dontCheck fromOpt $- command "move" paramPaths seek+def = [withOptions options $ command "move" paramPaths seek "move content of files to/from another repository"] +fromOption :: Option+fromOption = Option.field ['f'] "from" paramRemote "source remote"++toOption :: Option+toOption = Option.field ['t'] "to" paramRemote "destination remote"++options :: [Option]+options = [fromOption, toOption]+ seek :: [CommandSeek]-seek = [withFilesInGit $ whenAnnexed $ start True]+seek = [withField toOption Remote.byName $ \to ->+ withField fromOption Remote.byName $ \from ->+ withFilesInGit $ whenAnnexed $ start to from True] -start :: Bool -> FilePath -> (Key, Backend) -> CommandStart-start move file (key, _) = do+start :: Maybe Remote -> Maybe Remote -> Bool -> FilePath -> (Key, Backend) -> CommandStart+start to from move file (key, _) = do noAuto- to <- Annex.getState Annex.toremote- from <- Annex.getState Annex.fromremote case (from, to) of (Nothing, Nothing) -> error "specify either --from or --to"- (Nothing, Just name) -> do- dest <- Remote.byName name- toStart dest move file key- (Just name, Nothing) -> do- src <- Remote.byName name- fromStart src move file key+ (Nothing, Just dest) -> toStart dest move file key+ (Just src, Nothing) -> fromStart src move file key (_ , _) -> error "only one of --from or --to can be specified" where noAuto = when move $ whenM (Annex.getState Annex.auto) $ error
Command/Status.hs view
@@ -144,9 +144,9 @@ backend_usage :: Stat backend_usage = stat "backend usage" $ nojson $- usage <$> cachedKeysReferenced <*> cachedKeysPresent+ calc <$> cachedKeysReferenced <*> cachedKeysPresent where- usage a b = pp "" $ reverse . sort $ map swap $ splits $ S.toList $ S.union a b+ calc a b = pp "" $ reverse . sort $ map swap $ splits $ S.toList $ S.union a b splits :: [Key] -> [(String, Integer)] splits ks = M.toList $ M.fromListWith (+) $ map tcount ks tcount k = (keyBackendName k, 1)
Command/Sync.hs view
@@ -61,7 +61,7 @@ wanted | null rs = good =<< available | otherwise = listed- listed = mapM Remote.byName rs+ listed = catMaybes <$> mapM (Remote.byName . Just) rs available = filter nonspecial <$> Remote.enabledRemoteList good = filterM $ Remote.Git.repoAvail . Types.Remote.repo nonspecial r = Types.Remote.remotetype r == Remote.Git.remote
Command/Unused.hs view
@@ -27,19 +27,23 @@ import qualified Backend import qualified Remote import qualified Annex.Branch+import qualified Option import Annex.CatFile def :: [Command]-def = [dontCheck fromOpt $ command "unused" paramNothing seek+def = [withOptions [fromOption] $ command "unused" paramNothing seek "look for unused file content"] +fromOption :: Option+fromOption = Option.field ['f'] "from" paramRemote "remote to check for unused content"+ seek :: [CommandSeek]-seek = [withNothing start]+seek = [withNothing $ start] {- Finds unused content in the annex. -} start :: CommandStart start = do- from <- Annex.getState Annex.fromremote+ from <- Annex.getField $ Option.name fromOption let (name, action) = case from of Nothing -> (".", checkUnused) Just "." -> (".", checkUnused)@@ -63,7 +67,7 @@ checkRemoteUnused :: String -> CommandPerform checkRemoteUnused name = do- checkRemoteUnused' =<< Remote.byName name+ checkRemoteUnused' =<< fromJust <$> Remote.byName (Just name) next $ return True checkRemoteUnused' :: Remote -> Annex ()
Command/Whereis.hs view
@@ -8,7 +8,6 @@ module Command.Whereis where import Common.Annex-import Logs.Location import Command import Remote import Logs.Trust
Config.hs view
@@ -30,7 +30,7 @@ def' <- fromRepo $ Git.Config.get ("annex." ++ key) def fromRepo $ Git.Config.get (remoteConfig r key) def' -{- Looks up a per-remote config setting in git config. -}+{- A per-remote config setting in git config. -} remoteConfig :: Git.Repo -> ConfigKey -> String remoteConfig r key = "remote." ++ fromMaybe "" (Git.remoteName r) ++ ".annex-" ++ key @@ -67,9 +67,7 @@ , semiCheapRemoteCost + encryptedRemoteCostAdj < expensiveRemoteCost ] -{- Checks if a repo should be ignored, based either on annex-ignore- - setting, or on command-line options. Allows command-line to override- - annex-ignore. -}+{- Checks if a repo should be ignored. -} repoNotIgnored :: Git.Repo -> Annex Bool repoNotIgnored r = not . Git.configTrue <$> getConfig r "ignore" "false" @@ -83,3 +81,7 @@ readMaybe <$> fromRepo (Git.Config.get config "1") perhaps fallback = maybe fallback (return . id) config = "annex.numcopies"++{- Gets the trust level set for a remote in git config. -}+getTrustLevel :: Git.Repo -> Annex (Maybe String)+getTrustLevel r = fromRepo $ Git.Config.getMaybe $ remoteConfig r "trustlevel"
Git.hs view
@@ -29,7 +29,7 @@ import qualified Data.Map as M import Data.Char-import Network.URI (uriPath, uriScheme)+import Network.URI (uriPath, uriScheme, unEscapeString) import Common import Git.Types@@ -107,7 +107,7 @@ - - Note that for URL repositories, this is the path on the remote host. -} workTree :: Repo -> FilePath-workTree Repo { location = Url u } = uriPath u+workTree Repo { location = Url u } = unEscapeString $ uriPath u workTree Repo { location = Dir d } = d workTree Repo { location = Unknown } = undefined
Git/Config.hs view
@@ -20,6 +20,10 @@ get :: String -> String -> Repo -> String get key defaultValue repo = M.findWithDefault defaultValue key (config repo) +{- Returns a single git config setting, if set. -}+getMaybe :: String -> Repo -> Maybe String+getMaybe key repo = M.lookup key (config repo)+ {- Runs git config and populates a repo with its config. -} read :: Repo -> IO Repo read repo@(Repo { location = Dir d }) = do
Git/Construct.hs view
@@ -6,6 +6,7 @@ -} module Git.Construct (+ fromCurrent, fromCwd, fromAbsPath, fromUrl,@@ -19,6 +20,8 @@ ) where import System.Posix.User+import System.Posix.Env (getEnv, unsetEnv)+import System.Posix.Directory (changeWorkingDirectory) import qualified Data.Map as M hiding (map, split) import Network.URI @@ -27,13 +30,40 @@ import Git import qualified Git.Url as Url -{- Finds the current git repository, which may be in a parent directory. -}+{- Finds the current git repository.+ -+ - GIT_DIR can override the location of the .git directory.+ -+ - When GIT_WORK_TREE is set, chdir to it, so that anything using+ - this repository runs in the right location. However, this chdir is+ - done after determining GIT_DIR; git does not let GIT_WORK_TREE+ - influence the git directory.+ -+ - Both environment variables are unset, to avoid confusing other git+ - commands that also look at them. This would particularly be a problem+ - when GIT_DIR is relative and we chdir for GIT_WORK_TREE. Instead,+ - the Git module passes --work-tree and --git-dir to git commands it runs.+ -}+fromCurrent :: IO Repo+fromCurrent = do+ r <- maybe fromCwd fromPath =<< getEnv "GIT_DIR"+ maybe (return ()) changeWorkingDirectory =<< getEnv "GIT_WORK_TREE"+ unsetEnv "GIT_DIR"+ unsetEnv "GIT_WORK_TREE"+ return r++{- Finds the git repository used for the Cwd, which may be in a parent+ - directory. -} fromCwd :: IO Repo fromCwd = getCurrentDirectory >>= seekUp isRepoTop >>= maybe norepo makerepo where makerepo = return . newFrom . Dir norepo = error "Not in a git repository." +{- Local Repo constructor, accepts a relative or absolute path. -}+fromPath :: FilePath -> IO Repo+fromPath dir = fromAbsPath =<< absPath dir+ {- Local Repo constructor, requires an absolute path to the repo be - specified. -} fromAbsPath :: FilePath -> IO Repo@@ -60,14 +90,23 @@ where ret = return . newFrom . Dir -{- Remote Repo constructor. Throws exception on invalid url. -}+{- Remote Repo constructor. Throws exception on invalid url.+ -+ - Git is somewhat forgiving about urls to repositories, allowing+ - eg spaces that are not normally allowed unescaped in urls.+ -} fromUrl :: String -> IO Repo fromUrl url+ | not (isURI url) = fromUrlStrict $ escapeURIString isUnescapedInURI url+ | otherwise = fromUrlStrict url++fromUrlStrict :: String -> IO Repo+fromUrlStrict url | startswith "file://" url = fromAbsPath $ uriPath u | otherwise = return $ newFrom $ Url u- where- u = fromMaybe bad $ parseURI url- bad = error $ "bad url " ++ url+ where+ u = fromMaybe bad $ parseURI url+ bad = error $ "bad url " ++ url {- Creates a repo that has an unknown location. -} fromUnknown :: IO Repo@@ -117,7 +156,7 @@ where gen v | scpstyle v = fromUrl $ scptourl v- | isURI v = fromUrl v+ | urlstyle v = fromUrl v | otherwise = fromRemotePath v repo -- insteadof config can rewrite remote location calcloc l@@ -137,6 +176,7 @@ M.toList $ fullconfig repo splitconfigs (k, vs) = map (\v -> (k, v)) vs (prefix, suffix) = ("url." , ".insteadof")+ urlstyle v = isURI v || ":" `isInfixOf` v && "//" `isInfixOf` v -- git remotes can be written scp style -- [user@]host:dir scpstyle v = ":" `isInfixOf` v && not ("//" `isInfixOf` v) scptourl v = "ssh://" ++ host ++ slash dir
Git/Sha.hs view
@@ -34,3 +34,6 @@ {- Size of a git sha. -} shaSize :: Int shaSize = 40++nullSha :: Ref +nullSha = Ref $ replicate shaSize '0'
Git/UnionMerge.hs view
@@ -103,14 +103,13 @@ - a line suitable for update_index that union merges the two sides of the - diff. -} mergeFile :: String -> FilePath -> CatFileHandle -> Repo -> IO (Maybe String)-mergeFile info file h repo = case filter (/= nullsha) [Ref asha, Ref bsha] of+mergeFile info file h repo = case filter (/= nullSha) [Ref asha, Ref bsha] of [] -> return Nothing (sha:[]) -> use sha shas -> use =<< either return (hashObject repo . L.unlines) =<< calcMerge . zip shas <$> mapM getcontents shas where [_colonmode, _bmode, asha, bsha, _status] = words info- nullsha = Ref $ replicate shaSize '0' getcontents s = L.lines <$> catObject h s use sha = return $ Just $ update_index_line sha file
GitAnnex.hs view
@@ -18,7 +18,7 @@ import qualified Annex import qualified Remote import qualified Limit-import qualified Utility.Format+import qualified Option import qualified Command.Add import qualified Command.Unannex@@ -41,6 +41,7 @@ import qualified Command.PreCommit import qualified Command.Find import qualified Command.Whereis+import qualified Command.Log import qualified Command.Merge import qualified Command.Status import qualified Command.Migrate@@ -85,6 +86,7 @@ , Command.DropUnused.def , Command.Find.def , Command.Whereis.def+ , Command.Log.def , Command.Merge.def , Command.Status.def , Command.Migrate.def@@ -94,12 +96,8 @@ ] options :: [Option]-options = commonOptions ++- [ Option ['t'] ["to"] (ReqArg setto paramRemote)- "specify to where to transfer content"- , Option ['f'] ["from"] (ReqArg setfrom paramRemote)- "specify from where to transfer content"- , Option ['N'] ["numcopies"] (ReqArg setnumcopies paramNumber)+options = Option.common +++ [ Option ['N'] ["numcopies"] (ReqArg setnumcopies paramNumber) "override default number of copies" , Option [] ["trust"] (ReqArg (Remote.forceTrust Trusted) paramRemote) "override trust setting"@@ -109,10 +107,6 @@ "override trust setting to untrusted" , Option ['c'] ["config"] (ReqArg setgitconfig "NAME=VALUE") "override git configuration setting"- , Option [] ["print0"] (NoArg setprint0)- "terminate output with null"- , Option [] ["format"] (ReqArg setformat paramFormat)- "control format of output" , Option ['x'] ["exclude"] (ReqArg Limit.addExclude paramGlob) "skip files matching the glob pattern" , Option ['I'] ["include"] (ReqArg Limit.addInclude paramGlob)@@ -123,13 +117,9 @@ "skip files with fewer copies" , Option ['B'] ["inbackend"] (ReqArg Limit.addInBackend paramName) "skip files not using a key-value backend"- ] ++ matcherOptions+ ] ++ Option.matcher where- setto v = Annex.changeState $ \s -> s { Annex.toremote = Just v }- setfrom v = Annex.changeState $ \s -> s { Annex.fromremote = Just v } setnumcopies v = Annex.changeState $ \s -> s {Annex.forcenumcopies = readMaybe v }- setformat v = Annex.changeState $ \s -> s { Annex.format = Just $ Utility.Format.gen v }- setprint0 = setformat "${file}\0" setgitconfig :: String -> Annex () setgitconfig v = do newg <- inRepo $ Git.Config.store v@@ -139,4 +129,4 @@ header = "Usage: git-annex command [option ..]" run :: [String] -> IO ()-run args = dispatch args cmds options header Git.Construct.fromCwd+run args = dispatch args cmds options header Git.Construct.fromCurrent
INSTALL view
@@ -6,6 +6,9 @@ * [[Fedora]] * [[FreeBSD]] * [[openSUSE]]+* [[ArchLinux]]+* [[NixOS]]+* Windows: [[sorry, not possible yet|todo/windows_support]] ## Using cabal @@ -29,7 +32,7 @@ * [TestPack](http://hackage.haskell.org/cgi-bin/hackage-scripts/package/testpack) * [QuickCheck 2](http://hackage.haskell.org/package/QuickCheck) * [HTTP](http://hackage.haskell.org/package/HTTP)- * [hS3](http://hackage.haskell.org/package/hS3) (optional, but recommended)+ * [hS3](http://hackage.haskell.org/package/hS3) * [json](http://hackage.haskell.org/package/json) * Shell commands * [git](http://git-scm.com/)
Limit.hs view
@@ -15,7 +15,6 @@ import qualified Utility.Matcher import qualified Remote import qualified Backend-import Logs.Location import Annex.Content type Limit = Utility.Matcher.Token (FilePath -> Annex Bool)@@ -78,7 +77,7 @@ handle a (Just (key, _)) = a key inremote key = do u <- Remote.nameToUUID name- us <- keyLocations key+ us <- Remote.keyLocations key return $ u `elem` us {- Adds a limit to skip files not believed to have the specified number@@ -92,7 +91,7 @@ check n = Backend.lookupFile >=> handle n handle _ Nothing = return False handle n (Just (key, _)) = do- us <- keyLocations key+ us <- Remote.keyLocations key return $ length us >= n {- Adds a limit to skip files not using a specified key-value backend. -}
Logs/Location.hs view
@@ -16,8 +16,7 @@ module Logs.Location ( LogStatus(..), logChange,- readLog,- keyLocations,+ loggedLocations, loggedKeys, loggedKeysFor, logFile,@@ -27,7 +26,6 @@ import Common.Annex import qualified Annex.Branch import Logs.Presence-import Logs.Trust {- Log a change in the presence of a key's value in a repository. -} logChange :: Key -> UUID -> LogStatus -> Annex ()@@ -36,13 +34,9 @@ {- Returns a list of repository UUIDs that, according to the log, have - the value of a key.- -- - Dead repositories are skipped. -}-keyLocations :: Key -> Annex [UUID]-keyLocations key = do- l <- map toUUID <$> (currentLog . logFile) key- snd <$> trustPartition DeadTrusted l+loggedLocations :: Key -> Annex [UUID]+loggedLocations key = map toUUID <$> (currentLog . logFile) key {- Finds all keys that have location log information. - (There may be duplicate keys in the list.) -}@@ -57,7 +51,7 @@ {- This should run strictly to avoid the filterM - building many thunks containing keyLocations data. -} isthere k = do- us <- keyLocations k+ us <- loggedLocations k let !there = u `elem` us return there
Logs/Presence.hs view
@@ -13,14 +13,15 @@ module Logs.Presence ( LogStatus(..),+ LogLine, addLog, readLog,+ getLog, parseLog, showLog, logNow, compactLog, currentLog,- LogLine ) where import Data.Time.Clock.POSIX@@ -79,6 +80,10 @@ {- Reads a log and returns only the info that is still in effect. -} currentLog :: FilePath -> Annex [String] currentLog file = map info . filterPresent <$> readLog file++{- Given a log, returns only the info that is are still in effect. -}+getLog :: String -> [String]+getLog = map info . filterPresent . parseLog {- Returns the info from LogLines that are in effect. -} filterPresent :: [LogLine] -> [LogLine]
Logs/Trust.hs view
@@ -1,6 +1,6 @@-{- git-annex trust+{- git-annex trust log -- - Copyright 2010 Joey Hess <joey@kitenet.net>+ - Copyright 2010-2012 Joey Hess <joey@kitenet.net> - - Licensed under the GNU GPL version 3 or higher. -}@@ -9,7 +9,7 @@ TrustLevel(..), trustGet, trustSet,- trustPartition+ trustPartition, ) where import qualified Data.Map as M@@ -20,6 +20,9 @@ import qualified Annex.Branch import qualified Annex import Logs.UUIDBased+import Remote.List+import Config+import qualified Types.Remote {- Filename of trust.log. -} trustLog :: FilePath@@ -32,6 +35,15 @@ trustGet :: TrustLevel -> Annex [UUID] trustGet level = M.keys . M.filter (== level) <$> trustMap +{- Changes the trust level for a uuid in the trustLog. -}+trustSet :: UUID -> TrustLevel -> Annex ()+trustSet uuid@(UUID _) level = do+ ts <- liftIO getPOSIXTime+ Annex.Branch.change trustLog $+ showLog showTrust . changeLog ts uuid level . parseLog (Just . parseTrust)+ Annex.changeState $ \s -> s { Annex.trustmap = Nothing }+trustSet NoUUID _ = error "unknown UUID; cannot modify trust level"+ {- Partitions a list of UUIDs to those matching a TrustLevel and not. -} trustPartition :: TrustLevel -> [UUID] -> Annex ([UUID], [UUID]) trustPartition level ls@@ -46,18 +58,30 @@ return $ partition (`elem` candidates) ls {- Read the trustLog into a map, overriding with any- - values from forcetrust. The map is cached for speed. -}+ - values from forcetrust or the git config. The map is cached for speed. -} trustMap :: Annex TrustMap trustMap = do cached <- Annex.getState Annex.trustmap case cached of Just m -> return m Nothing -> do- overrides <- M.fromList <$> Annex.getState Annex.forcetrust- m <- (M.union overrides . simpleMap . parseLog (Just . parseTrust)) <$>+ overrides <- Annex.getState Annex.forcetrust+ logged <- simpleMap . parseLog (Just . parseTrust) <$> Annex.Branch.get trustLog+ configured <- M.fromList . catMaybes <$>+ (mapM configuredtrust =<< remoteList)+ let m = M.union overrides $ M.union configured logged Annex.changeState $ \s -> s { Annex.trustmap = Just m } return m+ where+ configuredtrust r =+ maybe Nothing (\l -> Just (Types.Remote.uuid r, l)) <$>+ maybe Nothing convert <$>+ getTrustLevel (Types.Remote.repo r)+ convert "trusted" = Just Trusted+ convert "untrusted" = Just UnTrusted+ convert "semitrusted" = Just SemiTrusted+ convert _ = Nothing {- The trust.log used to only list trusted repos, without a field for the - trust status, which is why this defaults to Trusted. -}@@ -74,12 +98,3 @@ showTrust UnTrusted = "0" showTrust DeadTrusted = "X" showTrust SemiTrusted = "?"--{- Changes the trust level for a uuid in the trustLog. -}-trustSet :: UUID -> TrustLevel -> Annex ()-trustSet uuid@(UUID _) level = do- ts <- liftIO getPOSIXTime- Annex.Branch.change trustLog $- showLog showTrust . changeLog ts uuid level . parseLog (Just . parseTrust)- Annex.changeState $ \s -> s { Annex.trustmap = Nothing }-trustSet NoUUID _ = error "unknown UUID; cannot modify trust level"
Makefile view
@@ -10,7 +10,7 @@ bins=git-annex git-annex-shell git-union-merge mans=git-annex.1 git-annex-shell.1 git-union-merge.1-sources=Build/SysConfig.hs Utility/StatFS.hs Utility/Touch.hs Remote/S3.hs+sources=Build/SysConfig.hs Utility/StatFS.hs Utility/Touch.hs all=$(bins) $(mans) docs @@ -33,18 +33,7 @@ hsc2hs $< perl -i -pe 's/^{-# INCLUDE.*//' $@ -Remote/S3.hs:- @ln -sf S3real.hs Remote/S3.hs--Remote/S3.o: Remote/S3.hs- @if ! $(GHCMAKE) Remote/S3.hs; then \- ln -sf S3stub.hs Remote/S3.hs; \- echo "** building without S3 support"; \- fi--sources: $(sources)--$(bins): sources Remote/S3.o+$(bins): $(sources) $(GHCMAKE) $@ git-annex.1: doc/git-annex.mdwn@@ -66,12 +55,11 @@ test: @if ! $(GHCMAKE) -O0 test; then \- echo "** not running test suite" >&2; \- else \- if ! ./test; then \- echo "** test suite failed!" >&2; \- exit 1; \- fi; \+ echo "** failed to build the test suite" >&2; \+ exit 1; \+ elif ! ./test; then \+ echo "** test suite failed!" >&2; \+ exit 1; \ fi testcoverage:@@ -111,5 +99,9 @@ @sed -e "s!\(Extra-Source-Files: \).*!\1$(shell find . -name .git -prune -or -not -name \\*.orig -not -type d -print | perl -ne 'print unless length >= 100')!i" < git-annex.cabal.orig > git-annex.cabal @cabal sdist @mv git-annex.cabal.orig git-annex.cabal++# Upload to hackage.+hackage: sdist+ @cabal upload dist/*.tar.gz .PHONY: $(bins) test install
+ Option.hs view
@@ -0,0 +1,79 @@+{- git-annex command-line options+ -+ - Copyright 2010-2011 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++module Option (+ common,+ matcher,+ flag,+ field,+ name,+ ArgDescr(..),+ OptDescr(..),+) where++import System.Console.GetOpt+import System.Log.Logger++import Common.Annex+import qualified Annex+import Limit+import Usage++common :: [Option]+common =+ [ Option [] ["force"] (NoArg (setforce True))+ "allow actions that may lose annexed data"+ , Option ['F'] ["fast"] (NoArg (setfast True))+ "avoid slow operations"+ , Option ['a'] ["auto"] (NoArg (setauto True))+ "automatic mode"+ , Option ['q'] ["quiet"] (NoArg (setoutput Annex.QuietOutput))+ "avoid verbose output"+ , Option ['v'] ["verbose"] (NoArg (setoutput Annex.NormalOutput))+ "allow verbose output (default)"+ , Option ['j'] ["json"] (NoArg (setoutput Annex.JSONOutput))+ "enable JSON output"+ , Option ['d'] ["debug"] (NoArg (setdebug))+ "show debug messages"+ , Option ['b'] ["backend"] (ReqArg setforcebackend paramName)+ "specify key-value backend to use"+ ]+ where+ setforce v = Annex.changeState $ \s -> s { Annex.force = v }+ setfast v = Annex.changeState $ \s -> s { Annex.fast = v }+ setauto v = Annex.changeState $ \s -> s { Annex.auto = v }+ setoutput v = Annex.changeState $ \s -> s { Annex.output = v }+ setforcebackend v = Annex.changeState $ \s -> s { Annex.forcebackend = Just v }+ setdebug = liftIO $ updateGlobalLogger rootLoggerName $+ setLevel DEBUG++matcher :: [Option]+matcher =+ [ longopt "not" "negate next option"+ , longopt "and" "both previous and next option must match"+ , longopt "or" "either previous or next option must match"+ , shortopt "(" "open group of options"+ , shortopt ")" "close group of options"+ ]+ where+ longopt o = Option [] [o] $ NoArg $ addToken o+ shortopt o = Option o [] $ NoArg $ addToken o++{- An option that sets a flag. -}+flag :: String -> String -> String -> Option+flag short opt description = + Option short [opt] (NoArg (Annex.setFlag opt)) description++{- An option that sets a field. -}+field :: String -> String -> String -> String -> Option+field short opt paramdesc description = + Option short [opt] (ReqArg (Annex.setField opt) paramdesc) description++{- The flag or field name used for an option. -}+name :: Option -> String+name (Option _ o _ _) = Prelude.head o+
− Options.hs
@@ -1,96 +0,0 @@-{- git-annex command-line options- -- - Copyright 2010-2011 Joey Hess <joey@kitenet.net>- -- - Licensed under the GNU GPL version 3 or higher.- -}--module Options where--import System.Console.GetOpt-import System.Log.Logger--import Common.Annex-import qualified Annex-import Limit--{- Each dashed command-line option results in generation of an action- - in the Annex monad that performs the necessary setting.- -}-type Option = OptDescr (Annex ())--commonOptions :: [Option]-commonOptions =- [ Option [] ["force"] (NoArg (setforce True))- "allow actions that may lose annexed data"- , Option ['F'] ["fast"] (NoArg (setfast True))- "avoid slow operations"- , Option ['a'] ["auto"] (NoArg (setauto True))- "automatic mode"- , Option ['q'] ["quiet"] (NoArg (setoutput Annex.QuietOutput))- "avoid verbose output"- , Option ['v'] ["verbose"] (NoArg (setoutput Annex.NormalOutput))- "allow verbose output (default)"- , Option ['j'] ["json"] (NoArg (setoutput Annex.JSONOutput))- "enable JSON output"- , Option ['d'] ["debug"] (NoArg (setdebug))- "show debug messages"- , Option ['b'] ["backend"] (ReqArg setforcebackend paramName)- "specify key-value backend to use"- ]- where- setforce v = Annex.changeState $ \s -> s { Annex.force = v }- setfast v = Annex.changeState $ \s -> s { Annex.fast = v }- setauto v = Annex.changeState $ \s -> s { Annex.auto = v }- setoutput v = Annex.changeState $ \s -> s { Annex.output = v }- setforcebackend v = Annex.changeState $ \s -> s { Annex.forcebackend = Just v }- setdebug = liftIO $ updateGlobalLogger rootLoggerName $- setLevel DEBUG- -matcherOptions :: [Option]-matcherOptions =- [ longopt "not" "negate next option"- , longopt "and" "both previous and next option must match"- , longopt "or" "either previous or next option must match"- , shortopt "(" "open group of options"- , shortopt ")" "close group of options"- ]- where- longopt o = Option [] [o] $ NoArg $ addToken o- shortopt o = Option o [] $ NoArg $ addToken o--{- Descriptions of params used in usage messages. -}-paramPaths :: String-paramPaths = paramOptional $ paramRepeating paramPath -- most often used-paramPath :: String-paramPath = "PATH"-paramKey :: String-paramKey = "KEY"-paramDesc :: String-paramDesc = "DESC"-paramUrl :: String-paramUrl = "URL"-paramNumber :: String-paramNumber = "NUMBER"-paramRemote :: String-paramRemote = "REMOTE"-paramGlob :: String-paramGlob = "GLOB"-paramName :: String-paramName = "NAME"-paramUUID :: String-paramUUID = "UUID"-paramType :: String-paramType = "TYPE"-paramFormat :: String-paramFormat = "FORMAT"-paramKeyValue :: String-paramKeyValue = "K=V"-paramNothing :: String-paramNothing = ""-paramRepeating :: String -> String-paramRepeating s = s ++ " ..."-paramOptional :: String -> String-paramOptional s = "[" ++ s ++ "]"-paramPair :: String -> String -> String-paramPair a b = a ++ " " ++ b
Remote.hs view
@@ -19,10 +19,12 @@ remoteList, enabledRemoteList, remoteMap,+ uuidDescriptions, byName, prettyPrintUUIDs, remotesWithUUID, remotesWithoutUUID,+ keyLocations, keyPossibilities, keyPossibilitiesTrusted, nameToUUID,@@ -39,69 +41,38 @@ import Common.Annex import Types.Remote import qualified Annex-import Config import Annex.UUID import Logs.UUID import Logs.Trust import Logs.Location-import Logs.Remote--import qualified Remote.Git-import qualified Remote.S3-import qualified Remote.Bup-import qualified Remote.Directory-import qualified Remote.Rsync-import qualified Remote.Web-import qualified Remote.Hook--remoteTypes :: [RemoteType]-remoteTypes =- [ Remote.Git.remote- , Remote.S3.remote- , Remote.Bup.remote- , Remote.Directory.remote- , Remote.Rsync.remote- , Remote.Web.remote- , Remote.Hook.remote- ]--{- Builds a list of all available Remotes.- - Since doing so can be expensive, the list is cached. -}-remoteList :: Annex [Remote]-remoteList = do- rs <- Annex.getState Annex.remotes- if null rs- then do- m <- readRemoteLog- l <- mapM (process m) remoteTypes- let rs' = concat l- Annex.changeState $ \s -> s { Annex.remotes = rs' }- return rs'- else return rs- where- process m t = - enumerate t >>=- mapM (gen m t)- gen m t r = do- u <- getRepoUUID r- generate t r u (M.lookup u m)--{- All remotes that are not ignored. -}-enabledRemoteList :: Annex [Remote]-enabledRemoteList = filterM (repoNotIgnored . repo) =<< remoteList+import Remote.List {- Map of UUIDs of Remotes and their names. -} remoteMap :: Annex (M.Map UUID String)-remoteMap = M.fromList . map (\r -> (uuid r, name r)) <$> remoteList+remoteMap = M.fromList . map (\r -> (uuid r, name r)) .+ filter (\r -> uuid r /= NoUUID) <$> remoteList -{- Looks up a remote by name. (Or by UUID.) Only finds currently configured- - git remotes. -}-byName :: String -> Annex (Remote)-byName n = do+{- Map of UUIDs and their descriptions.+ - The names of Remotes are added to suppliment any description that has+ - been set for a repository. -}+uuidDescriptions :: Annex (M.Map UUID String)+uuidDescriptions = M.unionWith addName <$> uuidMap <*> remoteMap++addName :: String -> String -> String+addName desc n+ | desc == n = desc+ | null desc = n+ | otherwise = n ++ " (" ++ desc ++ ")"++{- When a name is specified, looks up the remote matching that name.+ - (Or it can be a UUID.) Only finds currently configured git remotes. -}+byName :: Maybe String -> Annex (Maybe Remote)+byName Nothing = return Nothing+byName (Just n) = do res <- byName' n case res of Left e -> error e- Right r -> return r+ Right r -> return $ Just r byName' :: String -> Annex (Either String Remote) byName' "" = return $ Left "no remote specified" byName' n = do@@ -142,28 +113,24 @@ prettyPrintUUIDs :: String -> [UUID] -> Annex String prettyPrintUUIDs desc uuids = do hereu <- getUUID- m <- M.unionWith addname <$> uuidMap <*> remoteMap+ m <- uuidDescriptions maybeShowJSON [(desc, map (jsonify m hereu) uuids)] return $ unwords $ map (\u -> "\t" ++ prettify m hereu u ++ "\n") uuids where- addname d n- | d == n = d- | null d = n- | otherwise = n ++ " (" ++ d ++ ")"- findlog m u = M.findWithDefault "" u m+ finddescription m u = M.findWithDefault "" u m prettify m hereu u | not (null d) = fromUUID u ++ " -- " ++ d | otherwise = fromUUID u where ishere = hereu == u- n = findlog m u+ n = finddescription m u d | null n && ishere = "here"- | ishere = addname n "here"+ | ishere = addName n "here" | otherwise = n jsonify m hereu u = toJSObject [ ("uuid", toJSON $ fromUUID u)- , ("description", toJSON $ findlog m u)+ , ("description", toJSON $ finddescription m u) , ("here", toJSON $ hereu == u) ] @@ -175,27 +142,32 @@ remotesWithoutUUID :: [Remote] -> [UUID] -> [Remote] remotesWithoutUUID rs us = filter (\r -> uuid r `notElem` us) rs -{- Cost ordered lists of remotes that the Logs.Location indicate may have a key.+{- List of repository UUIDs that the location log indicates may have a key.+ - Dead repositories are excluded. -}+keyLocations :: Key -> Annex [UUID]+keyLocations key = snd <$> (trustPartition DeadTrusted =<< loggedLocations key)++{- Cost ordered lists of remotes that the location log indicates+ - may have a key. -} keyPossibilities :: Key -> Annex [Remote]-keyPossibilities key = fst <$> keyPossibilities' False key+keyPossibilities key = fst <$> keyPossibilities' key [] -{- Cost ordered lists of remotes that the Logs.Location indicate may have a key.+{- Cost ordered lists of remotes that the location log indicates+ - may have a key. - - Also returns a list of UUIDs that are trusted to have the key - (some may not have configured remotes). -} keyPossibilitiesTrusted :: Key -> Annex ([Remote], [UUID])-keyPossibilitiesTrusted = keyPossibilities' True+keyPossibilitiesTrusted key = keyPossibilities' key =<< trustGet Trusted -keyPossibilities' :: Bool -> Key -> Annex ([Remote], [UUID])-keyPossibilities' withtrusted key = do+keyPossibilities' :: Key -> [UUID] -> Annex ([Remote], [UUID])+keyPossibilities' key trusted = do u <- getUUID- trusted <- if withtrusted then trustGet Trusted else return [] - -- get uuids of all remotes that are recorded to have the key- uuids <- keyLocations key- let validuuids = filter (/= u) uuids+ -- uuids of all remotes that are recorded to have the key+ validuuids <- filter (/= u) <$> keyLocations key -- note that validuuids is assumed to not have dups let validtrusteduuids = validuuids `intersect` trusted@@ -228,13 +200,13 @@ showTriedRemotes [] = return () showTriedRemotes remotes = showLongNote $ "Unable to access these remotes: " ++- (join ", " $ map name remotes)+ join ", " (map name remotes) forceTrust :: TrustLevel -> String -> Annex () forceTrust level remotename = do- r <- nameToUUID remotename+ u <- nameToUUID remotename Annex.changeState $ \s ->- s { Annex.forcetrust = (r, level):Annex.forcetrust s }+ s { Annex.forcetrust = M.insert u level (Annex.forcetrust s) } {- Used to log a change in a remote's having a key. The change is logged - in the local repo, not on the remote. The process of transferring the
Remote/Bup.hs view
@@ -19,7 +19,7 @@ import qualified Git.Config import qualified Git.Construct import Config-import Annex.Ssh+import Remote.Helper.Ssh import Remote.Helper.Special import Remote.Helper.Encryptable import Crypto
Remote/Git.hs view
@@ -13,7 +13,7 @@ import Common.Annex import Utility.CopyFile import Utility.RsyncFile-import Annex.Ssh+import Remote.Helper.Ssh import Types.Remote import qualified Git import qualified Git.Command@@ -115,13 +115,11 @@ pOpen ReadFromPipe "git" ["config", "--null", "--list", "--file", tmpfile] $ Git.Config.hRead r - store a = do- r' <- a+ store = observe $ \r' -> do g <- gitRepo let l = Git.remotes g let g' = g { Git.remotes = exchange l r' } Annex.changeState $ \s -> s { Annex.repo = g' }- return r' exchange [] _ = [] exchange (old:ls) new =@@ -184,9 +182,7 @@ -- No need to update the branch; its data is not used -- for anything onLocal is used to do. Annex.BranchState.disableUpdate- ret <- a- liftIO Git.Command.reap- return ret+ liftIO Git.Command.reap `after` a keyUrls :: Git.Repo -> Key -> [String] keyUrls r key = map tourl (annexLocations key)@@ -209,10 +205,8 @@ loc <- liftIO $ gitAnnexLocation key r rsyncOrCopyFile params loc file | Git.repoIsSsh r = rsyncHelper =<< rsyncParamsRemote r True key file- | Git.repoIsHttp r = liftIO $ downloadurls $ keyUrls r key+ | Git.repoIsHttp r = Annex.Content.downloadUrl (keyUrls r key) file | otherwise = error "copying from non-ssh, non-http repo not supported"- where- downloadurls us = untilTrue us $ \u -> Url.download u file {- Tries to copy a key's content to a remote's annex. -} copyToRemote :: Git.Repo -> Key -> Annex Bool@@ -223,10 +217,9 @@ -- run copy from perspective of remote liftIO $ onLocal r $ do ensureInitialized- ok <- Annex.Content.getViaTmp key $- rsyncOrCopyFile params keysrc- Annex.Content.saveState- return ok+ Annex.Content.saveState `after`+ Annex.Content.getViaTmp key+ (rsyncOrCopyFile params keysrc) | Git.repoIsSsh r = do keysrc <- inRepo $ gitAnnexLocation key rsyncHelper =<< rsyncParamsRemote r False key keysrc
+ Remote/Helper/Ssh.hs view
@@ -0,0 +1,65 @@+{- git-annex remote access with ssh+ -+ - Copyright 2011 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++module Remote.Helper.Ssh where++import Common+import qualified Git+import qualified Git.Url+import Types+import Config+import Annex.UUID++{- Generates parameters to ssh to a repository's host and run a command.+ - Caller is responsible for doing any neccessary shellEscaping of the+ - passed command. -}+sshToRepo :: Git.Repo -> [CommandParam] -> Annex [CommandParam]+sshToRepo repo sshcmd = do+ s <- getConfig repo "ssh-options" ""+ let sshoptions = map Param (words s)+ let sshport = case Git.Url.port repo of+ Nothing -> []+ Just p -> [Param "-p", Param (show p)]+ let sshhost = Param $ Git.Url.hostuser repo+ return $ sshoptions ++ sshport ++ [sshhost] ++ sshcmd++{- Generates parameters to run a git-annex-shell command on a remote+ - repository. -}+git_annex_shell :: Git.Repo -> String -> [CommandParam] -> Annex (Maybe (FilePath, [CommandParam]))+git_annex_shell r command params+ | not $ Git.repoIsUrl r = return $ Just (shellcmd, shellopts)+ | Git.repoIsSsh r = do+ uuid <- getRepoUUID r+ sshparams <- sshToRepo r [Param $ sshcmd uuid ]+ return $ Just ("ssh", sshparams)+ | otherwise = return Nothing+ where+ dir = Git.workTree r+ shellcmd = "git-annex-shell"+ shellopts = Param command : File dir : params+ sshcmd uuid = unwords $+ shellcmd : map shellEscape (toCommand shellopts) +++ uuidcheck uuid+ uuidcheck NoUUID = []+ uuidcheck (UUID u) = ["--uuid", u]++{- Uses a supplied function (such as boolSystem) to run a git-annex-shell+ - command on a remote.+ -+ - Or, if the remote does not support running remote commands, returns+ - a specified error value. -}+onRemote + :: Git.Repo+ -> (FilePath -> [CommandParam] -> IO a, a)+ -> String+ -> [CommandParam]+ -> Annex a+onRemote r (with, errorval) command params = do+ s <- git_annex_shell r command params+ case s of+ Just (c, ps) -> liftIO $ with c ps+ Nothing -> return errorval
+ Remote/List.hs view
@@ -0,0 +1,58 @@+{- git-annex remote list+ -+ - Copyright 2011 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++module Remote.List where++import qualified Data.Map as M++import Common.Annex+import qualified Annex+import Logs.Remote+import Types.Remote+import Annex.UUID+import Config++import qualified Remote.Git+import qualified Remote.S3+import qualified Remote.Bup+import qualified Remote.Directory+import qualified Remote.Rsync+import qualified Remote.Web+import qualified Remote.Hook++remoteTypes :: [RemoteType]+remoteTypes =+ [ Remote.Git.remote+ , Remote.S3.remote+ , Remote.Bup.remote+ , Remote.Directory.remote+ , Remote.Rsync.remote+ , Remote.Web.remote+ , Remote.Hook.remote+ ]++{- Builds a list of all available Remotes.+ - Since doing so can be expensive, the list is cached. -}+remoteList :: Annex [Remote]+remoteList = do+ rs <- Annex.getState Annex.remotes+ if null rs+ then do+ m <- readRemoteLog+ rs' <- concat <$> mapM (process m) remoteTypes+ Annex.changeState $ \s -> s { Annex.remotes = rs' }+ return rs'+ else return rs+ where+ process m t = enumerate t >>= mapM (gen m t)+ gen m t r = do+ u <- getRepoUUID r+ generate t r u (M.lookup u m)++{- All remotes that are not ignored. -}+enabledRemoteList :: Annex [Remote]+enabledRemoteList = filterM (repoNotIgnored . repo) =<< remoteList
Remote/Rsync.hs view
@@ -172,9 +172,7 @@ let tmp = t </> "rsynctmp" </> show pid nuke tmp liftIO $ createDirectoryIfMissing True tmp- res <- a tmp- nuke tmp- return res+ nuke tmp `after` a tmp where nuke d = liftIO $ doesDirectoryExist d >>? removeDirectoryRecursive d
+ Remote/S3.hs view
@@ -0,0 +1,311 @@+{- Amazon S3 remotes.+ -+ - Copyright 2011 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++module Remote.S3 (remote) where++import Network.AWS.AWSConnection+import Network.AWS.S3Object+import Network.AWS.S3Bucket hiding (size)+import Network.AWS.AWSResult+import qualified Data.ByteString.Lazy.Char8 as L+import qualified Data.Map as M+import Data.Char+import System.Environment+import System.Posix.Env (setEnv)++import Common.Annex+import Types.Remote+import Types.Key+import qualified Git+import Config+import Remote.Helper.Special+import Remote.Helper.Encryptable+import Crypto+import Annex.Content+import Utility.Base64++remote :: RemoteType+remote = RemoteType {+ typename = "S3",+ enumerate = findSpecialRemotes "s3",+ generate = gen,+ setup = s3Setup+}++gen :: Git.Repo -> UUID -> Maybe RemoteConfig -> Annex Remote+gen r u c = do+ cst <- remoteCost r expensiveRemoteCost+ return $ gen' r u c cst+gen' :: Git.Repo -> UUID -> Maybe RemoteConfig -> Int -> Remote+gen' r u c cst =+ encryptableRemote c+ (storeEncrypted this)+ (retrieveEncrypted this)+ this+ where+ this = Remote {+ uuid = u,+ cost = cst,+ name = Git.repoDescribe r,+ storeKey = store this,+ retrieveKeyFile = retrieve this,+ removeKey = remove this,+ hasKey = checkPresent this,+ hasKeyCheap = False,+ config = c,+ repo = r,+ remotetype = remote+ }++s3Setup :: UUID -> RemoteConfig -> Annex RemoteConfig+s3Setup u c = handlehost $ M.lookup "host" c+ where+ remotename = fromJust (M.lookup "name" c)+ defbucket = remotename ++ "-" ++ fromUUID u+ defaults = M.fromList+ [ ("datacenter", "US")+ , ("storageclass", "STANDARD")+ , ("host", defaultAmazonS3Host)+ , ("port", show defaultAmazonS3Port)+ , ("bucket", defbucket)+ ]+ + handlehost Nothing = defaulthost+ handlehost (Just h)+ | ".archive.org" `isSuffixOf` map toLower h = archiveorg+ | otherwise = defaulthost++ use fullconfig = do+ gitConfigSpecialRemote u fullconfig "s3" "true"+ s3SetCreds fullconfig ++ defaulthost = do+ c' <- encryptionSetup c+ let fullconfig = c' `M.union` defaults+ genBucket fullconfig+ use fullconfig++ archiveorg = do+ showNote "Internet Archive mode"+ maybe (error "specify bucket=") (const $ return ()) $+ M.lookup "bucket" archiveconfig+ use archiveconfig+ where+ archiveconfig =+ -- hS3 does not pass through+ -- x-archive-* headers+ M.mapKeys (replace "x-archive-" "x-amz-") $+ -- encryption does not make sense here+ M.insert "encryption" "none" $+ M.union c $+ -- special constraints on key names+ M.insert "mungekeys" "ia" $+ -- bucket created only when files+ -- are uploaded+ M.insert "x-amz-auto-make-bucket" "1" $+ -- no default bucket name; should+ -- be human-readable+ M.delete "bucket" defaults++store :: Remote -> Key -> Annex Bool+store r k = s3Action r False $ \(conn, bucket) -> do+ dest <- inRepo $ gitAnnexLocation k+ res <- liftIO $ storeHelper (conn, bucket) r k dest+ s3Bool res++storeEncrypted :: Remote -> (Cipher, Key) -> Key -> Annex Bool+storeEncrypted r (cipher, enck) k = s3Action r False $ \(conn, bucket) -> + -- To get file size of the encrypted content, have to use a temp file.+ -- (An alternative would be chunking to to a constant size.)+ withTmp enck $ \tmp -> do+ f <- inRepo $ gitAnnexLocation k+ liftIO $ withEncryptedContent cipher (L.readFile f) $ \s -> L.writeFile tmp s+ res <- liftIO $ storeHelper (conn, bucket) r enck tmp+ s3Bool res++storeHelper :: (AWSConnection, String) -> Remote -> Key -> FilePath -> IO (AWSResult ())+storeHelper (conn, bucket) r k file = do+ content <- liftIO $ L.readFile file+ -- size is provided to S3 so the whole content does not need to be+ -- buffered to calculate it+ size <- maybe getsize (return . fromIntegral) $ keySize k+ let object = setStorageClass storageclass $ + S3Object bucket (bucketFile r k) ""+ (("Content-Length", show size) : xheaders) content+ sendObject conn object+ where+ storageclass =+ case fromJust $ M.lookup "storageclass" $ fromJust $ config r of+ "REDUCED_REDUNDANCY" -> REDUCED_REDUNDANCY+ _ -> STANDARD+ getsize = do+ s <- liftIO $ getFileStatus file+ return $ fileSize s+ + xheaders = filter isxheader $ M.assocs $ fromJust $ config r+ isxheader (h, _) = "x-amz-" `isPrefixOf` h++retrieve :: Remote -> Key -> FilePath -> Annex Bool+retrieve r k f = s3Action r False $ \(conn, bucket) -> do+ res <- liftIO $ getObject conn $ bucketKey r bucket k+ case res of+ Right o -> do+ liftIO $ L.writeFile f $ obj_data o+ return True+ Left e -> s3Warning e++retrieveEncrypted :: Remote -> (Cipher, Key) -> FilePath -> Annex Bool+retrieveEncrypted r (cipher, enck) f = s3Action r False $ \(conn, bucket) -> do+ res <- liftIO $ getObject conn $ bucketKey r bucket enck+ case res of+ Right o -> liftIO $ + withDecryptedContent cipher (return $ obj_data o) $ \content -> do+ L.writeFile f content+ return True+ Left e -> s3Warning e++remove :: Remote -> Key -> Annex Bool+remove r k = s3Action r False $ \(conn, bucket) -> do+ res <- liftIO $ deleteObject conn $ bucketKey r bucket k+ s3Bool res++checkPresent :: Remote -> Key -> Annex (Either String Bool)+checkPresent r k = s3Action r noconn $ \(conn, bucket) -> do+ showAction $ "checking " ++ name r+ res <- liftIO $ getObjectInfo conn $ bucketKey r bucket k+ case res of+ Right _ -> return $ Right True+ Left (AWSError _ _) -> return $ Right False+ Left e -> return $ Left (s3Error e)+ where+ noconn = Left $ error "S3 not configured"+ +s3Warning :: ReqError -> Annex Bool+s3Warning e = do+ warning $ prettyReqError e+ return False++s3Error :: ReqError -> a+s3Error e = error $ prettyReqError e++s3Bool :: AWSResult () -> Annex Bool+s3Bool (Right _) = return True+s3Bool (Left e) = s3Warning e++s3Action :: Remote -> a -> ((AWSConnection, String) -> Annex a) -> Annex a+s3Action r noconn action = do+ when (isNothing $ config r) $+ error $ "Missing configuration for special remote " ++ name r+ let bucket = M.lookup "bucket" $ fromJust $ config r+ conn <- s3Connection $ fromJust $ config r+ case (bucket, conn) of+ (Just b, Just c) -> action (c, b)+ _ -> return noconn++bucketFile :: Remote -> Key -> FilePath+bucketFile r = munge . show+ where+ munge s = case M.lookup "mungekeys" $ fromJust $ config r of+ Just "ia" -> iaMunge s+ _ -> s++bucketKey :: Remote -> String -> Key -> S3Object+bucketKey r bucket k = S3Object bucket (bucketFile r k) "" [] L.empty++{- Internet Archive limits filenames to a subset of ascii,+ - with no whitespace. Other characters are xml entity+ - encoded. -}+iaMunge :: String -> String+iaMunge = (>>= munge)+ where+ munge c+ | isAsciiUpper c || isAsciiLower c || isNumber c = [c]+ | c `elem` "_-.\"" = [c]+ | isSpace c = []+ | otherwise = "&" ++ show (ord c) ++ ";"++genBucket :: RemoteConfig -> Annex ()+genBucket c = do+ conn <- s3ConnectionRequired c+ showAction "checking bucket"+ loc <- liftIO $ getBucketLocation conn bucket + case loc of+ Right _ -> return ()+ Left err@(NetworkError _) -> s3Error err+ Left (AWSError _ _) -> do+ showAction $ "creating bucket in " ++ datacenter+ res <- liftIO $ createBucketIn conn bucket datacenter+ case res of+ Right _ -> return ()+ Left err -> s3Error err+ where+ bucket = fromJust $ M.lookup "bucket" c+ datacenter = fromJust $ M.lookup "datacenter" c++s3ConnectionRequired :: RemoteConfig -> Annex AWSConnection+s3ConnectionRequired c =+ maybe (error "Cannot connect to S3") return =<< s3Connection c++s3Connection :: RemoteConfig -> Annex (Maybe AWSConnection)+s3Connection c = do+ creds <- s3GetCreds c+ case creds of+ Just (ak, sk) -> return $ Just $ AWSConnection host port ak sk+ _ -> do+ warning $ "Set both " ++ s3AccessKey ++ " and " ++ s3SecretKey ++ " to use S3"+ return Nothing+ where+ host = fromJust $ M.lookup "host" c+ port = let s = fromJust $ M.lookup "port" c in+ case reads s of+ [(p, _)] -> p+ _ -> error $ "bad S3 port value: " ++ s++{- S3 creds come from the environment if set. + - Otherwise, might be stored encrypted in the remote's config. -}+s3GetCreds :: RemoteConfig -> Annex (Maybe (String, String))+s3GetCreds c = do+ ak <- getEnvKey s3AccessKey+ sk <- getEnvKey s3SecretKey+ if null ak || null sk+ then do+ mcipher <- remoteCipher c+ case (M.lookup "s3creds" c, mcipher) of+ (Just encrypted, Just cipher) -> do+ s <- liftIO $ withDecryptedContent cipher+ (return $ L.pack $ fromB64 encrypted)+ (return . L.unpack)+ let [ak', sk', _rest] = lines s+ liftIO $ do+ setEnv s3AccessKey ak True+ setEnv s3SecretKey sk True+ return $ Just (ak', sk')+ _ -> return Nothing+ else return $ Just (ak, sk)+ where+ getEnvKey s = liftIO $ catchDefaultIO (getEnv s) ""++{- Stores S3 creds encrypted in the remote's config if possible. -}+s3SetCreds :: RemoteConfig -> Annex RemoteConfig+s3SetCreds c = do+ creds <- s3GetCreds c+ case creds of+ Just (ak, sk) -> do+ mcipher <- remoteCipher c+ case mcipher of+ Just cipher -> do+ s <- liftIO $ withEncryptedContent cipher+ (return $ L.pack $ unlines [ak, sk])+ (return . L.unpack)+ return $ M.insert "s3creds" (toB64 s) c+ Nothing -> return c+ _ -> return c++s3AccessKey :: String+s3AccessKey = "AWS_ACCESS_KEY_ID"+s3SecretKey :: String+s3SecretKey = "AWS_SECRET_ACCESS_KEY"
− Remote/S3real.hs
@@ -1,311 +0,0 @@-{- Amazon S3 remotes.- -- - Copyright 2011 Joey Hess <joey@kitenet.net>- -- - Licensed under the GNU GPL version 3 or higher.- -}--module Remote.S3 (remote) where--import Network.AWS.AWSConnection-import Network.AWS.S3Object-import Network.AWS.S3Bucket hiding (size)-import Network.AWS.AWSResult-import qualified Data.ByteString.Lazy.Char8 as L-import qualified Data.Map as M-import Data.Char-import System.Environment-import System.Posix.Env (setEnv)--import Common.Annex-import Types.Remote-import Types.Key-import qualified Git-import Config-import Remote.Helper.Special-import Remote.Helper.Encryptable-import Crypto-import Annex.Content-import Utility.Base64--remote :: RemoteType-remote = RemoteType {- typename = "S3",- enumerate = findSpecialRemotes "s3",- generate = gen,- setup = s3Setup-}--gen :: Git.Repo -> UUID -> Maybe RemoteConfig -> Annex Remote-gen r u c = do- cst <- remoteCost r expensiveRemoteCost- return $ gen' r u c cst-gen' :: Git.Repo -> UUID -> Maybe RemoteConfig -> Int -> Remote-gen' r u c cst =- encryptableRemote c- (storeEncrypted this)- (retrieveEncrypted this)- this- where- this = Remote {- uuid = u,- cost = cst,- name = Git.repoDescribe r,- storeKey = store this,- retrieveKeyFile = retrieve this,- removeKey = remove this,- hasKey = checkPresent this,- hasKeyCheap = False,- config = c,- repo = r,- remotetype = remote- }--s3Setup :: UUID -> RemoteConfig -> Annex RemoteConfig-s3Setup u c = handlehost $ M.lookup "host" c- where- remotename = fromJust (M.lookup "name" c)- defbucket = remotename ++ "-" ++ fromUUID u- defaults = M.fromList- [ ("datacenter", "US")- , ("storageclass", "STANDARD")- , ("host", defaultAmazonS3Host)- , ("port", show defaultAmazonS3Port)- , ("bucket", defbucket)- ]- - handlehost Nothing = defaulthost- handlehost (Just h)- | ".archive.org" `isSuffixOf` map toLower h = archiveorg- | otherwise = defaulthost-- use fullconfig = do- gitConfigSpecialRemote u fullconfig "s3" "true"- s3SetCreds fullconfig -- defaulthost = do- c' <- encryptionSetup c- let fullconfig = c' `M.union` defaults- genBucket fullconfig- use fullconfig-- archiveorg = do- showNote "Internet Archive mode"- maybe (error "specify bucket=") (const $ return ()) $- M.lookup "bucket" archiveconfig- use archiveconfig- where- archiveconfig =- -- hS3 does not pass through- -- x-archive-* headers- M.mapKeys (replace "x-archive-" "x-amz-") $- -- encryption does not make sense here- M.insert "encryption" "none" $- M.union c $- -- special constraints on key names- M.insert "mungekeys" "ia" $- -- bucket created only when files- -- are uploaded- M.insert "x-amz-auto-make-bucket" "1" $- -- no default bucket name; should- -- be human-readable- M.delete "bucket" defaults--store :: Remote -> Key -> Annex Bool-store r k = s3Action r False $ \(conn, bucket) -> do- dest <- inRepo $ gitAnnexLocation k- res <- liftIO $ storeHelper (conn, bucket) r k dest- s3Bool res--storeEncrypted :: Remote -> (Cipher, Key) -> Key -> Annex Bool-storeEncrypted r (cipher, enck) k = s3Action r False $ \(conn, bucket) -> - -- To get file size of the encrypted content, have to use a temp file.- -- (An alternative would be chunking to to a constant size.)- withTmp enck $ \tmp -> do- f <- inRepo $ gitAnnexLocation k- liftIO $ withEncryptedContent cipher (L.readFile f) $ \s -> L.writeFile tmp s- res <- liftIO $ storeHelper (conn, bucket) r enck tmp- s3Bool res--storeHelper :: (AWSConnection, String) -> Remote -> Key -> FilePath -> IO (AWSResult ())-storeHelper (conn, bucket) r k file = do- content <- liftIO $ L.readFile file- -- size is provided to S3 so the whole content does not need to be- -- buffered to calculate it- size <- maybe getsize (return . fromIntegral) $ keySize k- let object = setStorageClass storageclass $ - S3Object bucket (bucketFile r k) ""- (("Content-Length", show size) : xheaders) content- sendObject conn object- where- storageclass =- case fromJust $ M.lookup "storageclass" $ fromJust $ config r of- "REDUCED_REDUNDANCY" -> REDUCED_REDUNDANCY- _ -> STANDARD- getsize = do- s <- liftIO $ getFileStatus file- return $ fileSize s- - xheaders = filter isxheader $ M.assocs $ fromJust $ config r- isxheader (h, _) = "x-amz-" `isPrefixOf` h--retrieve :: Remote -> Key -> FilePath -> Annex Bool-retrieve r k f = s3Action r False $ \(conn, bucket) -> do- res <- liftIO $ getObject conn $ bucketKey r bucket k- case res of- Right o -> do- liftIO $ L.writeFile f $ obj_data o- return True- Left e -> s3Warning e--retrieveEncrypted :: Remote -> (Cipher, Key) -> FilePath -> Annex Bool-retrieveEncrypted r (cipher, enck) f = s3Action r False $ \(conn, bucket) -> do- res <- liftIO $ getObject conn $ bucketKey r bucket enck- case res of- Right o -> liftIO $ - withDecryptedContent cipher (return $ obj_data o) $ \content -> do- L.writeFile f content- return True- Left e -> s3Warning e--remove :: Remote -> Key -> Annex Bool-remove r k = s3Action r False $ \(conn, bucket) -> do- res <- liftIO $ deleteObject conn $ bucketKey r bucket k- s3Bool res--checkPresent :: Remote -> Key -> Annex (Either String Bool)-checkPresent r k = s3Action r noconn $ \(conn, bucket) -> do- showAction $ "checking " ++ name r- res <- liftIO $ getObjectInfo conn $ bucketKey r bucket k- case res of- Right _ -> return $ Right True- Left (AWSError _ _) -> return $ Right False- Left e -> return $ Left (s3Error e)- where- noconn = Left $ error "S3 not configured"- -s3Warning :: ReqError -> Annex Bool-s3Warning e = do- warning $ prettyReqError e- return False--s3Error :: ReqError -> a-s3Error e = error $ prettyReqError e--s3Bool :: AWSResult () -> Annex Bool-s3Bool (Right _) = return True-s3Bool (Left e) = s3Warning e--s3Action :: Remote -> a -> ((AWSConnection, String) -> Annex a) -> Annex a-s3Action r noconn action = do- when (isNothing $ config r) $- error $ "Missing configuration for special remote " ++ name r- let bucket = M.lookup "bucket" $ fromJust $ config r- conn <- s3Connection $ fromJust $ config r- case (bucket, conn) of- (Just b, Just c) -> action (c, b)- _ -> return noconn--bucketFile :: Remote -> Key -> FilePath-bucketFile r = munge . show- where- munge s = case M.lookup "mungekeys" $ fromJust $ config r of- Just "ia" -> iaMunge s- _ -> s--bucketKey :: Remote -> String -> Key -> S3Object-bucketKey r bucket k = S3Object bucket (bucketFile r k) "" [] L.empty--{- Internet Archive limits filenames to a subset of ascii,- - with no whitespace. Other characters are xml entity- - encoded. -}-iaMunge :: String -> String-iaMunge = (>>= munge)- where- munge c- | isAsciiUpper c || isAsciiLower c || isNumber c = [c]- | c `elem` "_-.\"" = [c]- | isSpace c = []- | otherwise = "&" ++ show (ord c) ++ ";"--genBucket :: RemoteConfig -> Annex ()-genBucket c = do- conn <- s3ConnectionRequired c- showAction "checking bucket"- loc <- liftIO $ getBucketLocation conn bucket - case loc of- Right _ -> return ()- Left err@(NetworkError _) -> s3Error err- Left (AWSError _ _) -> do- showAction $ "creating bucket in " ++ datacenter- res <- liftIO $ createBucketIn conn bucket datacenter- case res of- Right _ -> return ()- Left err -> s3Error err- where- bucket = fromJust $ M.lookup "bucket" c- datacenter = fromJust $ M.lookup "datacenter" c--s3ConnectionRequired :: RemoteConfig -> Annex AWSConnection-s3ConnectionRequired c =- maybe (error "Cannot connect to S3") return =<< s3Connection c--s3Connection :: RemoteConfig -> Annex (Maybe AWSConnection)-s3Connection c = do- creds <- s3GetCreds c- case creds of- Just (ak, sk) -> return $ Just $ AWSConnection host port ak sk- _ -> do- warning $ "Set both " ++ s3AccessKey ++ " and " ++ s3SecretKey ++ " to use S3"- return Nothing- where- host = fromJust $ M.lookup "host" c- port = let s = fromJust $ M.lookup "port" c in- case reads s of- [(p, _)] -> p- _ -> error $ "bad S3 port value: " ++ s--{- S3 creds come from the environment if set. - - Otherwise, might be stored encrypted in the remote's config. -}-s3GetCreds :: RemoteConfig -> Annex (Maybe (String, String))-s3GetCreds c = do- ak <- getEnvKey s3AccessKey- sk <- getEnvKey s3SecretKey- if null ak || null sk- then do- mcipher <- remoteCipher c- case (M.lookup "s3creds" c, mcipher) of- (Just encrypted, Just cipher) -> do- s <- liftIO $ withDecryptedContent cipher- (return $ L.pack $ fromB64 encrypted)- (return . L.unpack)- let [ak', sk', _rest] = lines s- liftIO $ do- setEnv s3AccessKey ak True- setEnv s3SecretKey sk True- return $ Just (ak', sk')- _ -> return Nothing- else return $ Just (ak, sk)- where- getEnvKey s = liftIO $ catchDefaultIO (getEnv s) ""--{- Stores S3 creds encrypted in the remote's config if possible. -}-s3SetCreds :: RemoteConfig -> Annex RemoteConfig-s3SetCreds c = do- creds <- s3GetCreds c- case creds of- Just (ak, sk) -> do- mcipher <- remoteCipher c- case mcipher of- Just cipher -> do- s <- liftIO $ withEncryptedContent cipher- (return $ L.pack $ unlines [ak, sk])- (return . L.unpack)- return $ M.insert "s3creds" (toB64 s) c- Nothing -> return c- _ -> return c--s3AccessKey :: String-s3AccessKey = "AWS_ACCESS_KEY_ID"-s3SecretKey :: String-s3SecretKey = "AWS_SECRET_ACCESS_KEY"
− Remote/S3stub.hs
@@ -1,13 +0,0 @@--- stub for when hS3 is not available-module Remote.S3 (remote) where--import Types.Remote-import Types--remote :: RemoteType-remote = RemoteType {- typename = "S3",- enumerate = return [],- generate = error "S3 not enabled",- setup = error "S3 not enabled"-}
Remote/Web.hs view
@@ -11,6 +11,7 @@ import Types.Remote import qualified Git import qualified Git.Construct+import Annex.Content import Config import Logs.Web import qualified Utility.Url as Url@@ -55,7 +56,7 @@ return False get urls = do showOutput -- make way for download progress bar- liftIO $ anyM (`Url.download` file) urls+ downloadUrl urls file uploadKey :: Key -> Annex Bool uploadKey _ = do
Seek.hs view
@@ -20,11 +20,10 @@ import qualified Git.LsFiles as LsFiles import qualified Git.CheckAttr import qualified Limit+import qualified Option seekHelper :: ([FilePath] -> Git.Repo -> IO [FilePath]) -> [FilePath] -> Annex [FilePath]-seekHelper a params = do- g <- gitRepo- liftIO $ runPreserveOrder (`a` g) params+seekHelper a params = inRepo $ \g -> runPreserveOrder (`a` g) params withFilesInGit :: (FilePath -> CommandStart) -> CommandSeek withFilesInGit a params = prepFiltered a $ seekHelper LsFiles.inRepo params@@ -40,20 +39,21 @@ go (file, v) = a (readMaybe v) file withBackendFilesInGit :: (BackendFile -> CommandStart) -> CommandSeek-withBackendFilesInGit a params = do- files <- seekHelper LsFiles.inRepo params- prepBackendPairs a files--withFilesMissing :: (String -> CommandStart) -> CommandSeek-withFilesMissing a params = prepFiltered a $ liftIO $ filterM missing params- where- missing = liftM not . doesFileExist+withBackendFilesInGit a params =+ prepBackendPairs a =<< seekHelper LsFiles.inRepo params withFilesNotInGit :: (BackendFile -> CommandStart) -> CommandSeek withFilesNotInGit a params = do- force <- Annex.getState Annex.force- newfiles <- seekHelper (LsFiles.notInRepo force) params- prepBackendPairs a newfiles+ {- dotfiles are not acted on unless explicitly listed -}+ files <- filter (not . dotfile) <$> seek ps+ dotfiles <- if null dotps then return [] else seek dotps+ prepBackendPairs a $ preserveOrder params (files++dotfiles)+ where+ (dotps, ps) = partition dotfile params+ seek l = do+ force <- Annex.getState Annex.force+ g <- gitRepo+ liftIO $ (\p -> LsFiles.notInRepo force p g) l withWords :: ([String] -> CommandStart) -> CommandSeek withWords a params = return [a params]@@ -85,6 +85,22 @@ where parse p = fromMaybe (error "bad key") $ readKey p +withValue :: Annex v -> (v -> CommandSeek) -> CommandSeek+withValue v a params = do+ r <- v+ a r params++{- Modifies a seek action using the value of a field option, which is fed into+ - a conversion function, and then is passed into the seek action.+ - This ensures that the conversion function only runs once.+ -}+withField :: Option -> (Maybe String -> Annex a) -> (a -> CommandSeek) -> CommandSeek+withField option converter = withValue $+ converter =<< Annex.getField (Option.name option)++withFlag :: Option -> (Bool -> CommandSeek) -> CommandSeek+withFlag option = withValue $ Annex.getFlag (Option.name option)+ withNothing :: CommandStart -> CommandSeek withNothing a [] = return [a] withNothing _ _ = error "This command takes no parameters."@@ -99,18 +115,12 @@ prepFilteredGen :: (b -> CommandStart) -> (b -> FilePath) -> Annex [b] -> Annex [CommandStart] prepFilteredGen a d fs = do matcher <- Limit.getMatcher- prepStart (proc matcher) fs+ map (proc matcher) <$> fs where proc matcher v = do let f = d v ok <- matcher f if ok then a v else return Nothing--{- Generates a list of CommandStart actions that will be run to perform a- - command, using a list (ie of files) coming from an action. The list- - will be produced and consumed lazily. -}-prepStart :: (b -> CommandStart) -> Annex [b] -> Annex [CommandStart]-prepStart a = liftM (map a) notSymlink :: FilePath -> IO Bool notSymlink f = liftIO $ not . isSymbolicLink <$> getSymbolicLinkStatus f
Types.hs view
@@ -11,7 +11,8 @@ Key, UUID(..), Remote,- RemoteType+ RemoteType,+ Option ) where import Annex@@ -19,6 +20,7 @@ import Types.Key import Types.UUID import Types.Remote+import Types.Option type Backend = BackendA Annex type Remote = RemoteA Annex
Types/Command.hs view
@@ -32,14 +32,15 @@ type CommandCleanup = Annex Bool {- A command is defined by specifying these things. -}-data Command = Command {- cmdnorepo :: Maybe (IO ()),- cmdcheck :: [CommandCheck],- cmdname :: String,- cmdparams :: String,- cmdseek :: [CommandSeek],- cmddesc :: String-}+data Command = Command+ { cmdoptions :: [Option] -- command-specific options+ , cmdnorepo :: Maybe (IO ()) -- an action to run when not in a repo+ , cmdcheck :: [CommandCheck] -- check stage+ , cmdname :: String+ , cmdparamdesc :: String -- description of params for usage+ , cmdseek :: [CommandSeek] -- seek stage+ , cmddesc :: String -- description of command for usage+ } {- CommandCheck functions can be compared using their unique id. -} instance Eq CommandCheck where
+ Types/Option.hs view
@@ -0,0 +1,17 @@+{- git-annex command options+ -+ - Copyright 2011 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++module Types.Option where++import System.Console.GetOpt++import Annex++{- Each dashed command-line option results in generation of an action+ - in the Annex monad that performs the necessary setting.+ -}+type Option = OptDescr (Annex ())
Upgrade.hs view
@@ -13,12 +13,10 @@ import qualified Upgrade.V1 import qualified Upgrade.V2 -{- Uses the annex.version git config setting to automate upgrades. -} upgrade :: Annex Bool-upgrade = do- version <- getVersion- case version of- Just "0" -> Upgrade.V0.upgrade- Just "1" -> Upgrade.V1.upgrade- Just "2" -> Upgrade.V2.upgrade- _ -> return True+upgrade = go =<< getVersion+ where+ go (Just "0") = Upgrade.V0.upgrade+ go (Just "1") = Upgrade.V1.upgrade+ go (Just "2") = Upgrade.V2.upgrade+ go _ = return True
+ Usage.hs view
@@ -0,0 +1,88 @@+{- git-annex usage messages+ -+ - Copyright 2010-2011 Joey Hess <joey@kitenet.net>+ -+ - Licensed under the GNU GPL version 3 or higher.+ -}++module Usage where++import System.Console.GetOpt++import Types.Command+import Types.Option++{- Usage message with lists of commands and options. -}+usage :: String -> [Command] -> [Option] -> String+usage header cmds commonoptions = unlines $ + [ header+ , ""+ , "Options:"+ ] ++ optlines +++ [ ""+ , "Commands:"+ , ""+ ] ++ cmdlines+ where+ -- To get consistent indentation of options, generate the+ -- usage for all options at once. A command's options will+ -- be displayed after the command.+ alloptlines = filter (not . null) $+ lines $ usageInfo "" $+ concatMap cmdoptions cmds ++ commonoptions+ (cmdlines, optlines) = go cmds alloptlines []+ go [] os ls = (ls, os)+ go (c:cs) os ls = go cs os' (ls++(l:o))+ where+ (o, os') = splitAt (length $ cmdoptions c) os+ l = concat + [ cmdname c+ , namepad (cmdname c)+ , cmdparamdesc c+ , descpad (cmdparamdesc c)+ , cmddesc c+ ]+ pad n s = replicate (n - length s) ' '+ namepad = pad $ longest cmdname + 1+ descpad = pad $ longest cmdparamdesc + 2+ longest f = foldl max 0 $ map (length . f) cmds++{- Descriptions of params used in usage messages. -}+paramPaths :: String+paramPaths = paramOptional $ paramRepeating paramPath -- most often used+paramPath :: String+paramPath = "PATH"+paramKey :: String+paramKey = "KEY"+paramDesc :: String+paramDesc = "DESC"+paramUrl :: String+paramUrl = "URL"+paramNumber :: String+paramNumber = "NUMBER"+paramRemote :: String+paramRemote = "REMOTE"+paramGlob :: String+paramGlob = "GLOB"+paramName :: String+paramName = "NAME"+paramValue :: String+paramValue = "VALUE"+paramUUID :: String+paramUUID = "UUID"+paramType :: String+paramType = "TYPE"+paramDate :: String+paramDate = "DATE"+paramFormat :: String+paramFormat = "FORMAT"+paramKeyValue :: String+paramKeyValue = "K=V"+paramNothing :: String+paramNothing = ""+paramRepeating :: String -> String+paramRepeating s = s ++ " ..."+paramOptional :: String -> String+paramOptional s = "[" ++ s ++ "]"+paramPair :: String -> String -> String+paramPair a b = a ++ " " ++ b
Utility/Gpg.hs view
@@ -23,9 +23,13 @@ stdParams :: [CommandParam] -> IO [String] stdParams params = do -- Enable batch mode if GPG_AGENT_INFO is set, to avoid extraneous- -- gpg output about password prompts.+ -- gpg output about password prompts. GPG_BATCH is set by the test+ -- suite for a similar reason. e <- getEnv "GPG_AGENT_INFO"- let batch = if isNothing e then [] else ["--batch"]+ b <- getEnv "GPG_BATCH"+ let batch = if isNothing e && isNothing b+ then []+ else ["--batch", "--no-tty"] return $ batch ++ defaults ++ toCommand params where -- be quiet, even about checking the trustdb
Utility/Monad.hs view
@@ -20,7 +20,7 @@ then return (Just x) else firstM p xs -{- Returns true if any value in the list satisfies the preducate,+{- Returns true if any value in the list satisfies the predicate, - stopping once one is found. -} anyM :: (Monad m) => (a -> m Bool) -> [a] -> m Bool anyM p = liftM isJust . firstM p@@ -29,10 +29,13 @@ untilTrue :: (Monad m) => [a] -> (a -> m Bool) -> m Bool untilTrue = flip anyM -{- Runs a monadic action, passing its value to an observer- - before returning it. -}+{- Runs an action, passing its value to an observer before returning it. -} observe :: (Monad m) => (a -> m b) -> m a -> m a observe observer a = do r <- a _ <- observer r return r++{- b `after` a runs first a, then b, and returns the value of a -}+after :: (Monad m) => m b -> m a -> m a+after = observe . const
Utility/Path.hs view
@@ -134,3 +134,14 @@ inPath command = getSearchPath >>= anyM indir where indir d = doesFileExist $ d </> command++{- Checks if a filename is a unix dotfile. All files inside dotdirs+ - count as dotfiles. -}+dotfile :: FilePath -> Bool+dotfile file+ | f == "." = False+ | f == ".." = False+ | f == "" = False+ | otherwise = "." `isPrefixOf` f || dotfile (takeDirectory file)+ where+ f = takeFileName file
Utility/Url.hs view
@@ -6,6 +6,7 @@ -} module Utility.Url (+ URLString, exists, canDownload, download,@@ -43,21 +44,21 @@ - would not be appropriate to test at configure time and build support - for only one in. -}-download :: URLString -> FilePath -> IO Bool-download url file = do+download :: URLString -> [CommandParam] -> FilePath -> IO Bool+download url options file = do e <- inPath "wget" if e then- boolSystem "wget"- [Params "-c -O", File file, File url]+ go "wget" [Params "-c -O", File file, File url] else -- Uses the -# progress display, because the normal -- one is very confusing when resuming, showing -- the remainder to download as the whole file, -- and not indicating how much percent was -- downloaded before the resume.- boolSystem "curl" - [Params "-L -C - -# -o", File file, File url]+ go "curl" [Params "-L -C - -# -o", File file, File url]+ where+ go cmd opts = boolSystem cmd (options++opts) {- Downloads a small file. -} get :: URLString -> IO String
debian/changelog view
@@ -1,3 +1,40 @@+git-annex (3.20120113) unstable; urgency=low++ * log: Add --gource mode, which generates output usable by gource.+ * map: Fix display of remote repos+ * Add annex-trustlevel configuration settings, which can be used to + override the trust level of a remote.+ * git-annex, git-union-merge: Support GIT_DIR and GIT_WORK_TREE.+ * Add libghc-testpack-dev to build depends on all arches.++ -- Joey Hess <joeyh@debian.org> Fri, 13 Jan 2012 15:35:17 -0400++git-annex (3.20120106) unstable; urgency=low++ * Support unescaped repository urls, like git does.+ * log: New command that displays the location log for files,+ showing each repository they were added to and removed from.+ * Fix overbroad gpg --no-tty fix from last release.++ -- Joey Hess <joeyh@debian.org> Sat, 07 Jan 2012 13:16:23 -0400++git-annex (3.20120105) unstable; urgency=low++ * Added annex-web-options configuration settings, which can be+ used to provide parameters to whichever of wget or curl git-annex uses+ (depends on which is available, but most of their important options+ suitable for use here are the same).+ * Dotfiles, and files inside dotdirs are not added by "git annex add"+ unless the dotfile or directory is explicitly listed. So "git annex add ."+ will add all untracked files in the current directory except for those in+ dotdirs.+ * Added quickcheck to build dependencies, and fail if test suite cannot be+ built.+ * fsck: Do backend-specific check before checking numcopies is satisfied.+ * Run gpg with --no-tty. Closes: #654721++ -- Joey Hess <joeyh@debian.org> Thu, 05 Jan 2012 13:44:12 -0400+ git-annex (3.20111231) unstable; urgency=low * sync: Improved to work well without a central bare repository.
debian/control view
@@ -12,7 +12,8 @@ libghc-http-dev, libghc-utf8-string-dev, libghc-hs3-dev (>= 0.5.6),- libghc-testpack-dev [any-i386 any-amd64],+ libghc-testpack-dev,+ libghc-quickcheck2-dev, libghc-monad-control-dev (>= 0.3), libghc-lifted-base-dev, libghc-json-dev,
debian/copyright view
@@ -2,7 +2,7 @@ Source: native package Files: *-Copyright: © 2010-2011 Joey Hess <joey@kitenet.net>+Copyright: © 2010-2012 Joey Hess <joey@kitenet.net> License: GPL-3+ The full text of version 3 of the GPL is distributed as doc/GPL in this package's source, or in /usr/share/common-licenses/GPL-3 on
+ doc/NixOS.mdwn view
@@ -0,0 +1,5 @@+Users of the [Nix package manager](http://nixos.org/) can install it by running:++ nix-env -i git-annex++The build status of the package within Nix can be seen on the [Hydra Build Farm](http://hydra.nixos.org/job/nixpkgs/trunk/gitAndTools.gitAnnex).
+ doc/bugs/Lost_S3_Remote.mdwn view
@@ -0,0 +1,59 @@+Somehow I've lost my S3 remote... git-annex knows it's there, but its not associating it with the git remote in .git/config++ $ git-annex whereis pebuilder.iso + whereis pebuilder.iso (3 copies) + 3b6fc6f6-3025-11e1-b496-33bffbc0f3ed -- housebackup (external seagate drive on /mnt/back/RemoteStore)+ 6b1326d8-2abb-11e1-8f43-979159a7f900 -- synology+ 9b297772-2ab2-11e1-a86f-2fd669cb2417 -- Amazon S3+ ok++Amazon S3 is the description from the remote. My .git/config file contains this block:++ [remote "cloud"]+ annex-s3 = true+ annex-uuid = 9b297772-2ab2-11e1-a86f-2fd669cb2417+ annex-cost = 70++The UUID matches... But I cannot access it... see below:++ [39532:39531 - 0:626] 08:20:38 [vivitron@tronlap:o +3] ~/annex/ISO + $ git-annex get pebuilder.iso --from=cloud+ git-annex: there is no git remote named "cloud"+ + [39532:39531 - 0:627] 08:20:56 [vivitron@tronlap:o +3] ~/annex/ISO + $ git-annex get pebuilder.iso --from="Amazon S3"+ git-annex: there is no git remote named "Amazon S3"+ + [39532:39531 - 0:628] 08:21:01 [vivitron@tronlap:o +3] ~/annex/ISO + $ git-annex get pebuilder.iso --from=9b297772-2ab2-11e1-a86f-2fd669cb2417+ git-annex: there is no git remote named "9b297772-2ab2-11e1-a86f-2fd669cb2417"++ [39532:39531 - 0:629] 08:21:08 [vivitron@tronlap:o +3] ~/annex/ISO + $ ++git remote lists "cloud" as a remote:++ $ git remote+ all+ cloud+ cs+ es3+ origin++git-annex status lists S3 support:++ $ git-annex status+ supported backends: SHA256 SHA1 SHA512 SHA224 SHA384 SHA256E SHA1E SHA512E SHA224E SHA384E WORM URL+ supported remote types: git S3 bup directory rsync web hook++++I appreciate any help.... I've tested versions 3.20111211, 3.20111231, and 3.20120105++ $ git --version+ git version 1.7.8.1++++> [[done]]; I've fixed the build system so this confusing thing cannot+> happen anymore. --[[Joey]]
+ doc/bugs/Lost_S3_Remote/comment_1_6e80e6db6671581d471fc9a54181c04c._comment view
@@ -0,0 +1,10 @@+[[!comment format=mdwn+ username="http://joey.kitenet.net/"+ nickname="joey"+ subject="comment 1"+ date="2012-01-06T03:04:35Z"+ content="""+Despite `status` listing S3 support, your git-annex is actually built with S3stub, probably because it failed to find the necessary S3 module at build time. Rebuild git-annex and watch closely, you'll see \"** building without S3 support\". Look above that for the error and fix it.++It was certianly a bug that it showed S3 as supported when built without it. I've fixed that.+"""]]
+ doc/bugs/Lost_S3_Remote/comment_2_c99c65882a3924f4890e500f9492b442._comment view
@@ -0,0 +1,8 @@+[[!comment format=mdwn+ username="http://joey.kitenet.net/"+ nickname="joey"+ subject="comment 2"+ date="2012-01-06T03:08:28Z"+ content="""+BTW, you'll want to \"make clean\", since the S3stub hack symlinks a file into place and it will continue building with S3stub even if you fix the problem until you clean.+"""]]
+ doc/bugs/Lost_S3_Remote/comment_3_1e434d5a20a692cd9dc7f6f8f20f30dd._comment view
@@ -0,0 +1,8 @@+[[!comment format=mdwn+ username="https://www.google.com/accounts/o8/id?id=AItOawkey8WuXUh_x5JC2c9_it1CYRnVTgdGu1M"+ nickname="Dustin"+ subject="Thank you!"+ date="2012-01-06T03:38:27Z"+ content="""+make clean and rebuild worked... Thank you+"""]]
+ doc/bugs/__34__make_test__34___fails_silently.mdwn view
@@ -0,0 +1,4 @@+`make test` fails silently when the test program cannot be built. This happens, for example, when attempting to compile git-annex with `QuickCheck-2.4.2`.++> I've made "make test" exit nonzero if the test suite cannot be built.+> [[done]] --[[Joey]]
+ doc/bugs/conq:_invalid_command_syntax.mdwn view
@@ -0,0 +1,30 @@+I've been getting an occasional error from git-annex.++The error is: 'conq: invalid command syntax.'++For example, the last two commands I ran are:++ $ git annex unused+ unused . (checking for unused data...) (checking master...) (checking origin/master...) + Some annexed data is no longer used by any files:+ NUMBER KEY+ 1 SHA256-s.....+ (To see where data was previously used, try: git log --stat -S'KEY')+ + To remove unwanted data: git-annex dropunused NUMBER+ + ok+ + $ git annex dropunused 1+ dropunused 1 conq: invalid command syntax.+ ok++++*OS:* OSX + port installs of the GNU tools++*git-annex-version:* 3.20111211++*git-version:* 1.7.7.4++> [[done]], apparently not a git-annex bug --[[Joey]]
+ doc/bugs/conq:_invalid_command_syntax/comment_1_f33b83025ce974e496f83f248275a66a._comment view
@@ -0,0 +1,10 @@+[[!comment format=mdwn+ username="http://joey.kitenet.net/"+ nickname="joey"+ subject="comment 1"+ date="2012-01-03T00:34:59Z"+ content="""+AFAICs, you probably just have a \"conq\" program that is running in the background and emitted this error.++The error message is not part of git-annex; it does not run any \"conq\" thing itself. Although you could try passing the --debug parameter to check the commands it does run to see if one of them somehow causes this conq thing.+"""]]
+ doc/bugs/conq:_invalid_command_syntax/comment_2_195106ca8dedad5f4d755f625e38e8af._comment view
@@ -0,0 +1,9 @@+[[!comment format=mdwn+ username="http://joey.kitenet.net/"+ nickname="joey"+ subject="comment 2"+ date="2012-01-03T00:41:08Z"+ content="""+A google search <http://www.google.com/search?hl=en&sclient=psy-ab&q=conq%3A+invalid+command+syntax&btnG=>+finds other examples of this error message related to ssh, mercurial, and bitbucket. What that has to do with git is anyone's guess, but I'm pretty sure git-annex is not related to it at all.+"""]]
+ doc/bugs/conq:_invalid_command_syntax/comment_3_55af43e2f43a4c373f7a0a33678d0b1c._comment view
@@ -0,0 +1,15 @@+[[!comment format=mdwn+ username="http://a-or-b.myopenid.com/"+ ip="203.45.2.230"+ subject="comment 3"+ date="2012-01-03T00:49:41Z"+ content="""+Yeah, I saw those google links myself, but couldn't see why the bitbucket/ssh would be relevant.++The strange thing is that I *only* get this message when running git-annex.++I also don't have a conq in my path so I don't know where it is running from.+ ++Oh well, if I ever sort it out I'll post back here.+"""]]
doc/bugs/on--git-dir_and_--work-tree_options.mdwn view
@@ -27,3 +27,5 @@ git-annex version: 3.20110702 +> [[done]], git-annex now honors `GIT_DIR` and `GIT_WORK_TREE` like other+> git commands do. --[[Joey]]
+ doc/bugs/signal_weirdness.mdwn view
@@ -0,0 +1,38 @@+For the record, there is a slight weirdness with how git-annex+handles a signal like ctrl-c.++For example:++ joey@gnu:~/tmp/b>git annex copy a b --to origin+ copy a (checking origin...) (to origin...) + SHA256-s104857600--20492a4d0d84f8beb1767f6616229f85d44c2827b64bdbfb260ee12fa1109e0e+ 3272 0% 0.00kB/s 0:00:00 ^C+ zsh: interrupt git annex copy a --to origin+ joey@gnu:~/tmp/b>+ rsync error: unexplained error (code 130) at rsync.c(549) [sender=3.0.9]++Here git-annex exits before rsync has fully exited. Not a large problem+but sorta weird.++The culprit is `safeSystemEnv` in Utility.SafeCommand, which installs+a default signal handler for SIGINT, which causes it to immediatly+terminate git-annex. rsync, in turn, has its own SIGINT handler, which +prints the message, typically later.++(Why it prints that message and not its more usual message about having+received a signal, I'm not sure?)++It's more usual for a `system` like thing to block SIGINT, letting the child+catch it and exit, and then detecting the child's exit status and terminating. +However, since rsync *is* trapping SIGINT, and exiting nonzero explicitly,+git-annex can't tell that rsync failed due to a SIGINT.+And, git-annex typically doesn't stop when a single child fails. In the+example above, it would go on to copy `b` after a ctrl-c!++A further complication is that git-annex is itself a child process+of git, which does not block SIGINT either. So if git-annex blocks sigint,+it will be left running in the background after git exits, and continuing+with further actions too. (Probably this is a bug in git.)++Which is why the current behavior of not blocking SIGINT was chosen,+as a less bad alternative. Still, I'd like to find a better one. --[[Joey]]
doc/feeds.mdwn view
@@ -1,3 +1,5 @@ Aggregating git-annex mentions from elsewhere on the net.. * [[!aggregate expirecount=25 name="identica" feedurl="http://identi.ca/api/statusnet/tags/timeline/gitannex.rss" url="http://identi.ca/tag/gitannex"]]+* [[!aggregate expirecount=25 name="twitter" feedurl="http://search.twitter.com/search.atom?q=git-annex" url="http://twitter.com/"]]+
+ doc/forum/Auto_archiving.mdwn view
@@ -0,0 +1,17 @@+I've been toying with the idea of auto archiving files (that is - removing them from .) based on a set of rules.++Git already provides attribute management for files and I put together a simple script that tries to achieve the following:++* Look for files with X copies (including a local one)+* Verify that the file is not recent (defined as not having been dropped or getted within X days )+* Verify that the file has an annex.archive attribute+* Archive if the above is met++Here is the script:+http://pastebin.com/53iLqyPd++You just add the annex.archive attribute to files via .gitattributes to use++The script runs in preview mode... exec with autoArchive.sh commit to drop the files.++Open to thoughts / suggestions
+ doc/forum/Handling_web_special_remote_when_content_changes__63__.mdwn view
@@ -0,0 +1,19 @@+I am in the process of organising all of my documents (pdf/ps/etc.) and putting them into an annex. It seems like the easiest (and smartest?) way for me to manage my 15,000+ document library... (Yeah, I've not read them all!)++However, one of the issues I have run into is when I want to include something like a software manual...++I'm not even sure if git-annex is the correct way to handle these sort of document, but...++What would you do if the URL stays the same, but the file content changes over time?++For example, the administration manual for R gets updated and re-released for each release of R, but the URL stays the same.++ http://cran.r-project.org/doc/manuals/R-admin.pdf++I'm not particularly worried about whether my annex version is the most recent, just that if I want to 'annex get' it, it will pull *a* version from somewhere.++Any thoughts?++I'd bet that the SHA-hash would change between releases(!) so would a WORM backend be the best approach? It would mess up my one-file-in-multiple-directories (i.e. multiple simlinks to the one SHA-...-.....) approach.++
+ doc/forum/git-subtree_support__63__.mdwn view
@@ -0,0 +1,9 @@+Hi,++I am a happy user of [git-subtree](http://github.com/apenwarr/git-subtree), and I wonder whether it integrates nicely with git-annex?++My use-case looks like this: I have two annex repositories -- one at home and one at work. The annex at work is a strict subset of the one at home, i.e. all files that I have at work ought to be part of the annex at home, but not the other way round. Now, I realize that I could have one annex and selectively copy files to the checked out copy at work, but I don't want to do that because I don't want to have (broken) symlinks for all kinds of stuff visible on my machine at work that is not supposed to be there (such as MP3 files, etc.). Instead, I would like to use git-subtree to import the work annex into a sub-directory of the one at home, so that both annex are logically separate, but still the one at home always contains everything that the one at work contains.++Is that possible?++And if not, is there maybe another way to accomplish this kind of thing?
+ doc/forum/git-subtree_support__63__/comment_1_4f333cb71ed1ff259bbfd86704806aa6._comment view
@@ -0,0 +1,10 @@+[[!comment format=mdwn+ username="http://joey.kitenet.net/"+ nickname="joey"+ subject="comment 1"+ date="2012-01-03T17:00:53Z"+ content="""+I have no experience using git-subtree, but as long as the home repository has the work one as a git remote, it will automatically merge work's git-annex branch with its own git-annex branch, and so will know what files are present at work, and will be able to get them.++Probably you won't want to make work have home as a remote, so work's git-annex will not know which files home has, nor will it be able to copy files to home (but home will be able to copy files to work).+"""]]
+ doc/forum/git-subtree_support__63__/comment_2_73d2a015b1ac79ec99e071a8b1e29034._comment view
@@ -0,0 +1,8 @@+[[!comment format=mdwn+ username="http://peter-simons.myopenid.com/"+ ip="77.188.44.113"+ subject="comment 2"+ date="2012-01-03T18:11:37Z"+ content="""+The point of git-subtree is that I can import another repository into sub-directory, i.e. I can have a directory called \"work\" that contains all files from the annex I have at work. If I make the other annex a remote and merge its contents, then all contents is going to be merged at the top-level, which is somewhat undesirable in my particular case.+"""]]
+ doc/forum/git-subtree_support__63__/comment_3_c533400e22c306c033fcd56e64761b0b._comment view
@@ -0,0 +1,8 @@+[[!comment format=mdwn+ username="http://joey.kitenet.net/"+ nickname="joey"+ subject="comment 3"+ date="2012-01-03T18:42:08Z"+ content="""+You can make it a remote without merging its contents. Git will not merge its contents by default unless it's named \"origin\". git-annex will be prefectly happy with that.+"""]]
+ doc/forum/git-subtree_support__63__/comment_4_75b0e072e668aa46ff0a8d62a6620306._comment view
@@ -0,0 +1,8 @@+[[!comment format=mdwn+ username="http://peter-simons.myopenid.com/"+ ip="77.188.44.113"+ subject="comment 4"+ date="2012-01-03T19:17:36Z"+ content="""+Okay, I see, but is `git annex get --auto .` going to import all those files from the work remote into my home if the `master` branch of that remote isn't merged?+"""]]
+ doc/forum/git-subtree_support__63__/comment_5_f5ec9649d9f1dc122e715de5533bc674._comment view
@@ -0,0 +1,8 @@+[[!comment format=mdwn+ username="http://joey.kitenet.net/"+ nickname="joey"+ subject="comment 5"+ date="2012-01-03T19:31:45Z"+ content="""+Yes; git-annex uses the git-annex branch independently of the branch you have checked out. You may find [[internals]] interesting reading, but the short answer is it will work.+"""]]
+ doc/forum/git-subtree_support__63__/comment_6_85df530f7b6d76b74ac8017c6034f95e._comment view
@@ -0,0 +1,8 @@+[[!comment format=mdwn+ username="http://peter-simons.myopenid.com/"+ ip="77.188.44.113"+ subject="comment 6"+ date="2012-01-03T19:47:11Z"+ content="""+Very cool! Thank you for the explanation.+"""]]
+ doc/forum/unlock__47__lock_always_gets_me.mdwn view
@@ -0,0 +1,11 @@+Several times now I've done something like:++ $ git annex unlock movie.avi+ $ mv /tmp/fixed.avi movie.avi+ $ git annex lock movie.avi++Oops, I just lost my fixed.avi! That really feels like the right sequence of operations to me, so I'm always surprised when I make that mistake. I would like to see the current `lock` renamed to something like `undo-unlock`, or have the behavior changed to be the same as `add`, or maybe warn and require a `--force` when the file has been changed.++If changing current behavior is undesirable, maybe `unlock` could just print a reminder that `git annex add` is the correct next step after making changes?++Failing that, I suppose I could slowly start to learn from my mistakes.
+ doc/forum/unlock__47__lock_always_gets_me/comment_1_dee73a7ea3e1a5154601adb59782831f._comment view
@@ -0,0 +1,12 @@+[[!comment format=mdwn+ username="http://joey.kitenet.net/"+ nickname="joey"+ subject="comment 1"+ date="2012-01-07T17:15:31Z"+ content="""+Well, lock could check for modifications and require --force to lose them. But the check could be expensive for large files.++But `git annex lock` is just a convenient way to run `git checkout`. And running `git checkout` or `git reset --hard` will lose your uncommitted file the same way obviously. ++Perhaps the best fix would be to get rid of `lock` entirely, and let the user use the underlying git commands same as they would to drop modifications to other files. It would then also make sense to remove `unlock`, leaving only `edit`.+"""]]
doc/git-annex.mdwn view
@@ -64,7 +64,8 @@ Adds files in the path to the annex. Files that are already checked into git, or that git has been configured to ignore will be silently skipped.- (Use --force to add ignored files.)+ (Use --force to add ignored files.) Dotfiles are skipped unless explicitly+ listed. * get [path ...] @@ -127,8 +128,8 @@ the default is to sync with all remotes. Or specify --fast to sync with the remotes with the lowest annex-cost value. - The sync process involves first committing all local changes, then- fetching and merging the `synced/master` and the `git-annex` branch+ The sync process involves first committing all local changes (git commit -a),+ then fetching and merging the `synced/master` and the `git-annex` branch from the remote repositories and finally pushing the changes back to those branches on the remote repositories. You can use standard git commands to do each of those steps by hand, or if you don't want to@@ -272,6 +273,18 @@ Displays a list of repositories known to contain the content of the specified file or files. +* log [path ...]++ Displays the location log for the specified file or files,+ showing each repository they were added to ("+") and removed from ("-").++ To limit how far back to seach for location log changes, the options+ --since, --after, --until, --before, and --max-count can be specified.+ They are passed through to git log. For example, --since "1 month ago"++ To generate output suitable for the gource visualisation program,+ specify --gource.+ * status Displays some statistics and other information, including how much data@@ -593,6 +606,12 @@ git-annex caches UUIDs of remote repositories here. +* `remote.<name>.annex-trustlevel`++ Configures a local trust level for the remote. This overrides the value+ configured by the trust and untrust commands. The value can be any of+ "trusted", "semitrusted" or "untrusted".+ * `remote.<name>.annex-ssh-options` Options to use when using ssh to talk to this remote.@@ -603,16 +622,22 @@ to or from this remote. For example, to force ipv6, and limit the bandwidth to 100Kbyte/s, set it to "-6 --bwlimit 100" +* `remote.<name>.annex-web-options`++ Options to use when using wget or curl to download a file from the web.+ (wget is always used in preference to curl if available).+ For example, to force ipv4 only, set it to "-4"+ * `remote.<name>.annex-bup-split-options` Options to pass to bup split when storing content in this remote. For example, to limit the bandwidth to 100Kbye/s, set it to "--bwlimit 100k" (There is no corresponding option for bup join.) -* `annex.ssh-options`, `annex.rsync-options`, `annex.bup-split-options`+* `annex.ssh-options`, `annex.rsync-options`, `annex.web-options, `annex.bup-split-options` - Default ssh, rsync, and bup options to use if a remote does not have- specific options.+ Default ssh, rsync, wget/curl, and bup options to use if a remote does not+ have specific options. * `remote.<name>.buprepo`
+ doc/how_it_works.mdwn view
@@ -0,0 +1,41 @@+This page gives a high-level view of git-annex. For a detailed+low-level view, see [[the_man_page|git-annex]] and [[internals]].++You do not need to read this page to get started with using git-annex. The+[[walkthrough]] provides step-by-step instructions.++Still reading? Ok. Git's man page calls it "a stupid content+tracker". With git-annex, git is instead "a stupid filename and metadata"+tracker. The contents of large files are not stored in git, only the+names of the files and some other metadata remain there.++The contents of the files are kept by git-annex in a distributed key/value+store consisting of every clone of a given git repository. That's a fancy+way to say that git-annex stores the actual file content somewhere under+`.git/annex/`. (See [[internals]] for details.)++That was the values; what about the keys? Well, a key is calculated for a+given file when it's first added into git-annex. Normally this uses a hash+of its contents, but various [[backends]] can produce different sorts of+keys. The file that gets checked into git is just a symlink to the key+under `.git/annex/`. If the content of a file is modified, that produces+a different key (and the symlink is changed).++A file's content can be [[transferred|transferring_data]] from one+repository to another by git-annex. Which repositories contain a given+value is tracked by git-annex (see [[location_tracking]]). It stores this+tracking information in a separate branch, named "git-annex". All you ever+do with the "git-annex" branch is push/pull it around between repositories,+to [[sync]] up git-annex's view of the world.++That's really all there is to it. Oh, there are [[special_remotes]] that+let values be stored other places than git repositories (anything from+Amazon S3 to a USB key), and there's a pile of commands listed in+[[the_man_page|git-annex]] to handle moving the values around and managing+them. But if you grok the description above, you can see through all that.+It's really just symlinks, keys, values, and a git-annex branch to store+additional metadata.++---++Next: [[install]] or [[walkthrough]]
doc/index.mdwn view
@@ -1,6 +1,6 @@ [[!inline raw=yes pages="summary"]] -To get a feel for it, see the [[walkthrough]].+To get a feel for it, see the [[walkthrough]] or read about [[how_it_works]]. [[!sidebar content=""" [[!img logo_small.png link=no]]@@ -51,11 +51,13 @@ * [[internals]] * [[design]] * [[what git annex is not|not]]-* git-annex is Free Software, licensed under the [[GPL]].+* [[sitemap]] <br clear="all" /> ----++git-annex is Free Software, licensed under the [[GPL]]. git-annex's wiki is powered by [Ikiwiki](http://ikiwiki.info/) and hosted by [Branchable](http://branchable.com/).
doc/install.mdwn view
@@ -6,6 +6,9 @@ * [[Fedora]] * [[FreeBSD]] * [[openSUSE]]+* [[ArchLinux]]+* [[NixOS]]+* Windows: [[sorry, not possible yet|todo/windows_support]] ## Using cabal @@ -29,7 +32,7 @@ * [TestPack](http://hackage.haskell.org/cgi-bin/hackage-scripts/package/testpack) * [QuickCheck 2](http://hackage.haskell.org/package/QuickCheck) * [HTTP](http://hackage.haskell.org/package/HTTP)- * [hS3](http://hackage.haskell.org/package/hS3) (optional, but recommended)+ * [hS3](http://hackage.haskell.org/package/hS3) * [json](http://hackage.haskell.org/package/json) * Shell commands * [git](http://git-scm.com/)
+ doc/install/ArchLinux.mdwn view
@@ -0,0 +1,9 @@+There is a non-official source package for git-annex in+[AUR](https://aur.archlinux.org/packages.php?ID=44272).++You can then build it yourself or use a wrapper for AUR+such as yaourt:++<pre>+$ yaourt -Sy git-annex+</pre>
− doc/install/comment_3_cff163ea3e7cad926f4ed9e78b896598._comment
@@ -1,10 +0,0 @@-[[!comment format=mdwn- username="https://www.google.com/accounts/o8/id?id=AItOawmByD9tmR48HuYgS4qWEGDDaoVTTC3m4kc"- nickname="Jonas"- subject="Any chance to get git-annex going on windows?"- date="2011-06-10T18:08:36Z"- content="""-Would be great! :-)--Jonas-"""]]
− doc/install/comment_4_82a17eee4a076c6c79fddeda347e0c9a._comment
@@ -1,69 +0,0 @@-[[!comment format=mdwn- username="http://joey.kitenet.net/"- nickname="joey"- subject="short answer: no"- date="2011-06-10T19:55:38Z"- content="""-Long answer, quoting from a mail to someone else:--Well, I can tell you that it assumes a POSIX system, both in available-utilities and system calls, So you'd need to use cygwin or something-like that. (Perhaps you already are for git, I think git also assumes a-POSIX system.) So you need a Haskell that can target that. What this-page refers to as \"GHC-Cygwin\":-<http://www.haskell.org/ghc/docs/6.6/html/building/platforms.html>-I don't know where to get one. Did find this:-<http://copilotco.com/mail-archives/haskell-cafe.2007/msg00824.html>--(There are probably also still some places where it assumes / as a path-separator, although I fixed some.)--FWIW, git-annex works fine on OS X and other fine proprietary unixen. ;P--------Alternatively, windows versions of these functions could be found,-which are all the ones that need POSIX, I think. A fair amount of this,-the stuff to do with signals and users, could be empty stubs in windows.-The file manipulation, particularly symlinks, would probably be the main-challenge.--<pre>-addSignal-blockSignals-changeWorkingDirectory-createLink-createSymbolicLink-emptySignalSet-executeFile-fileMode-fileSize-forkProcess-getAnyProcessStatus-getEffectiveUserID-getEnvDefault-getFileStatus-getProcessID-getProcessStatus-getSignalMask-getSymbolicLinkStatus-getUserEntryForID-getUserEntryForName-groupWriteMode-homeDirectory-installHandler-intersectFileModes-isRegularFile-isSymbolicLink-modificationTime-otherWriteMode-ownerWriteMode-readSymbolicLink-setEnv-setFileMode-setSignalMask-sigCHLD-sigINT-unionFileModes-</pre>-"""]]
doc/news.mdwn view
@@ -3,7 +3,7 @@ posted. git-annex users are recommended to subscribe to this page's RSS feed. -[[!inline pages="./news/* and !*/Discussion" rootpage="news" show="30"]]+[[!inline pages="./news/* and !./news/*/* and !*/Discussion" rootpage="news" show="30"]] """ else="""
− doc/news/version_3.20111107.mdwn
@@ -1,8 +0,0 @@-git-annex 3.20111107 released with [[!toggle text="these changes"]]-[[!toggleable text="""- * merge: Use fast-forward merges when possible.- Thanks Valentin Haenel for a test case showing how non-fast-forward- merges could result in an ongoing pull/merge/push cycle.- * Don't try to read config from repos with annex-ignore set.- * Bugfix: In the past two releases, git-annex init has written the uuid.log- in the wrong format, with the UUID and description flipped."""]]
− doc/news/version_3.20111111.mdwn
@@ -1,10 +0,0 @@-git-annex 3.20111111 released with [[!toggle text="these changes"]]-[[!toggleable text="""- * Handle a case where an annexed file is moved into a gitignored directory,- by having fix --force add its change.- * Avoid cyclic drop problems.- * Optimized copy --from and get --from to avoid checking the location log- for files that are already present.- * Automatically fix up badly formatted uuid.log entries produced by- 3.20111105, whenever the uuid.log is changed (ie, by init or describe).- * map: Support remotes with /~/ and /~user/"""]]
− doc/news/version_3.20111122.mdwn
@@ -1,22 +0,0 @@-git-annex 3.20111122 released with [[!toggle text="these changes"]]-[[!toggleable text="""- * merge: Improve commit messages to mention what was merged.- * Avoid doing auto-merging in commands that don't need fully current- information from the git-annex branch. In particular, git annex add- no longer needs to auto-merge.- * init: When run in an already initalized repository, and without- a description specified, don't delete the old description.- * Optimised union merging; now only runs git cat-file once, and runs- in constant space.- * status: Now displays trusted, untrusted, and semitrusted repositories- separately.- * status: Include all special remotes in the list of repositories.- * status: Fix --json mode.- * status: --fast is back- * Fix support for insteadOf url remapping. Closes: #[644278](http://bugs.debian.org/644278)- * When not run in a git repository, git-annex can still display a usage- message, and "git annex version" even works.- * migrate: Don't fall over a stale temp file.- * Avoid excessive escaping for rsync special remotes that are not accessed- over ssh.- * find: Support --print0"""]]
− doc/news/version_3.20111122~bpo60+2.mdwn
@@ -1,22 +0,0 @@-git-annex 3.20111122~bpo60+2 released with [[!toggle text="these changes"]]-[[!toggleable text="""- * merge: Improve commit messages to mention what was merged.- * Avoid doing auto-merging in commands that don't need fully current- information from the git-annex branch. In particular, git annex add- no longer needs to auto-merge.- * init: When run in an already initalized repository, and without- a description specified, don't delete the old description.- * Optimised union merging; now only runs git cat-file once, and runs- in constant space.- * status: Now displays trusted, untrusted, and semitrusted repositories- separately.- * status: Include all special remotes in the list of repositories.- * status: Fix --json mode.- * status: --fast is back- * Fix support for insteadOf url remapping. Closes: #[644278](http://bugs.debian.org/644278)- * When not run in a git repository, git-annex can still display a usage- message, and "git annex version" even works.- * migrate: Don't fall over a stale temp file.- * Avoid excessive escaping for rsync special remotes that are not accessed- over ssh.- * find: Support --print0"""]]
− doc/news/version_3.20111203.mdwn
@@ -1,19 +0,0 @@-git-annex 3.20111203 released with [[!toggle text="these changes"]]-[[!toggleable text="""- * The VFAT filesystem on recent versions of Linux, when mounted with- shortname=mixed, does not get along well with git-annex's mixed case- .git/annex/objects hash directories. To avoid this problem, new content- is now stored in all-lowercase hash directories. Except for non-bare- repositories which would be a pain to transition and cannot be put on FAT.- (Old mixed-case hash directories are still tried for backwards- compatibility.)- * Flush json output, avoiding a buffering problem that could result in- doubled output.- * Avoid needing haskell98 and other fixes for new ghc. Thanks, Mark Wright.- * Bugfix: dropunused did not drop keys with two spaces in their name.- * Support for storing .git/annex on a different device than the rest of the- git repository.- * --inbackend can be used to make git-annex only operate on files- whose content is stored using a specified key-value backend.- * dead: A command which says that a repository is gone for good- and you don't want git-annex to mention it again."""]]
− doc/news/version_3.20111211.mdwn
@@ -1,20 +0,0 @@-git-annex 3.20111211 released with [[!toggle text="these changes"]]-[[!toggleable text="""- * Fix bug in last version in getting contents from bare repositories.- * Ensure that git-annex branch changes are merged into git-annex's index,- which fixes a bug that could cause changes that were pushed to the- git-annex branch to get reverted. As a side effect, it's now safe- for users to check out and commit changes directly to the git-annex- branch.- * map: Fix a failure to detect a loop when both repositories are local- and refer to each other with relative paths.- * Prevent key names from containing newlines.- * add: If interrupted, add can leave files converted to symlinks but not- yet added to git. Running the add again will now clean up this situtation.- * Fix caching of decrypted ciphers, which failed when drop had to check- multiple different encrypted special remotes.- * unannex: Can be run on files that have been added to the annex, but not- yet committed.- * sync: New command that synchronises the local repository and default- remote, by running git commit, pull, and push for you.- * Version monad-control dependency in cabal file."""]]
+ doc/news/version_3.20120105.mdwn view
@@ -0,0 +1,14 @@+git-annex 3.20120105 released with [[!toggle text="these changes"]]+[[!toggleable text="""+ * Added annex-web-options configuration settings, which can be+ used to provide parameters to whichever of wget or curl git-annex uses+ (depends on which is available, but most of their important options+ suitable for use here are the same).+ * Dotfiles, and files inside dotdirs are not added by "git annex add"+ unless the dotfile or directory is explicitly listed. So "git annex add ."+ will add all untracked files in the current directory except for those in+ dotdirs.+ * Added quickcheck to build dependencies, and fail if test suite cannot be+ built.+ * fsck: Do backend-specific check before checking numcopies is satisfied.+ * Run gpg with --no-tty. Closes: #[654721](http://bugs.debian.org/654721)"""]]
+ doc/news/version_3.20120106.mdwn view
@@ -0,0 +1,6 @@+git-annex 3.20120106 released with [[!toggle text="these changes"]]+[[!toggleable text="""+ * Support unescaped repository urls, like git does.+ * log: New command that displays the location log for files,+ showing each repository they were added to and removed from.+ * Fix overbroad gpg --no-tty fix from last release."""]]
+ doc/news/version_3.20120106/comment_1_fb1a3135e2d9f39f2c372ccc2c50c85a._comment view
@@ -0,0 +1,8 @@+[[!comment format=mdwn+ username="http://peter-simons.myopenid.com/"+ ip="77.186.134.113"+ subject="Not announced on Hackage?"+ date="2012-01-13T17:37:11Z"+ content="""+We have the [latest version in NixOS](http://hydra.nixos.org/job/nixpkgs/trunk/gitAndTools.gitAnnex), but we cannot advertise that fact on Hackage because it seems the corresponding Cabal file hasn't been uploaded to <http://hackage.haskell.org/package/git-annex>. Is there any particular reason why Hackage doesn't know about this release?+"""]]
+ doc/news/version_3.20120106/comment_2_ae292ca7294b6790233e545086c3ac2f._comment view
@@ -0,0 +1,10 @@+[[!comment format=mdwn+ username="http://joey.kitenet.net/"+ nickname="joey"+ subject="comment 2"+ date="2012-01-13T17:52:46Z"+ content="""+Uploading to hackage is a PITA (manual password entry and I am often on a slow link besides) and is not integrated with my regular release process, so I often forget to do it. I will try to upload the next release there again.++You might add a page under [[install]] for your git-annex packages.+"""]]
+ doc/news/version_3.20120106/comment_3_29ccda9ac458fd5cc9ec5508c62df6ea._comment view
@@ -0,0 +1,12 @@+[[!comment format=mdwn+ username="http://peter-simons.myopenid.com/"+ ip="77.186.134.113"+ subject="comment 3"+ date="2012-01-13T18:48:28Z"+ content="""+For what it's worth, the package `cabal-install` is pretty good for uploading packages to Hackages, among other things. It allows users to configure their username/password, and then making a release to Hackage is as simple as running:++ cabal upload foo-version.tar.gz++I use that to do releases of my stuff, too, and I'm quite happy. `cabal-install` has other features, too, of course.+"""]]
+ doc/news/version_3.20120113.mdwn view
@@ -0,0 +1,8 @@+git-annex 3.20120113 released with [[!toggle text="these changes"]]+[[!toggleable text="""+ * log: Add --gource mode, which generates output usable by gource.+ * map: Fix display of remote repos+ * Add annex-trustlevel configuration settings, which can be used to+ override the trust level of a remote.+ * git-annex, git-union-merge: Support GIT\_DIR and GIT\_WORK\_TREE.+ * Add libghc-testpack-dev to build depends on all arches."""]]
− doc/news/version_backport.mdwn
@@ -1,6 +0,0 @@-git-annex backport released with [[!toggle text="these changes"]]-[[!toggleable text="""- * Removed conflict on newer version of git, this backport can now be used- with either stable's git, or the git backport.- * This backport continues to be modified to not build without monad-control,- which is not available in stable."""]]
+ doc/sitemap.mdwn view
@@ -0,0 +1,3 @@+[[!map pages="page(*) and !*/discussion and !recentchanges+and !bugs/* and !examples/*/* and !news/* and !tips/*+and !forum/* and !todo/* and !users/* and !ikiwiki/*"]]
+ doc/tips/using_gitolite_with_git-annex/comment_9_28418635a6ed7231b89e02211cd3c236._comment view
@@ -0,0 +1,8 @@+[[!comment format=mdwn+ username="http://joey.kitenet.net/"+ nickname="joey"+ subject="comment 9"+ date="2012-01-02T16:27:55Z"+ content="""+Ah right. git-annex normalizes all git ssh style user@host:dir to valid uris, which is where the `/~/` comes from. I don't anticipate this changing on the git-annex side.+"""]]
+ doc/tips/visualizing_repositories_with_gource.mdwn view
@@ -0,0 +1,22 @@+[Gource](http://code.google.com/p/gource/) is an amazing animated+visualisation of a git repository.++Normally, gource shows files being added, removed, and changed in+the repository, and the user(s) making the changes. Of course it can be+used in this way in a repository using git-annex too; just run `gource`.++The other way to use gource with git-annex is to visualise the movement of+annexed file contents between repositories. In this view, the "users" are+repositories, and they move around the file contents that are being added+or removed from them with git-annex.++[[!img screenshot.jpg]]++To use gource this way, first go into the directory you want to visualize,+and use `git annex log` to make an input file for `gource`:++ git annex log --gource | tee gorce.log+ sort gource.log | gource --log-format custom -++The `git annex log` can take a while, to speed it up you can use something+like `--after "4 monts ago"` to limit how far back it goes.
+ doc/tips/visualizing_repositories_with_gource/screenshot.jpg view
binary file changed (absent → 78509 bytes)
+ doc/todo/windows_support.mdwn view
@@ -0,0 +1,65 @@+short answer: no++Long answer, quoting from a mail to someone else:++Well, I can tell you that it assumes a POSIX system, both in available+utilities and system calls, So you'd need to use cygwin or something+like that. (Perhaps you already are for git, I think git also assumes a+POSIX system.) So you need a Haskell that can target that. What this+page refers to as "GHC-Cygwin":+<http://www.haskell.org/ghc/docs/6.6/html/building/platforms.html>+I don't know where to get one. Did find this:+<http://copilotco.com/mail-archives/haskell-cafe.2007/msg00824.html>++(There are probably also still some places where it assumes / as a path+separator, although I fixed some. Probably almost all are fixed now.)++FWIW, git-annex works fine on OS X and other fine proprietary unixen. ;P+--[[Joey]]++----++Alternatively, windows versions of these functions could be found,+which are all the ones that need POSIX, I think. A fair amount of this,+the stuff to do with signals and users, could be empty stubs in windows.+The file manipulation, particularly symlinks, would probably be the main+challenge.++<pre>+addSignal+blockSignals+changeWorkingDirectory+createLink+createSymbolicLink+emptySignalSet+executeFile+fileMode+fileSize+forkProcess+getAnyProcessStatus+getEffectiveUserID+getEnvDefault+getFileStatus+getProcessID+getProcessStatus+getSignalMask+getSymbolicLinkStatus+getUserEntryForID+getUserEntryForName+groupWriteMode+homeDirectory+installHandler+intersectFileModes+isRegularFile+isSymbolicLink+modificationTime+otherWriteMode+ownerWriteMode+readSymbolicLink+setEnv+setFileMode+setSignalMask+sigCHLD+sigINT+unionFileModes+</pre>
doc/transferring_data.mdwn view
@@ -10,7 +10,7 @@ It's equally easy to transfer a single file to or from a repository, or to launch a retrievel of a massive pile of files from whatever-repositories they are scattered amoung.+repositories they are scattered amongst. git-annex automatically uses whatever remotes are currently accessible, preferring ones that are less expensive to talk to.
git-annex-shell.hs view
@@ -13,6 +13,7 @@ import CmdLine import Command import Annex.UUID+import qualified Option import qualified Command.ConfigList import qualified Command.InAnnex@@ -36,10 +37,12 @@ cmds :: [Command] cmds = map adddirparam $ cmds_readonly ++ cmds_notreadonly where- adddirparam c = c { cmdparams = "DIRECTORY " ++ cmdparams c }+ adddirparam c = c+ { cmdparamdesc = "DIRECTORY " ++ cmdparamdesc c+ } options :: [OptDescr (Annex ())]-options = commonOptions +++options = Option.common ++ [ Option [] ["uuid"] (ReqArg checkuuid paramUUID) "repository uuid" ] where
git-annex.cabal view
@@ -1,5 +1,5 @@ Name: git-annex-Version: 3.20111231+Version: 3.20120113 Cabal-Version: >= 1.6 License: GPL Maintainer: Joey Hess <joey@kitenet.net>@@ -7,7 +7,7 @@ Stability: Stable Copyright: 2010-2011 Joey Hess License-File: GPL-Extra-Source-Files: ./debian/NEWS ./debian/control ./debian/rules ./debian/manpages ./debian/changelog ./debian/doc-base ./debian/copyright ./debian/compat ./Messages/JSON.hs ./configure.hs ./Annex.hs ./Seek.hs ./Crypto.hs ./Common.hs ./README ./Command/Merge.hs ./Command/AddUrl.hs ./Command/Whereis.hs ./Command/Unlock.hs ./Command/Version.hs ./Command/FromKey.hs ./Command/PreCommit.hs ./Command/Sync.hs ./Command/Map.hs ./Command/Unused.hs ./Command/Uninit.hs ./Command/Migrate.hs ./Command/Init.hs ./Command/ConfigList.hs ./Command/Trust.hs ./Command/Lock.hs ./Command/SendKey.hs ./Command/RecvKey.hs ./Command/Reinject.hs ./Command/Add.hs ./Command/Fix.hs ./Command/Untrust.hs ./Command/Dead.hs ./Command/InitRemote.hs ./Command/Semitrust.hs ./Command/Fsck.hs ./Command/Move.hs ./Command/DropUnused.hs ./Command/Get.hs ./Command/Upgrade.hs ./Command/Describe.hs ./Command/Drop.hs ./Command/DropKey.hs ./Command/InAnnex.hs ./Command/Find.hs ./Command/Unannex.hs ./Command/Status.hs ./Command/Copy.hs ./Init.hs ./Types.hs ./Common/Annex.hs ./Makefile ./git-annex.cabal ./Upgrade/V1.hs ./Upgrade/V2.hs ./Upgrade/V0.hs ./CHANGELOG ./Git/LsFiles.hs ./Git/Version.hs ./Git/UnionMerge.hs ./Git/Url.hs ./Git/HashObject.hs ./Git/Types.hs ./Git/CatFile.hs ./Git/Queue.hs ./Git/Ref.hs ./Git/Filename.hs ./Git/Branch.hs ./Git/Sha.hs ./Git/LsTree.hs ./Git/Config.hs ./Git/CheckAttr.hs ./Git/Command.hs ./Git/Construct.hs ./Git/Index.hs ./doc/upgrades.mdwn ./doc/forum/Recommended_number_of_repositories.mdwn ./doc/forum/wishlist:_define_remotes_that_must_have_all_files.mdwn ./doc/forum/Will_git_annex_work_on_a_FAT32_formatted_key__63__.mdwn ./doc/forum/wishlist:_command_options_changes/comment_2_f6a637c78c989382e3c22d41b7fb4cc2._comment ./doc/forum/wishlist:_command_options_changes/comment_3_bf1114533d2895804e531e76eb6b8095._comment ./doc/forum/wishlist:_command_options_changes/comment_1_bfba72a696789bf21b2435dea15f967a._comment ./doc/forum/pure_git-annex_only_workflow/comment_4_dc8a3f75533906ad3756fcc47f7e96bb._comment ./doc/forum/pure_git-annex_only_workflow/comment_15_cb7c856d8141b2de3cc95874753f1ee5._comment ./doc/forum/pure_git-annex_only_workflow/comment_7_33db51096f568c65b22b4be0b5538c0d._comment ./doc/forum/pure_git-annex_only_workflow/comment_9_ace319652f9c7546883b5152ddc82591._comment ./doc/forum/pure_git-annex_only_workflow/comment_12_ca8ca35d6cd4a9f94568536736c12adc._comment ./doc/forum/pure_git-annex_only_workflow/comment_10_683768c9826b0bf0f267e8734b9eb872._comment ./doc/forum/pure_git-annex_only_workflow/comment_11_6b541ed834ef45606f3b98779a25a148._comment ./doc/forum/pure_git-annex_only_workflow/comment_14_b63568b327215ef8f646a39d760fdfc0._comment ./doc/forum/pure_git-annex_only_workflow/comment_8_6e5b42fdb7801daadc0b3046cbc3d51e._comment ./doc/forum/pure_git-annex_only_workflow/comment_1_a32f7efd18d174845099a4ed59e6feae._comment ./doc/forum/pure_git-annex_only_workflow/comment_13_00c82d320c7b4bb51078beba17e14dc8._comment ./doc/forum/pure_git-annex_only_workflow/comment_3_9b7d89da52f7ebb7801f9ec8545c3aba._comment ./doc/forum/pure_git-annex_only_workflow/comment_6_3660d45c5656f68924acbd23790024ee._comment ./doc/forum/pure_git-annex_only_workflow/comment_2_66dc9b65523a9912411db03c039ba848._comment ./doc/forum/pure_git-annex_only_workflow/comment_5_afe5035a6b35ed2c7e193fb69cc182e2._comment ./doc/forum/wishlist:_git-annex_replicate/comment_3_c13f4f9c3d5884fc6255fd04feadc2b1._comment ./doc/forum/wishlist:_git-annex_replicate/comment_1_9926132ec6052760cdf28518a24e2358._comment ./doc/forum/wishlist:_git-annex_replicate/comment_2_c43932f4194aba8fb2470b18e0817599._comment ./doc/forum/wishlist:_git-annex_replicate/comment_4_63f24abf086d644dced8b01e1a9948c9._comment ./doc/forum/Podcast_syncing_use-case/comment_1_ace6f9d3a950348a3ac0ff592b62e786._comment ./doc/forum/Podcast_syncing_use-case/comment_2_930a6620b4d516e69ed952f9da5371bb._comment ./doc/forum/Behaviour_of_fsck/comment_4_e4911dc6793f98fb81151daacbe49968._comment ./doc/forum/Behaviour_of_fsck/comment_3_97848f9a3db89c0427cfb671ba13300e._comment ./doc/forum/Behaviour_of_fsck/comment_2_ead36a23c3e6efa1c41e4555f93e014e._comment ./doc/forum/Behaviour_of_fsck/comment_1_0e40f158b3f4ccdcaab1408d858b68b8._comment ./doc/forum/incompatible_versions__63__/comment_1_629f28258746d413e452cbd42a1a43f4._comment ./doc/forum/vlc_and_git-annex/comment_1_9c9ab8ce463cf74418aa2f385955f165._comment ./doc/forum/vlc_and_git-annex/comment_2_037f94c1deeac873dbdb36cd4c927e45._comment ./doc/forum/Recommended_number_of_repositories/comment_1_3ef256230756be8a9679b107cdbfd018._comment ./doc/forum/migration_to_git-annex_and_rsync.mdwn ./doc/forum/hashing_objects_directories.mdwn ./doc/forum/git_annex_ls___47___metadata_in_git_annex_whereis.mdwn ./doc/forum/Podcast_syncing_use-case.mdwn ./doc/forum/hashing_objects_directories/comment_5_ef6cfd49d24c180c2d0a062e5bd3a0be._comment ./doc/forum/hashing_objects_directories/comment_1_c55c56076be4f54251b0b7f79f28a607._comment ./doc/forum/hashing_objects_directories/comment_2_504c96959c779176f991f4125ea22009._comment ./doc/forum/hashing_objects_directories/comment_3_9134bde0a13aac0b6a4e5ebabd7f22e8._comment ./doc/forum/hashing_objects_directories/comment_4_0de9170e429cbfea66f5afa8980d45ac._comment ./doc/forum/location_tracking_cleanup.mdwn ./doc/forum/Wishlist:_Ways_of_selecting_files_based_on_meta-information.mdwn ./doc/forum/confusion_with_remotes__44___map.mdwn ./doc/forum/git-annex_on_OSX.mdwn ./doc/forum/A_really_stupid_question.mdwn ./doc/forum/git_tag_missing_for_3.20111011/comment_1_7a53bf273f3078ab3351369ef2b5f2a6._comment ./doc/forum/version_3_upgrade/comment_1_05fc9c9cad26c520bebb98c852c71e35._comment ./doc/forum/example_of_massively_disconnected_operation.mdwn ./doc/forum/git-annex_communication_channels/comment_2_c7aeefa6ef9a2e75d8667b479ade1b7f._comment ./doc/forum/git-annex_communication_channels/comment_5_404b723a681eb93fee015cea8024b6bc._comment ./doc/forum/git-annex_communication_channels/comment_1_198325d2e9337c90f026396de89eec0e._comment ./doc/forum/git-annex_communication_channels/comment_4_1ba6ddf54843c17c7d19a9996f2ab712._comment ./doc/forum/git-annex_communication_channels/comment_6_0d87d0e26461494b1d7f8a701a924729._comment ./doc/forum/git-annex_communication_channels/comment_3_1ff08a3e0e63fa0e560cbc9602245caa._comment ./doc/forum/git-annex_communication_channels/comment_7_2c87c7a0648fe87c2bf6b4391f1cc468._comment ./doc/forum/wishlist:_git-annex_replicate.mdwn ./doc/forum/advantages_of_SHA__42___over_WORM/comment_1_96c354cac4b5ce5cf6664943bc84db1d._comment ./doc/forum/performance_improvement:_git_on_ssd__44___annex_on_spindle_disk.mdwn ./doc/forum/Behaviour_of_fsck.mdwn ./doc/forum/git_annex_add_crash_and_subsequent_recovery.mdwn ./doc/forum/working_without_git-annex_commits.mdwn ./doc/forum/migrate_existing_git_repository_to_git-annex.mdwn ./doc/forum/__34__git_annex_lock__34___very_slow_for_big_repo.mdwn ./doc/forum/wishlist:_traffic_accounting_for_git-annex.mdwn ./doc/forum/git_pull_remote_git-annex.mdwn ./doc/forum/rsync_over_ssh__63__.mdwn ./doc/forum/unannex_alternatives/comment_3_b1687fc8f9e7744327bbeb6f0635d1cd._comment ./doc/forum/unannex_alternatives/comment_1_dcd4cd41280b41512bbdffafaf307993._comment ./doc/forum/unannex_alternatives/comment_2_58a72a9fe0f58c7af0b4d7927a2dd21d._comment ./doc/forum/wishlist:_git_annex_status/comment_4_9aeeb83d202dc8fb33ff364b0705ad94._comment ./doc/forum/wishlist:_git_annex_status/comment_3_d1fd70c67243971c96d59e1ffb7ef6e7._comment ./doc/forum/wishlist:_git_annex_status/comment_2_c2b0ce025805b774dc77ce264a222824._comment ./doc/forum/wishlist:_git_annex_status/comment_1_994bfd12c5d82e08040d6116915c5090._comment ./doc/forum/git_pull_remote_git-annex/comment_7_24c45ee981b18bc78325c768242e635d._comment ./doc/forum/git_pull_remote_git-annex/comment_2_0f7f4a311b0ec1d89613e80847e69b42._comment ./doc/forum/git_pull_remote_git-annex/comment_1_9c245db3518d8b889ecdf5115ad9e053._comment ./doc/forum/git_pull_remote_git-annex/comment_5_4f2a05ef6551806dd0ec65372f183ca4._comment ./doc/forum/git_pull_remote_git-annex/comment_4_646f2077edcabc000a7d9cb75a93cf55._comment ./doc/forum/git_pull_remote_git-annex/comment_8_7e76ee9b6520cbffaf484c9299a63ad3._comment ./doc/forum/git_pull_remote_git-annex/comment_3_1aa89725b5196e40a16edeeb5ccfa371._comment ./doc/forum/git_pull_remote_git-annex/comment_6_3925d1aa56bce9380f712e238d63080f._comment ./doc/forum/wishlist:_command_options_changes.mdwn ./doc/forum/location_tracking_cleanup/comment_3_c15428cec90e969284a5e690fb4b2fde._comment ./doc/forum/location_tracking_cleanup/comment_2_e7395cb6e01f42da72adf71ea3ebcde4._comment ./doc/forum/location_tracking_cleanup/comment_1_7d6319e8c94dfe998af9cfcbf170efb2._comment ./doc/forum/new_microfeatures/comment_2_41ad904c68e89c85e1fc49c9e9106969._comment ./doc/forum/new_microfeatures/comment_1_058bd517c6fffaf3446b1f5d5be63623._comment ./doc/forum/new_microfeatures/comment_3_a1a9347b5bc517f2a89a8b292c3f8517._comment ./doc/forum/new_microfeatures/comment_7_94045b9078b1fff877933b012d1b49e2._comment ./doc/forum/new_microfeatures/comment_5_3c627d275586ff499d928a8f8136babf._comment ./doc/forum/new_microfeatures/comment_4_5a6786dc52382fff5cc42fdb05770196._comment ./doc/forum/new_microfeatures/comment_6_31ea08c008500560c0b96c6601bc6362._comment ./doc/forum/Error_while_adding_a_file___34__createSymbolicLink:_already_exists__34__.mdwn ./doc/forum/advantages_of_SHA__42___over_WORM.mdwn ./doc/forum/wishlist:_git_annex_put_--_same_as_get__44___but_for_defaults.mdwn ./doc/forum/OSX__39__s_default_sshd_behaviour_has_limited_paths_set.mdwn ./doc/forum/bainstorming:_git_annex_push___38___pull.mdwn ./doc/forum/sparse_git_checkouts_with_annex.mdwn ./doc/forum/Need_new_build_instructions_for_Debian_stable.mdwn ./doc/forum/batch_check_on_remote_when_using_copy.mdwn ./doc/forum/tips:_special__95__remotes__47__hook_with_tahoe-lafs.mdwn ./doc/forum/wishlist:alias_system.mdwn ./doc/forum/incompatible_versions__63__.mdwn ./doc/forum/A_really_stupid_question/comment_1_40e02556de0b00b94f245a0196b5a89f._comment ./doc/forum/wishlist:_git_backend_for_git-annex.mdwn ./doc/forum/vlc_and_git-annex.mdwn ./doc/forum/seems_to_build_fine_on_haskell_platform_2011.mdwn ./doc/forum/rsync_over_ssh__63__/comment_1_ee21f32e90303e20339e0a568321bbbe._comment ./doc/forum/rsync_over_ssh__63__/comment_2_aa690da6ecfb2b30fc5080ad76dc77b1._comment ./doc/forum/wishlist:_special_remote_for_sftp_or_rsync.mdwn ./doc/forum/OSX__39__s_haskell-platform_statically_links_things.mdwn ./doc/forum/using_git_annex_to_merge_and_synchronize_2_directories___40__like_unison__41__.mdwn ./doc/forum/git_tag_missing_for_3.20111011.mdwn ./doc/forum/unannex_alternatives.mdwn ./doc/forum/can_git-annex_replace_ddm__63__.mdwn ./doc/forum/sparse_git_checkouts_with_annex/comment_2_e357db3ccc4079f07a291843975535eb._comment ./doc/forum/sparse_git_checkouts_with_annex/comment_1_c7dc199c5740a0e7ba606dfb5e3e579a._comment ./doc/forum/sparse_git_checkouts_with_annex/comment_3_fcfafca994194d57dccf5319c7c9e646._comment ./doc/forum/sparse_git_checkouts_with_annex/comment_4_04dc14880f31eee2b6d767d4d4258c5a._comment ./doc/forum/syncing_non-git_trees_with_git-annex.mdwn ./doc/forum/git-annex_communication_channels.mdwn ./doc/forum/can_git-annex_replace_ddm__63__/comment_3_4c69097fe2ee81359655e59a03a9bb8d._comment ./doc/forum/can_git-annex_replace_ddm__63__/comment_2_008554306dd082d7f543baf283510e92._comment ./doc/forum/can_git-annex_replace_ddm__63__/comment_1_aa05008dfe800474ff76678a400099e1._comment ./doc/forum/version_3_upgrade.mdwn ./doc/forum/relying_on_git_for_numcopies/comment_3_43d8e1513eb9947f8a503f094c03f307._comment ./doc/forum/relying_on_git_for_numcopies/comment_2_be6acbc26008a9cb54e7b8f498f2c2a2._comment ./doc/forum/relying_on_git_for_numcopies/comment_1_8ad3cccd7f66f6423341d71241ba89fc._comment ./doc/forum/confusion_with_remotes__44___map/comment_1_a38ded23b7f288292a843abcb1a56f38._comment ./doc/forum/confusion_with_remotes__44___map/comment_2_cd1c98b1276444e859a22c3dbd6f2a79._comment ./doc/forum/confusion_with_remotes__44___map/comment_6_496b0d9b86869bbac3a1356d53a3dda4._comment ./doc/forum/confusion_with_remotes__44___map/comment_5_27801584325d259fa490f67273f2ff71._comment ./doc/forum/confusion_with_remotes__44___map/comment_4_3b89b6d1518267fcbc050c9de038b9ca._comment ./doc/forum/confusion_with_remotes__44___map/comment_3_18531754089c991b6caefc57a5c17fe9._comment ./doc/forum/confusion_with_remotes__44___map/comment_7_9a456f61f956a3d5e81e723d5a90794c._comment ./doc/forum/--print0_option_as_in___34__find__34__.mdwn ./doc/forum/relying_on_git_for_numcopies.mdwn ./doc/forum/wishlist:_do_round_robin_downloading_of_data.mdwn ./doc/forum/pure_git-annex_only_workflow.mdwn ./doc/forum/wishlist:_git_annex_status.mdwn ./doc/forum/getting_git_annex_to_do_a_force_copy_to_a_remote.mdwn ./doc/forum/Problems_with_large_numbers_of_files.mdwn ./doc/forum/Can_I_store_normal_files_in_the_git-annex_git_repository__63__.mdwn ./doc/forum/Is_an_automagic_upgrade_of_the_object_directory_safe__63__.mdwn ./doc/forum/wishlist:_push_to_cia.vc_from_the_website__39__s_repo__44___not_your_personal_one.mdwn ./doc/forum/new_microfeatures.mdwn ./doc/backends.mdwn ./doc/bugs/__39__annex_add__39___fails_to___39__git_add__39___for_parent_relative_path.mdwn ./doc/bugs/uuid.log_trust.log_and_remote.log_merge_wackiness.mdwn ./doc/bugs/Remote_repo_and_set_operation_with_find.mdwn ./doc/bugs/softlink_mtime.mdwn ./doc/bugs/uninit_should_not_run_when_branch_git-annex_is_checked_out.mdwn ./doc/bugs/ordering.mdwn ./doc/bugs/dropping_files_with_a_URL_backend_fails.mdwn ./doc/bugs/fsck__47__fix_should_check__47__fix_the_permissions_of_.git__47__annex.mdwn ./doc/bugs/dropunused_doesn__39__t_handle_double_spaces_in_filename.mdwn ./doc/bugs/add_script-friendly_output_options.mdwn ./doc/bugs/uninit_does_not_work_in_old_repos.mdwn ./doc/bugs/git_annex_get_choke_when_remote_is_an_ssh_url_with_a_port.mdwn ./doc/bugs/unannex_and_uninit_do_not_work_when_git_index_is_broken.mdwn ./doc/bugs/git_annex_migrate_leaves_old_backend_versions_around.mdwn ./doc/bugs/git_annex_unused_failes_on_empty_repository.mdwn ./doc/bugs/git_annex_add_eats_files_when_filename_is_too_long.mdwn ./doc/bugs/S3_bucket_uses_the_same_key_for_encryption_and_hashing.mdwn ./doc/bugs/problem_with_upgrade_v2_-__62___v3.mdwn ./doc/bugs/git_annex_copy_--fast_does_not_copy_files.mdwn ./doc/bugs/Cabal_dependency_monadIO_missing.mdwn ./doc/bugs/dotdot_problem.mdwn ./doc/bugs/Problems_running_make_on_osx.mdwn ./doc/bugs/free_space_checking/comment_2_8a65f6d3dcf5baa3f7f2dbe1346e2615._comment ./doc/bugs/free_space_checking/comment_3_0fc6ff79a357b1619d13018ccacc7c10._comment ./doc/bugs/free_space_checking/comment_1_a868e805be43c5a7c19c41f1af8e41e6._comment ./doc/bugs/Error_when_moving_annexed_file_to_a_.gitignored_location.mdwn ./doc/bugs/done.mdwn ./doc/bugs/git_annex_copy_-f_REMOTE_._doesn__39__t_work_as_expected.mdwn ./doc/bugs/Displayed_copy_speed_is_wrong/comment_2_8b240de1d5ae9229fa2d77d1cc15a552._comment ./doc/bugs/Displayed_copy_speed_is_wrong/comment_1_74de3091e8bfd7acd6795e61f39f07c6._comment ./doc/bugs/Build_error_on_Mac_OSX_10.6.mdwn ./doc/bugs/bare_git_repos.mdwn ./doc/bugs/fat_support.mdwn ./doc/bugs/problems_with_utf8_names.mdwn ./doc/bugs/error_with_file_names_starting_with_dash.mdwn ./doc/bugs/not_possible_to_have_annex_on_a_separate_filesystem.mdwn ./doc/bugs/unhappy_without_UTF8_locale.mdwn ./doc/bugs/S3_memory_leaks.mdwn ./doc/bugs/git_annex_map_has_problems_with_urls_containing___126__.mdwn ./doc/bugs/interrupting_migration_causes_problems.mdwn ./doc/bugs/upgrade_left_untracked_.git-annex__47____42___directories.mdwn ./doc/bugs/cyclic_drop.mdwn ./doc/bugs/Problems_running_make_on_osx/comment_9_cc283b485b3c95ba7eebc8f0c96969b3._comment ./doc/bugs/Problems_running_make_on_osx/comment_4_c52be386f79f14c8570a8f1397c68581._comment ./doc/bugs/Problems_running_make_on_osx/comment_18_64fab50d95de619eb2e8f08f90237de1._comment ./doc/bugs/Problems_running_make_on_osx/comment_16_5c2dd6002aadaab30841b77a5f5aed34._comment ./doc/bugs/Problems_running_make_on_osx/comment_10_94e4ac430140042a2d0fb5a16d86b4e5._comment ./doc/bugs/Problems_running_make_on_osx/comment_15_6b8867b8e48bf807c955779c9f8f0909._comment ./doc/bugs/Problems_running_make_on_osx/comment_11_56f1143fa191361d63b441741699e17f._comment ./doc/bugs/Problems_running_make_on_osx/comment_20_7db27d1a22666c831848bc6c06d66a84._comment ./doc/bugs/Problems_running_make_on_osx/comment_12_ec5131624d0d2285d3b6880e47033f97._comment ./doc/bugs/Problems_running_make_on_osx/comment_3_68f0f8ae953589ae26d57310b40c878d._comment ./doc/bugs/Problems_running_make_on_osx/comment_14_89a960b6706ed703b390a81a8bc4e311._comment ./doc/bugs/Problems_running_make_on_osx/comment_17_62fccb04b0e4b695312f7a3f32fb96ee._comment ./doc/bugs/Problems_running_make_on_osx/comment_19_4253988ed178054c8b6400beeed68a29._comment ./doc/bugs/Problems_running_make_on_osx/comment_6_0c46f5165ceb5a7b9ea9689c33b3a4f8._comment ./doc/bugs/Problems_running_make_on_osx/comment_1_34120e82331ace01a6a4960862d38f2d._comment ./doc/bugs/Problems_running_make_on_osx/comment_7_237a137cce58a28abcc736cbf2c420b0._comment ./doc/bugs/Problems_running_make_on_osx/comment_5_7f1330a1e541b0f3e2192e596d7f7bee._comment ./doc/bugs/Problems_running_make_on_osx/comment_2_cc53d1681d576186dbc868dd9801d551._comment ./doc/bugs/Problems_running_make_on_osx/comment_13_88ed095a448096bf8a69015a04e64df1._comment ./doc/bugs/Problems_running_make_on_osx/comment_8_efafa203addf8fa79e33e21a87fb5a2b._comment ./doc/bugs/git-annex_directory_hashing_problems_on_osx.mdwn ./doc/bugs/No_easy_way_to_re-inject_a_file_into_an_annex.mdwn ./doc/bugs/git_annex_unlock_is_not_atomic.mdwn ./doc/bugs/free_space_checking.mdwn ./doc/bugs/wishlist:_more_descriptive_commit_messages_in_git-annex_branch.mdwn ./doc/bugs/Displayed_copy_speed_is_wrong.mdwn ./doc/bugs/git_annex_should_use___39__git_add_-f__39___internally.mdwn ./doc/bugs/minor_bug:_errors_are_not_verbose_enough.mdwn ./doc/bugs/No_version_information_from_cli.mdwn ./doc/bugs/Error_while_adding_a_file___34__createSymbolicLink:_already_exists__34__.mdwn ./doc/bugs/old_data_isn__39__t_unused_after_migration.mdwn ./doc/bugs/fails_to_handle_lot_of_files.mdwn ./doc/bugs/tests_fail_when_there_is_no_global_.gitconfig_for_the_user.mdwn ./doc/bugs/git_annex_initremote_walks_.git-annex.mdwn ./doc/bugs/git-annex_incorrectly_parses_bare_IPv6_addresses.mdwn ./doc/bugs/git_annex_version_should_without_being_in_a_repo_.mdwn ./doc/bugs/Can__39__t___34__git-annex_get__34___with_3.20111203.mdwn ./doc/bugs/Prevent_accidental_merges/comment_1_4c46a193915eab8f308a04175cb2e40a._comment ./doc/bugs/conflicting_haskell_packages/comment_1_e552a6cc6d7d1882e14130edfc2d6b3b._comment ./doc/bugs/tmp_file_handling.mdwn ./doc/bugs/annex_add_in_annex.mdwn ./doc/bugs/making_annex-merge_try_a_fast-forward.mdwn ./doc/bugs/bad_behaviour_with_file_names_with_newline_in_them.mdwn ./doc/bugs/on--git-dir_and_--work-tree_options.mdwn ./doc/bugs/Makefile_is_missing_dependancies.mdwn ./doc/bugs/test_suite_shouldn__39__t_fail_silently.mdwn ./doc/bugs/git_annex_upgrade_output_is_inconsistent_and_spammy.mdwn ./doc/bugs/problem_with_upgrade_v2_-__62___v3/comment_4_91439d4dbbf1461e281b276eb0003691._comment ./doc/bugs/problem_with_upgrade_v2_-__62___v3/comment_6_f360f0006bc9115bc5a3e2eb9fe58abd._comment ./doc/bugs/problem_with_upgrade_v2_-__62___v3/comment_3_86d9e7244ae492bcbe62720b8c4fc4a9._comment ./doc/bugs/problem_with_upgrade_v2_-__62___v3/comment_2_cd0123392b16d89db41b45464165c247._comment ./doc/bugs/problem_with_upgrade_v2_-__62___v3/comment_1_5f60006c9bb095167d817f234a14d20b._comment ./doc/bugs/problem_with_upgrade_v2_-__62___v3/comment_5_ca33a9ca0df33f7c1b58353d7ffb943d._comment ./doc/bugs/wishlist:_query_things_like_description__44___trust_level.mdwn ./doc/bugs/git_rename_detection_on_file_move/comment_9_75e0973f6d573df615e01005ebcea87d._comment ./doc/bugs/git_rename_detection_on_file_move/comment_7_7f20d0b2f6ed1c34021a135438037306._comment ./doc/bugs/git_rename_detection_on_file_move/comment_3_57010bcaca42089b451ad8659a1e018e._comment ./doc/bugs/git_rename_detection_on_file_move/comment_4_79d96599f757757f34d7b784e6c0e81c._comment ./doc/bugs/git_rename_detection_on_file_move/comment_5_d61f5693d947b9736b29fca1dbc7ad76._comment ./doc/bugs/git_rename_detection_on_file_move/comment_8_6a00500b24ba53248c78e1ffc8d1a591._comment ./doc/bugs/git_rename_detection_on_file_move/comment_2_7101d07400ad5935f880dc00d89bf90e._comment ./doc/bugs/git_rename_detection_on_file_move/comment_6_f63de6fe2f7189c8c2908cc41c4bc963._comment ./doc/bugs/git_rename_detection_on_file_move/comment_1_0531dcfa833b0321a7009526efe3df33._comment ./doc/bugs/fsck_claims_failed_checksum_when_less_copies_than_required_are_found.mdwn ./doc/bugs/add_range_argument_to___34__git_annex_dropunused__34___.mdwn ./doc/bugs/git_rename_detection_on_file_move.mdwn ./doc/bugs/problem_commit_normal_links.mdwn ./doc/bugs/extraneous_shell_escaping_for_rsync_remotes.mdwn ./doc/bugs/problems_with_utf8_names/comment_1_3c7e3f021c2c94277eecf9c8af6cec5f._comment ./doc/bugs/problems_with_utf8_names/comment_4_93bee35f5fa7744834994bc7a253a6f9._comment ./doc/bugs/problems_with_utf8_names/comment_3_4f936a5d3f9c7df64c8a87e62b7fbfdc._comment ./doc/bugs/problems_with_utf8_names/comment_2_bad4c4c5f54358d1bc0ab2adc713782a._comment ./doc/bugs/git_annex_unused_seems_to_check_for_current_path.mdwn ./doc/bugs/Makefile_is_missing_dependancies/comment_6_24119fc5d5963ce9dd669f7dcf006859._comment ./doc/bugs/Makefile_is_missing_dependancies/comment_3_c38b6f4abc9b9ad413c3b83ca04386c3._comment ./doc/bugs/Makefile_is_missing_dependancies/comment_8_a3555e3286cdc2bfeb9cde0ff727ba74._comment ./doc/bugs/Makefile_is_missing_dependancies/comment_2_416f12dbd0c2b841fac8164645b81df5._comment ./doc/bugs/Makefile_is_missing_dependancies/comment_5_0a1c52e2c96d19b9c3eb7e99b8c2434f._comment ./doc/bugs/Makefile_is_missing_dependancies/comment_7_96fd4725df4b54e670077a18d3ac4943._comment ./doc/bugs/Makefile_is_missing_dependancies/comment_1_5a3da5f79c8563c7a450aa29728abe7c._comment ./doc/bugs/Makefile_is_missing_dependancies/comment_4_cc13873175edf191047282700315beee._comment ./doc/bugs/Trouble_initializing_git_annex_on_NFS.mdwn ./doc/bugs/touch.hsc_has_problems_on_non-linux_based_systems.mdwn ./doc/bugs/build_issue_with_latest_release_0.20110522-1-gde817ba.mdwn ./doc/bugs/weird_local_clone_confuses.mdwn ./doc/bugs/fsck_output.mdwn ./doc/bugs/git-annex_branch_push_race.mdwn ./doc/bugs/wishlist:_allow_users_to_provide_UUID_when_running___96__git_annex_init__96__.mdwn ./doc/bugs/git-annex_has_issues_with_git_when_staging__47__commiting_logs.mdwn ./doc/bugs/git_annex_gets_confused_about_remotes_with_dots_in_their_names.mdwn ./doc/bugs/unannex_vs_unlock_hook_confusion.mdwn ./doc/bugs/Cabal_dependency_monadIO_missing/comment_2_4f4d8e1e00a2a4f7e8a8ab082e16adac._comment ./doc/bugs/Cabal_dependency_monadIO_missing/comment_1_14be660aa57fadec0d81b32a8b52c66f._comment ./doc/bugs/conflicting_haskell_packages.mdwn ./doc/bugs/git_command_line_constructed_by_unannex_command_has_tons_of_redundant_-a_paramters.mdwn ./doc/bugs/backend_version_upgrade_leaves_repo_unusable.mdwn ./doc/bugs/fat_support/comment_3_df3b943bc1081a8f3f7434ae0c8e061e._comment ./doc/bugs/fat_support/comment_4_90a8a15bedd94480945a374f9d706b86._comment ./doc/bugs/fat_support/comment_5_64bbf89de0836673224b83fdefa0407b._comment ./doc/bugs/fat_support/comment_1_04bcc4795d431e8cb32293aab29bbfe2._comment ./doc/bugs/fat_support/comment_2_bb4a97ebadb5c53809fc78431eabd7c8._comment ./doc/bugs/unannex_command_doesn__39__t_all_files.mdwn ./doc/bugs/annex_unannex__47__uninit_should_handle_copies.mdwn ./doc/bugs/git-annex_branch_corruption.mdwn ./doc/bugs/git_annex_fsck_is_a_no-op_in_bare_repos.mdwn ./doc/bugs/Unfortunate_interaction_with_Calibre.mdwn ./doc/bugs/error_propigation.mdwn ./doc/bugs/wishlist:_support_drop__44___find_on_special_remotes.mdwn ./doc/bugs/scp_interrupt_to_background.mdwn ./doc/bugs/copy_fast_confusing_with_broken_locationlog.mdwn ./doc/bugs/uninit_does_not_work_in_old_repos/comment_1_bc0619c6e17139df74639448aa6a0f72._comment ./doc/bugs/git-annex_losing_rsync_remotes_with_encryption_enabled.mdwn ./doc/bugs/configure_script_should_detect_uuidgen_instead_of_just_uuid.mdwn ./doc/bugs/check_for_curl_in_configure.hs.mdwn ./doc/bugs/fails_to_handle_lot_of_files/comment_1_09d8e4e66d8273fab611bd29e82dc7fc._comment ./doc/bugs/fails_to_handle_lot_of_files/comment_2_fd2ec05f4b5a7a6ae6bd9f5dbc3156de._comment ./doc/bugs/Name_scheme_does_not_follow_git__39__s_rules.mdwn ./doc/bugs/concurrent_git-annex_processes_can_lead_to_locking_issues.mdwn ./doc/bugs/Prevent_accidental_merges.mdwn ./doc/bugs/building_on_lenny.mdwn ./doc/bugs/case_sensitivity_on_FAT.mdwn ./doc/bugs/encrypted_S3_stalls.mdwn ./doc/bugs/support_bare_git_repo__44___with_the_annex_directory_exposed_to_http.mdwn ./doc/bugs/WORM:_Handle_long_filenames_correctly.mdwn ./doc/logo_small.png ./doc/tips.mdwn ./doc/use_case/Bob.mdwn ./doc/use_case/Alice.mdwn ./doc/upgrades/SHA_size.mdwn ./doc/news/sharebox_a_FUSE_filesystem_for_git-annex.mdwn ./doc/news/version_3.20111122.mdwn ./doc/news/version_3.20111203.mdwn ./doc/news/version_3.20111107.mdwn ./doc/news/version_backport.mdwn ./doc/news/version_3.20111122~bpo60+2.mdwn ./doc/news/version_3.20111231.mdwn ./doc/news/LWN_article.mdwn ./doc/news/version_3.20111211.mdwn ./doc/news/version_3.20111111.mdwn ./doc/git-union-merge.mdwn ./doc/special_remotes/S3.mdwn ./doc/special_remotes/web.mdwn ./doc/special_remotes/bup.mdwn ./doc/special_remotes/directory.mdwn ./doc/special_remotes/hook.mdwn ./doc/special_remotes/rsync.mdwn ./doc/users/joey.mdwn ./doc/users/fmarier.mdwn ./doc/users/chrysn.mdwn ./doc/users/gebi.mdwn ./doc/templates/walkthrough.tmpl ./doc/templates/bare.tmpl ./doc/index.mdwn ./doc/summary.mdwn ./doc/forum.mdwn ./doc/encryption/comment_1_1afca8d7182075d46db41f6ad3dd5911._comment ./doc/transferring_data.mdwn ./doc/download.mdwn ./doc/future_proofing.mdwn ./doc/todo/auto_remotes/discussion.mdwn ./doc/todo/link_file_to_remote_repo_feature.mdwn ./doc/todo/file_copy_progress_bar.mdwn ./doc/todo/use_cp_reflink.mdwn ./doc/todo/gitrm.mdwn ./doc/todo/exclude_files_on_a_given_remote.mdwn ./doc/todo/git-annex_unused_eats_memory.mdwn ./doc/todo/Please_abort_build_if___34__make_test__34___fails.mdwn ./doc/todo/add_--exclude_option_to_git_annex_find.mdwn ./doc/todo/tahoe_lfs_for_reals/comment_2_80b9e848edfdc7be21baab7d0cef0e3a._comment ./doc/todo/tahoe_lfs_for_reals/comment_1_0a4793ce6a867638f6e510e71dd4bb44._comment ./doc/todo/object_dir_reorg_v2.mdwn ./doc/todo/S3.mdwn ./doc/todo/auto_remotes.mdwn ./doc/todo/wishlist:_support_for_more_ssh_urls_.mdwn ./doc/todo/support-non-utf8-locales.mdwn ./doc/todo/done.mdwn ./doc/todo/fsck.mdwn ./doc/todo/support_S3_multipart_uploads.mdwn ./doc/todo/wishlist:_Provide_a___34__git_annex__34___command_that_will_skip_duplicates.mdwn ./doc/todo/pushpull.mdwn ./doc/todo/smudge.mdwn ./doc/todo/cache_key_info/comment_1_578df1b3b2cbfdc4aa1805378f35dc48._comment ./doc/todo/optimise_git-annex_merge.mdwn ./doc/todo/object_dir_reorg_v2/comment_3_79bdf9c51dec9f52372ce95b53233bb2._comment ./doc/todo/object_dir_reorg_v2/comment_7_42501404c82ca07147e2cce0cff59474._comment ./doc/todo/object_dir_reorg_v2/comment_5_821c382987f105da72a50e0a5ce61fdc._comment ./doc/todo/object_dir_reorg_v2/comment_1_ba03333dc76ff49eccaba375e68cb525._comment ./doc/todo/object_dir_reorg_v2/comment_2_81276ac309959dc741bc90101c213ab7._comment ./doc/todo/object_dir_reorg_v2/comment_6_8834c3a3f1258c4349d23aff8549bf35._comment ./doc/todo/object_dir_reorg_v2/comment_4_93aada9b1680fed56cc6f0f7c3aca5e5._comment ./doc/todo/union_mounting.mdwn ./doc/todo/wishlist:_swift_backend.mdwn ./doc/todo/Please_add_support_for_monad-control_0.3.x.mdwn ./doc/todo/wishlist:_swift_backend/comment_1_e6efbb35f61ee521b473a92674036788._comment ./doc/todo/wishlist:_swift_backend/comment_2_5d8c83b0485112e98367b7abaab3f4e3._comment ./doc/todo/git_annex_init_:_include_repo_description_and__47__or_UUID_in_commit_message.mdwn ./doc/todo/gitolite_and_gitosis_support.mdwn ./doc/todo/wishlist:___34__git_annex_add__34___multiple_processes.mdwn ./doc/todo/hidden_files.mdwn ./doc/todo/smudge/comment_1_4ea616bcdbc9e9a6fae9f2e2795c31c9._comment ./doc/todo/smudge/comment_2_e04b32caa0d2b4c577cdaf382a3ff7f6._comment ./doc/todo/network_remotes.mdwn ./doc/todo/add_a_git_backend.mdwn ./doc/todo/parallel_possibilities/comment_1_d8e34fc2bc4e5cf761574608f970d496._comment ./doc/todo/parallel_possibilities/comment_2_adb76f06a7997abe4559d3169a3181c3._comment ./doc/todo/checkout.mdwn ./doc/todo/immutable_annexed_files.mdwn ./doc/todo/wishlist:_Prevent_repeated_password_prompts_for_one_command.mdwn ./doc/todo/git-annex-shell.mdwn ./doc/todo/speed_up_fsck.mdwn ./doc/todo/tahoe_lfs_for_reals.mdwn ./doc/todo/avoid_unnecessary_union_merges.mdwn ./doc/todo/support_fsck_in_bare_repos.mdwn ./doc/todo/add_-all_option.mdwn ./doc/todo/using_url_backend.mdwn ./doc/todo/branching.mdwn ./doc/todo/rsync.mdwn ./doc/todo/backendSHA1.mdwn ./doc/todo/cache_key_info.mdwn ./doc/todo/parallel_possibilities.mdwn ./doc/todo/symlink_farming_commit_hook.mdwn ./doc/feeds.mdwn ./doc/sync.mdwn ./doc/copies.mdwn ./doc/repomap.png ./doc/special_remotes.mdwn ./doc/todo.mdwn ./doc/walkthrough/using_ssh_remotes.mdwn ./doc/walkthrough/automatically_managing_content.mdwn ./doc/walkthrough/removing_files/comment_1_cb65e7c510b75be1c51f655b058667c6._comment ./doc/walkthrough/removing_files/comment_2_64709ea4558915edd5c8ca4486965b07._comment ./doc/walkthrough/moving_file_content_between_repositories.mdwn ./doc/walkthrough/modifying_annexed_files.mdwn ./doc/walkthrough/more.mdwn ./doc/walkthrough/removing_files.mdwn ./doc/walkthrough/creating_a_repository.mdwn ./doc/walkthrough/adding_a_remote.mdwn ./doc/walkthrough/adding_a_remote/comment_1_0a59355bd33a796aec97173607e6adc9._comment ./doc/walkthrough/adding_a_remote/comment_2_f8cd79ef1593a8181a7f1086a87713e8._comment ./doc/walkthrough/adding_a_remote/comment_3_60691af4400521b5a8c8d75efe3b44cb._comment ./doc/walkthrough/adding_a_remote/comment_4_6f7cf5c330272c96b3abeb6612075c9d._comment ./doc/walkthrough/removing_files:_When_things_go_wrong.mdwn ./doc/walkthrough/renaming_files.mdwn ./doc/walkthrough/using_bup.mdwn ./doc/walkthrough/fsck:_when_things_go_wrong.mdwn ./doc/walkthrough/syncing.mdwn ./doc/walkthrough/adding_files.mdwn ./doc/walkthrough/unused_data.mdwn ./doc/walkthrough/fsck:_verifying_your_data.mdwn ./doc/walkthrough/getting_file_content.mdwn ./doc/walkthrough/backups.mdwn ./doc/walkthrough/transferring_files:_When_things_go_wrong.mdwn ./doc/GPL ./doc/logo.png ./doc/location_tracking.mdwn ./doc/design.mdwn ./doc/news.mdwn ./doc/tips/untrusted_repositories.mdwn ./doc/tips/automatically_getting_files_on_checkout.mdwn ./doc/tips/what_to_do_when_a_repository_is_corrupted.mdwn ./doc/tips/Internet_Archive_via_S3.mdwn ./doc/tips/what_to_do_when_you_lose_a_repository.mdwn ./doc/tips/using_Amazon_S3.mdwn ./doc/tips/using_the_web_as_a_special_remote.mdwn ./doc/tips/powerful_file_matching.mdwn ./doc/tips/using_gitolite_with_git-annex.mdwn ./doc/tips/recover_data_from_lost+found.mdwn ./doc/tips/centralized_git_repository_tutorial.mdwn ./doc/tips/finding_duplicate_files/comment_1_ddb477ca242ffeb21e0df394d8fdf5d2._comment ./doc/tips/using_git_annex_with_no_fixed_hostname_and_optimising_ssh.mdwn ./doc/tips/using_gitolite_with_git-annex/comment_4_eb81f824aadc97f098379c5f7e4fba4c._comment ./doc/tips/using_gitolite_with_git-annex/comment_6_3e203e010a4df5bf03899f867718adc5._comment ./doc/tips/using_gitolite_with_git-annex/comment_1_9a2a2a8eac9af97e0c984ad105763a73._comment ./doc/tips/using_gitolite_with_git-annex/comment_8_8249772c142117f88e37975d058aa936._comment ./doc/tips/using_gitolite_with_git-annex/comment_5_f688309532d2993630e9e72e87fb9c46._comment ./doc/tips/using_gitolite_with_git-annex/comment_7_f8fd08b6ab47378ad88c87348057220d._comment ./doc/tips/using_gitolite_with_git-annex/comment_3_807035f38509ccb9f93f1929ecd37417._comment ./doc/tips/using_gitolite_with_git-annex/comment_2_d8efea4ab9576555fadbb47666ecefa9._comment ./doc/tips/finding_duplicate_files.mdwn ./doc/tips/centralised_repository:_starting_from_nothing.mdwn ./doc/tips/using_the_SHA1_backend.mdwn ./doc/tips/migrating_data_to_a_new_backend.mdwn ./doc/encryption.mdwn ./doc/not.mdwn ./doc/download/comment_7_a5eebd214b135f34b18274a682211943._comment ./doc/download/comment_3_cf6044ebe99f71158034e21197228abd._comment ./doc/download/comment_5_c6b1bc40226fc2c8ba3e558150856992._comment ./doc/download/comment_6_3a52993d3553deb9a413debec9a5f92d._comment ./doc/download/comment_2_f85f72b33aedc3425f0c0c47867d02f3._comment ./doc/download/comment_8_59a976de6c7d333709b92f7cd5830850._comment ./doc/download/comment_4_10fc013865c7542c2ed9d6c0963bb391._comment ./doc/download/comment_1_fbd8b6d39e9d3c71791551358c863966._comment ./doc/contact.mdwn ./doc/trust.mdwn ./doc/bare_repositories.mdwn ./doc/distributed_version_control.mdwn ./doc/install.mdwn ./doc/git-annex-shell.mdwn ./doc/bugs.mdwn ./doc/meta.mdwn ./doc/design/encryption/comment_2_a610b3d056a059899178859a3a821ea5._comment ./doc/design/encryption/comment_3_cca186a9536cd3f6e86994631b14231c._comment ./doc/design/encryption/comment_1_4715ffafb3c4a9915bc33f2b26aaa9c1._comment ./doc/design/encryption/comment_4_8f3ba3e504b058791fc6e6f9c38154cf._comment ./doc/design/encryption.mdwn ./doc/comments.mdwn ./doc/git-annex.mdwn ./doc/internals.mdwn ./doc/users.mdwn ./doc/install/Ubuntu.mdwn ./doc/install/Debian.mdwn ./doc/install/openSUSE.mdwn ./doc/install/OSX.mdwn ./doc/install/FreeBSD.mdwn ./doc/install/OSX/comment_1_0a1760bf0db1f1ba89bdb4c62032f631._comment ./doc/install/comment_3_cff163ea3e7cad926f4ed9e78b896598._comment ./doc/install/Debian/comment_2_648e3467e260cdf233acdb0b53313ce0._comment ./doc/install/Debian/comment_1_029486088d098c2d4f1099f2f0e701a9._comment ./doc/install/Fedora.mdwn ./doc/install/comment_4_82a17eee4a076c6c79fddeda347e0c9a._comment ./doc/walkthrough.mdwn ./CmdLine.hs ./Messages.hs ./Setup.hs ./GPL ./mdwn2man ./Remote.hs ./git-annex.hs ./Locations.hs ./Backend/WORM.hs ./Backend/URL.hs ./Backend/SHA.hs ./Options.hs ./git-annex-shell.hs ./test.hs ./INSTALL ./Remote/Web.hs ./Remote/S3stub.hs ./Remote/Helper/Encryptable.hs ./Remote/Helper/Special.hs ./Remote/Directory.hs ./Remote/S3real.hs ./Remote/Bup.hs ./Remote/Hook.hs ./Remote/Rsync.hs ./Remote/Git.hs ./Build/TestConfig.hs ./Upgrade.hs ./Annex/Version.hs ./Annex/Exception.hs ./Annex/Journal.hs ./Annex/CatFile.hs ./Annex/Ssh.hs ./Annex/Queue.hs ./Annex/Branch.hs ./Annex/UUID.hs ./Annex/BranchState.hs ./Annex/Content.hs ./git-union-merge.hs ./Utility/Path.hs ./Utility/Matcher.hs ./Utility/TempFile.hs ./Utility/Url.hs ./Utility/DataUnits.hs ./Utility/StatFS.hsc ./Utility/Conditional.hs ./Utility/Monad.hs ./Utility/RsyncFile.hs ./Utility/CopyFile.hs ./Utility/Misc.hs ./Utility/SafeCommand.hs ./Utility/Gpg.hs ./Utility/Directory.hs ./Utility/FileMode.hs ./Utility/PartialPrelude.hs ./Utility/JSONStream.hs ./Utility/Dot.hs ./Utility/Touch.hsc ./Utility/Base64.hs ./Utility/Format.hs ./Types/Crypto.hs ./Types/UUID.hs ./Types/TrustLevel.hs ./Types/Remote.hs ./Types/BranchState.hs ./Types/Command.hs ./Types/Backend.hs ./Types/Key.hs ./Config.hs ./Checks.hs ./Command.hs ./.gitignore ./Backend.hs ./Logs/Web.hs ./Logs/UUIDBased.hs ./Logs/Trust.hs ./Logs/Location.hs ./Logs/UUID.hs ./Logs/Remote.hs ./Logs/Presence.hs ./.gitattributes ./Git.hs ./Limit.hs ./GitAnnex.hs+Extra-Source-Files: ./debian/NEWS ./debian/control ./debian/rules ./debian/manpages ./debian/changelog ./debian/doc-base ./debian/copyright ./debian/compat ./Messages/JSON.hs ./Option.hs ./configure.hs ./Annex.hs ./Seek.hs ./Crypto.hs ./Common.hs ./README ./Command/Merge.hs ./Command/AddUrl.hs ./Command/Whereis.hs ./Command/Unlock.hs ./Command/Version.hs ./Command/FromKey.hs ./Command/PreCommit.hs ./Command/Sync.hs ./Command/Map.hs ./Command/Unused.hs ./Command/Uninit.hs ./Command/Migrate.hs ./Command/Init.hs ./Command/ConfigList.hs ./Command/Trust.hs ./Command/Lock.hs ./Command/SendKey.hs ./Command/RecvKey.hs ./Command/Reinject.hs ./Command/Add.hs ./Command/Fix.hs ./Command/Untrust.hs ./Command/Dead.hs ./Command/InitRemote.hs ./Command/Semitrust.hs ./Command/Fsck.hs ./Command/Move.hs ./Command/DropUnused.hs ./Command/Get.hs ./Command/Upgrade.hs ./Command/Describe.hs ./Command/Drop.hs ./Command/DropKey.hs ./Command/InAnnex.hs ./Command/Find.hs ./Command/Log.hs ./Command/Unannex.hs ./Command/Status.hs ./Command/Copy.hs ./Init.hs ./Types.hs ./Common/Annex.hs ./Makefile ./git-annex.cabal ./Upgrade/V1.hs ./Upgrade/V2.hs ./Upgrade/V0.hs ./CHANGELOG ./Git/LsFiles.hs ./Git/Version.hs ./Git/UnionMerge.hs ./Git/Url.hs ./Git/HashObject.hs ./Git/Types.hs ./Git/CatFile.hs ./Git/Queue.hs ./Git/Ref.hs ./Git/Filename.hs ./Git/Branch.hs ./Git/Sha.hs ./Git/LsTree.hs ./Git/Config.hs ./Git/CheckAttr.hs ./Git/Command.hs ./Git/Construct.hs ./Git/Index.hs ./doc/upgrades.mdwn ./doc/forum/Recommended_number_of_repositories.mdwn ./doc/forum/unlock__47__lock_always_gets_me.mdwn ./doc/forum/wishlist:_define_remotes_that_must_have_all_files.mdwn ./doc/forum/Will_git_annex_work_on_a_FAT32_formatted_key__63__.mdwn ./doc/forum/wishlist:_command_options_changes/comment_2_f6a637c78c989382e3c22d41b7fb4cc2._comment ./doc/forum/wishlist:_command_options_changes/comment_3_bf1114533d2895804e531e76eb6b8095._comment ./doc/forum/wishlist:_command_options_changes/comment_1_bfba72a696789bf21b2435dea15f967a._comment ./doc/forum/pure_git-annex_only_workflow/comment_4_dc8a3f75533906ad3756fcc47f7e96bb._comment ./doc/forum/pure_git-annex_only_workflow/comment_15_cb7c856d8141b2de3cc95874753f1ee5._comment ./doc/forum/pure_git-annex_only_workflow/comment_7_33db51096f568c65b22b4be0b5538c0d._comment ./doc/forum/pure_git-annex_only_workflow/comment_9_ace319652f9c7546883b5152ddc82591._comment ./doc/forum/pure_git-annex_only_workflow/comment_12_ca8ca35d6cd4a9f94568536736c12adc._comment ./doc/forum/pure_git-annex_only_workflow/comment_10_683768c9826b0bf0f267e8734b9eb872._comment ./doc/forum/pure_git-annex_only_workflow/comment_11_6b541ed834ef45606f3b98779a25a148._comment ./doc/forum/pure_git-annex_only_workflow/comment_14_b63568b327215ef8f646a39d760fdfc0._comment ./doc/forum/pure_git-annex_only_workflow/comment_8_6e5b42fdb7801daadc0b3046cbc3d51e._comment ./doc/forum/pure_git-annex_only_workflow/comment_1_a32f7efd18d174845099a4ed59e6feae._comment ./doc/forum/pure_git-annex_only_workflow/comment_13_00c82d320c7b4bb51078beba17e14dc8._comment ./doc/forum/pure_git-annex_only_workflow/comment_3_9b7d89da52f7ebb7801f9ec8545c3aba._comment ./doc/forum/pure_git-annex_only_workflow/comment_6_3660d45c5656f68924acbd23790024ee._comment ./doc/forum/pure_git-annex_only_workflow/comment_2_66dc9b65523a9912411db03c039ba848._comment ./doc/forum/pure_git-annex_only_workflow/comment_5_afe5035a6b35ed2c7e193fb69cc182e2._comment ./doc/forum/wishlist:_git-annex_replicate/comment_3_c13f4f9c3d5884fc6255fd04feadc2b1._comment ./doc/forum/wishlist:_git-annex_replicate/comment_1_9926132ec6052760cdf28518a24e2358._comment ./doc/forum/wishlist:_git-annex_replicate/comment_2_c43932f4194aba8fb2470b18e0817599._comment ./doc/forum/wishlist:_git-annex_replicate/comment_4_63f24abf086d644dced8b01e1a9948c9._comment ./doc/forum/Podcast_syncing_use-case/comment_1_ace6f9d3a950348a3ac0ff592b62e786._comment ./doc/forum/Podcast_syncing_use-case/comment_2_930a6620b4d516e69ed952f9da5371bb._comment ./doc/forum/Behaviour_of_fsck/comment_4_e4911dc6793f98fb81151daacbe49968._comment ./doc/forum/Behaviour_of_fsck/comment_3_97848f9a3db89c0427cfb671ba13300e._comment ./doc/forum/Behaviour_of_fsck/comment_2_ead36a23c3e6efa1c41e4555f93e014e._comment ./doc/forum/Behaviour_of_fsck/comment_1_0e40f158b3f4ccdcaab1408d858b68b8._comment ./doc/forum/incompatible_versions__63__/comment_1_629f28258746d413e452cbd42a1a43f4._comment ./doc/forum/vlc_and_git-annex/comment_1_9c9ab8ce463cf74418aa2f385955f165._comment ./doc/forum/vlc_and_git-annex/comment_2_037f94c1deeac873dbdb36cd4c927e45._comment ./doc/forum/Recommended_number_of_repositories/comment_1_3ef256230756be8a9679b107cdbfd018._comment ./doc/forum/migration_to_git-annex_and_rsync.mdwn ./doc/forum/hashing_objects_directories.mdwn ./doc/forum/git_annex_ls___47___metadata_in_git_annex_whereis.mdwn ./doc/forum/unlock__47__lock_always_gets_me/comment_1_dee73a7ea3e1a5154601adb59782831f._comment ./doc/forum/git-subtree_support__63__.mdwn ./doc/forum/Podcast_syncing_use-case.mdwn ./doc/forum/hashing_objects_directories/comment_5_ef6cfd49d24c180c2d0a062e5bd3a0be._comment ./doc/forum/hashing_objects_directories/comment_1_c55c56076be4f54251b0b7f79f28a607._comment ./doc/forum/hashing_objects_directories/comment_2_504c96959c779176f991f4125ea22009._comment ./doc/forum/hashing_objects_directories/comment_3_9134bde0a13aac0b6a4e5ebabd7f22e8._comment ./doc/forum/hashing_objects_directories/comment_4_0de9170e429cbfea66f5afa8980d45ac._comment ./doc/forum/location_tracking_cleanup.mdwn ./doc/forum/Wishlist:_Ways_of_selecting_files_based_on_meta-information.mdwn ./doc/forum/confusion_with_remotes__44___map.mdwn ./doc/forum/git-annex_on_OSX.mdwn ./doc/forum/A_really_stupid_question.mdwn ./doc/forum/git_tag_missing_for_3.20111011/comment_1_7a53bf273f3078ab3351369ef2b5f2a6._comment ./doc/forum/version_3_upgrade/comment_1_05fc9c9cad26c520bebb98c852c71e35._comment ./doc/forum/example_of_massively_disconnected_operation.mdwn ./doc/forum/git-annex_communication_channels/comment_2_c7aeefa6ef9a2e75d8667b479ade1b7f._comment ./doc/forum/git-annex_communication_channels/comment_5_404b723a681eb93fee015cea8024b6bc._comment ./doc/forum/git-annex_communication_channels/comment_1_198325d2e9337c90f026396de89eec0e._comment ./doc/forum/git-annex_communication_channels/comment_4_1ba6ddf54843c17c7d19a9996f2ab712._comment ./doc/forum/git-annex_communication_channels/comment_6_0d87d0e26461494b1d7f8a701a924729._comment ./doc/forum/git-annex_communication_channels/comment_3_1ff08a3e0e63fa0e560cbc9602245caa._comment ./doc/forum/git-annex_communication_channels/comment_7_2c87c7a0648fe87c2bf6b4391f1cc468._comment ./doc/forum/wishlist:_git-annex_replicate.mdwn ./doc/forum/advantages_of_SHA__42___over_WORM/comment_1_96c354cac4b5ce5cf6664943bc84db1d._comment ./doc/forum/performance_improvement:_git_on_ssd__44___annex_on_spindle_disk.mdwn ./doc/forum/Behaviour_of_fsck.mdwn ./doc/forum/git_annex_add_crash_and_subsequent_recovery.mdwn ./doc/forum/Handling_web_special_remote_when_content_changes__63__.mdwn ./doc/forum/working_without_git-annex_commits.mdwn ./doc/forum/migrate_existing_git_repository_to_git-annex.mdwn ./doc/forum/__34__git_annex_lock__34___very_slow_for_big_repo.mdwn ./doc/forum/wishlist:_traffic_accounting_for_git-annex.mdwn ./doc/forum/git_pull_remote_git-annex.mdwn ./doc/forum/rsync_over_ssh__63__.mdwn ./doc/forum/unannex_alternatives/comment_3_b1687fc8f9e7744327bbeb6f0635d1cd._comment ./doc/forum/unannex_alternatives/comment_1_dcd4cd41280b41512bbdffafaf307993._comment ./doc/forum/unannex_alternatives/comment_2_58a72a9fe0f58c7af0b4d7927a2dd21d._comment ./doc/forum/wishlist:_git_annex_status/comment_4_9aeeb83d202dc8fb33ff364b0705ad94._comment ./doc/forum/wishlist:_git_annex_status/comment_3_d1fd70c67243971c96d59e1ffb7ef6e7._comment ./doc/forum/wishlist:_git_annex_status/comment_2_c2b0ce025805b774dc77ce264a222824._comment ./doc/forum/wishlist:_git_annex_status/comment_1_994bfd12c5d82e08040d6116915c5090._comment ./doc/forum/git_pull_remote_git-annex/comment_7_24c45ee981b18bc78325c768242e635d._comment ./doc/forum/git_pull_remote_git-annex/comment_2_0f7f4a311b0ec1d89613e80847e69b42._comment ./doc/forum/git_pull_remote_git-annex/comment_1_9c245db3518d8b889ecdf5115ad9e053._comment ./doc/forum/git_pull_remote_git-annex/comment_5_4f2a05ef6551806dd0ec65372f183ca4._comment ./doc/forum/git_pull_remote_git-annex/comment_4_646f2077edcabc000a7d9cb75a93cf55._comment ./doc/forum/git_pull_remote_git-annex/comment_8_7e76ee9b6520cbffaf484c9299a63ad3._comment ./doc/forum/git_pull_remote_git-annex/comment_3_1aa89725b5196e40a16edeeb5ccfa371._comment ./doc/forum/git_pull_remote_git-annex/comment_6_3925d1aa56bce9380f712e238d63080f._comment ./doc/forum/wishlist:_command_options_changes.mdwn ./doc/forum/location_tracking_cleanup/comment_3_c15428cec90e969284a5e690fb4b2fde._comment ./doc/forum/location_tracking_cleanup/comment_2_e7395cb6e01f42da72adf71ea3ebcde4._comment ./doc/forum/location_tracking_cleanup/comment_1_7d6319e8c94dfe998af9cfcbf170efb2._comment ./doc/forum/new_microfeatures/comment_2_41ad904c68e89c85e1fc49c9e9106969._comment ./doc/forum/new_microfeatures/comment_1_058bd517c6fffaf3446b1f5d5be63623._comment ./doc/forum/new_microfeatures/comment_3_a1a9347b5bc517f2a89a8b292c3f8517._comment ./doc/forum/new_microfeatures/comment_7_94045b9078b1fff877933b012d1b49e2._comment ./doc/forum/new_microfeatures/comment_5_3c627d275586ff499d928a8f8136babf._comment ./doc/forum/new_microfeatures/comment_4_5a6786dc52382fff5cc42fdb05770196._comment ./doc/forum/new_microfeatures/comment_6_31ea08c008500560c0b96c6601bc6362._comment ./doc/forum/Error_while_adding_a_file___34__createSymbolicLink:_already_exists__34__.mdwn ./doc/forum/advantages_of_SHA__42___over_WORM.mdwn ./doc/forum/wishlist:_git_annex_put_--_same_as_get__44___but_for_defaults.mdwn ./doc/forum/OSX__39__s_default_sshd_behaviour_has_limited_paths_set.mdwn ./doc/forum/Auto_archiving.mdwn ./doc/forum/bainstorming:_git_annex_push___38___pull.mdwn ./doc/forum/sparse_git_checkouts_with_annex.mdwn ./doc/forum/Need_new_build_instructions_for_Debian_stable.mdwn ./doc/forum/batch_check_on_remote_when_using_copy.mdwn ./doc/forum/tips:_special__95__remotes__47__hook_with_tahoe-lafs.mdwn ./doc/forum/wishlist:alias_system.mdwn ./doc/forum/incompatible_versions__63__.mdwn ./doc/forum/A_really_stupid_question/comment_1_40e02556de0b00b94f245a0196b5a89f._comment ./doc/forum/wishlist:_git_backend_for_git-annex.mdwn ./doc/forum/vlc_and_git-annex.mdwn ./doc/forum/seems_to_build_fine_on_haskell_platform_2011.mdwn ./doc/forum/rsync_over_ssh__63__/comment_1_ee21f32e90303e20339e0a568321bbbe._comment ./doc/forum/rsync_over_ssh__63__/comment_2_aa690da6ecfb2b30fc5080ad76dc77b1._comment ./doc/forum/wishlist:_special_remote_for_sftp_or_rsync.mdwn ./doc/forum/OSX__39__s_haskell-platform_statically_links_things.mdwn ./doc/forum/using_git_annex_to_merge_and_synchronize_2_directories___40__like_unison__41__.mdwn ./doc/forum/git_tag_missing_for_3.20111011.mdwn ./doc/forum/unannex_alternatives.mdwn ./doc/forum/can_git-annex_replace_ddm__63__.mdwn ./doc/forum/sparse_git_checkouts_with_annex/comment_2_e357db3ccc4079f07a291843975535eb._comment ./doc/forum/sparse_git_checkouts_with_annex/comment_1_c7dc199c5740a0e7ba606dfb5e3e579a._comment ./doc/forum/sparse_git_checkouts_with_annex/comment_3_fcfafca994194d57dccf5319c7c9e646._comment ./doc/forum/sparse_git_checkouts_with_annex/comment_4_04dc14880f31eee2b6d767d4d4258c5a._comment ./doc/forum/syncing_non-git_trees_with_git-annex.mdwn ./doc/forum/git-annex_communication_channels.mdwn ./doc/forum/can_git-annex_replace_ddm__63__/comment_3_4c69097fe2ee81359655e59a03a9bb8d._comment ./doc/forum/can_git-annex_replace_ddm__63__/comment_2_008554306dd082d7f543baf283510e92._comment ./doc/forum/can_git-annex_replace_ddm__63__/comment_1_aa05008dfe800474ff76678a400099e1._comment ./doc/forum/version_3_upgrade.mdwn ./doc/forum/relying_on_git_for_numcopies/comment_3_43d8e1513eb9947f8a503f094c03f307._comment ./doc/forum/relying_on_git_for_numcopies/comment_2_be6acbc26008a9cb54e7b8f498f2c2a2._comment ./doc/forum/relying_on_git_for_numcopies/comment_1_8ad3cccd7f66f6423341d71241ba89fc._comment ./doc/forum/confusion_with_remotes__44___map/comment_1_a38ded23b7f288292a843abcb1a56f38._comment ./doc/forum/confusion_with_remotes__44___map/comment_2_cd1c98b1276444e859a22c3dbd6f2a79._comment ./doc/forum/confusion_with_remotes__44___map/comment_6_496b0d9b86869bbac3a1356d53a3dda4._comment ./doc/forum/confusion_with_remotes__44___map/comment_5_27801584325d259fa490f67273f2ff71._comment ./doc/forum/confusion_with_remotes__44___map/comment_4_3b89b6d1518267fcbc050c9de038b9ca._comment ./doc/forum/confusion_with_remotes__44___map/comment_3_18531754089c991b6caefc57a5c17fe9._comment ./doc/forum/confusion_with_remotes__44___map/comment_7_9a456f61f956a3d5e81e723d5a90794c._comment ./doc/forum/--print0_option_as_in___34__find__34__.mdwn ./doc/forum/relying_on_git_for_numcopies.mdwn ./doc/forum/wishlist:_do_round_robin_downloading_of_data.mdwn ./doc/forum/pure_git-annex_only_workflow.mdwn ./doc/forum/wishlist:_git_annex_status.mdwn ./doc/forum/getting_git_annex_to_do_a_force_copy_to_a_remote.mdwn ./doc/forum/Problems_with_large_numbers_of_files.mdwn ./doc/forum/Can_I_store_normal_files_in_the_git-annex_git_repository__63__.mdwn ./doc/forum/Is_an_automagic_upgrade_of_the_object_directory_safe__63__.mdwn ./doc/forum/wishlist:_push_to_cia.vc_from_the_website__39__s_repo__44___not_your_personal_one.mdwn ./doc/forum/new_microfeatures.mdwn ./doc/forum/git-subtree_support__63__/comment_2_73d2a015b1ac79ec99e071a8b1e29034._comment ./doc/forum/git-subtree_support__63__/comment_1_4f333cb71ed1ff259bbfd86704806aa6._comment ./doc/forum/git-subtree_support__63__/comment_4_75b0e072e668aa46ff0a8d62a6620306._comment ./doc/forum/git-subtree_support__63__/comment_3_c533400e22c306c033fcd56e64761b0b._comment ./doc/forum/git-subtree_support__63__/comment_6_85df530f7b6d76b74ac8017c6034f95e._comment ./doc/forum/git-subtree_support__63__/comment_5_f5ec9649d9f1dc122e715de5533bc674._comment ./doc/backends.mdwn ./doc/bugs/__39__annex_add__39___fails_to___39__git_add__39___for_parent_relative_path.mdwn ./doc/bugs/uuid.log_trust.log_and_remote.log_merge_wackiness.mdwn ./doc/bugs/Remote_repo_and_set_operation_with_find.mdwn ./doc/bugs/softlink_mtime.mdwn ./doc/bugs/uninit_should_not_run_when_branch_git-annex_is_checked_out.mdwn ./doc/bugs/ordering.mdwn ./doc/bugs/dropping_files_with_a_URL_backend_fails.mdwn ./doc/bugs/fsck__47__fix_should_check__47__fix_the_permissions_of_.git__47__annex.mdwn ./doc/bugs/dropunused_doesn__39__t_handle_double_spaces_in_filename.mdwn ./doc/bugs/add_script-friendly_output_options.mdwn ./doc/bugs/uninit_does_not_work_in_old_repos.mdwn ./doc/bugs/conq:_invalid_command_syntax.mdwn ./doc/bugs/git_annex_get_choke_when_remote_is_an_ssh_url_with_a_port.mdwn ./doc/bugs/unannex_and_uninit_do_not_work_when_git_index_is_broken.mdwn ./doc/bugs/git_annex_migrate_leaves_old_backend_versions_around.mdwn ./doc/bugs/git_annex_unused_failes_on_empty_repository.mdwn ./doc/bugs/git_annex_add_eats_files_when_filename_is_too_long.mdwn ./doc/bugs/S3_bucket_uses_the_same_key_for_encryption_and_hashing.mdwn ./doc/bugs/problem_with_upgrade_v2_-__62___v3.mdwn ./doc/bugs/git_annex_copy_--fast_does_not_copy_files.mdwn ./doc/bugs/Cabal_dependency_monadIO_missing.mdwn ./doc/bugs/dotdot_problem.mdwn ./doc/bugs/Problems_running_make_on_osx.mdwn ./doc/bugs/free_space_checking/comment_2_8a65f6d3dcf5baa3f7f2dbe1346e2615._comment ./doc/bugs/free_space_checking/comment_3_0fc6ff79a357b1619d13018ccacc7c10._comment ./doc/bugs/free_space_checking/comment_1_a868e805be43c5a7c19c41f1af8e41e6._comment ./doc/bugs/Error_when_moving_annexed_file_to_a_.gitignored_location.mdwn ./doc/bugs/done.mdwn ./doc/bugs/git_annex_copy_-f_REMOTE_._doesn__39__t_work_as_expected.mdwn ./doc/bugs/Displayed_copy_speed_is_wrong/comment_2_8b240de1d5ae9229fa2d77d1cc15a552._comment ./doc/bugs/Displayed_copy_speed_is_wrong/comment_1_74de3091e8bfd7acd6795e61f39f07c6._comment ./doc/bugs/Build_error_on_Mac_OSX_10.6.mdwn ./doc/bugs/bare_git_repos.mdwn ./doc/bugs/fat_support.mdwn ./doc/bugs/problems_with_utf8_names.mdwn ./doc/bugs/error_with_file_names_starting_with_dash.mdwn ./doc/bugs/not_possible_to_have_annex_on_a_separate_filesystem.mdwn ./doc/bugs/Lost_S3_Remote.mdwn ./doc/bugs/unhappy_without_UTF8_locale.mdwn ./doc/bugs/S3_memory_leaks.mdwn ./doc/bugs/git_annex_map_has_problems_with_urls_containing___126__.mdwn ./doc/bugs/interrupting_migration_causes_problems.mdwn ./doc/bugs/upgrade_left_untracked_.git-annex__47____42___directories.mdwn ./doc/bugs/cyclic_drop.mdwn ./doc/bugs/Problems_running_make_on_osx/comment_9_cc283b485b3c95ba7eebc8f0c96969b3._comment ./doc/bugs/Problems_running_make_on_osx/comment_4_c52be386f79f14c8570a8f1397c68581._comment ./doc/bugs/Problems_running_make_on_osx/comment_18_64fab50d95de619eb2e8f08f90237de1._comment ./doc/bugs/Problems_running_make_on_osx/comment_16_5c2dd6002aadaab30841b77a5f5aed34._comment ./doc/bugs/Problems_running_make_on_osx/comment_10_94e4ac430140042a2d0fb5a16d86b4e5._comment ./doc/bugs/Problems_running_make_on_osx/comment_15_6b8867b8e48bf807c955779c9f8f0909._comment ./doc/bugs/Problems_running_make_on_osx/comment_11_56f1143fa191361d63b441741699e17f._comment ./doc/bugs/Problems_running_make_on_osx/comment_20_7db27d1a22666c831848bc6c06d66a84._comment ./doc/bugs/Problems_running_make_on_osx/comment_12_ec5131624d0d2285d3b6880e47033f97._comment ./doc/bugs/Problems_running_make_on_osx/comment_3_68f0f8ae953589ae26d57310b40c878d._comment ./doc/bugs/Problems_running_make_on_osx/comment_14_89a960b6706ed703b390a81a8bc4e311._comment ./doc/bugs/Problems_running_make_on_osx/comment_17_62fccb04b0e4b695312f7a3f32fb96ee._comment ./doc/bugs/Problems_running_make_on_osx/comment_19_4253988ed178054c8b6400beeed68a29._comment ./doc/bugs/Problems_running_make_on_osx/comment_6_0c46f5165ceb5a7b9ea9689c33b3a4f8._comment ./doc/bugs/Problems_running_make_on_osx/comment_1_34120e82331ace01a6a4960862d38f2d._comment ./doc/bugs/Problems_running_make_on_osx/comment_7_237a137cce58a28abcc736cbf2c420b0._comment ./doc/bugs/Problems_running_make_on_osx/comment_5_7f1330a1e541b0f3e2192e596d7f7bee._comment ./doc/bugs/Problems_running_make_on_osx/comment_2_cc53d1681d576186dbc868dd9801d551._comment ./doc/bugs/Problems_running_make_on_osx/comment_13_88ed095a448096bf8a69015a04e64df1._comment ./doc/bugs/Problems_running_make_on_osx/comment_8_efafa203addf8fa79e33e21a87fb5a2b._comment ./doc/bugs/git-annex_directory_hashing_problems_on_osx.mdwn ./doc/bugs/No_easy_way_to_re-inject_a_file_into_an_annex.mdwn ./doc/bugs/git_annex_unlock_is_not_atomic.mdwn ./doc/bugs/free_space_checking.mdwn ./doc/bugs/wishlist:_more_descriptive_commit_messages_in_git-annex_branch.mdwn ./doc/bugs/Displayed_copy_speed_is_wrong.mdwn ./doc/bugs/git_annex_should_use___39__git_add_-f__39___internally.mdwn ./doc/bugs/minor_bug:_errors_are_not_verbose_enough.mdwn ./doc/bugs/__34__make_test__34___fails_silently.mdwn ./doc/bugs/No_version_information_from_cli.mdwn ./doc/bugs/Error_while_adding_a_file___34__createSymbolicLink:_already_exists__34__.mdwn ./doc/bugs/conq:_invalid_command_syntax/comment_1_f33b83025ce974e496f83f248275a66a._comment ./doc/bugs/conq:_invalid_command_syntax/comment_2_195106ca8dedad5f4d755f625e38e8af._comment ./doc/bugs/conq:_invalid_command_syntax/comment_3_55af43e2f43a4c373f7a0a33678d0b1c._comment ./doc/bugs/old_data_isn__39__t_unused_after_migration.mdwn ./doc/bugs/fails_to_handle_lot_of_files.mdwn ./doc/bugs/tests_fail_when_there_is_no_global_.gitconfig_for_the_user.mdwn ./doc/bugs/git_annex_initremote_walks_.git-annex.mdwn ./doc/bugs/signal_weirdness.mdwn ./doc/bugs/git-annex_incorrectly_parses_bare_IPv6_addresses.mdwn ./doc/bugs/git_annex_version_should_without_being_in_a_repo_.mdwn ./doc/bugs/Can__39__t___34__git-annex_get__34___with_3.20111203.mdwn ./doc/bugs/Prevent_accidental_merges/comment_1_4c46a193915eab8f308a04175cb2e40a._comment ./doc/bugs/conflicting_haskell_packages/comment_1_e552a6cc6d7d1882e14130edfc2d6b3b._comment ./doc/bugs/tmp_file_handling.mdwn ./doc/bugs/annex_add_in_annex.mdwn ./doc/bugs/making_annex-merge_try_a_fast-forward.mdwn ./doc/bugs/bad_behaviour_with_file_names_with_newline_in_them.mdwn ./doc/bugs/Lost_S3_Remote/comment_2_c99c65882a3924f4890e500f9492b442._comment ./doc/bugs/Lost_S3_Remote/comment_3_1e434d5a20a692cd9dc7f6f8f20f30dd._comment ./doc/bugs/Lost_S3_Remote/comment_1_6e80e6db6671581d471fc9a54181c04c._comment ./doc/bugs/on--git-dir_and_--work-tree_options.mdwn ./doc/bugs/Makefile_is_missing_dependancies.mdwn ./doc/bugs/test_suite_shouldn__39__t_fail_silently.mdwn ./doc/bugs/git_annex_upgrade_output_is_inconsistent_and_spammy.mdwn ./doc/bugs/problem_with_upgrade_v2_-__62___v3/comment_4_91439d4dbbf1461e281b276eb0003691._comment ./doc/bugs/problem_with_upgrade_v2_-__62___v3/comment_6_f360f0006bc9115bc5a3e2eb9fe58abd._comment ./doc/bugs/problem_with_upgrade_v2_-__62___v3/comment_3_86d9e7244ae492bcbe62720b8c4fc4a9._comment ./doc/bugs/problem_with_upgrade_v2_-__62___v3/comment_2_cd0123392b16d89db41b45464165c247._comment ./doc/bugs/problem_with_upgrade_v2_-__62___v3/comment_1_5f60006c9bb095167d817f234a14d20b._comment ./doc/bugs/problem_with_upgrade_v2_-__62___v3/comment_5_ca33a9ca0df33f7c1b58353d7ffb943d._comment ./doc/bugs/wishlist:_query_things_like_description__44___trust_level.mdwn ./doc/bugs/git_rename_detection_on_file_move/comment_9_75e0973f6d573df615e01005ebcea87d._comment ./doc/bugs/git_rename_detection_on_file_move/comment_7_7f20d0b2f6ed1c34021a135438037306._comment ./doc/bugs/git_rename_detection_on_file_move/comment_3_57010bcaca42089b451ad8659a1e018e._comment ./doc/bugs/git_rename_detection_on_file_move/comment_4_79d96599f757757f34d7b784e6c0e81c._comment ./doc/bugs/git_rename_detection_on_file_move/comment_5_d61f5693d947b9736b29fca1dbc7ad76._comment ./doc/bugs/git_rename_detection_on_file_move/comment_8_6a00500b24ba53248c78e1ffc8d1a591._comment ./doc/bugs/git_rename_detection_on_file_move/comment_2_7101d07400ad5935f880dc00d89bf90e._comment ./doc/bugs/git_rename_detection_on_file_move/comment_6_f63de6fe2f7189c8c2908cc41c4bc963._comment ./doc/bugs/git_rename_detection_on_file_move/comment_1_0531dcfa833b0321a7009526efe3df33._comment ./doc/bugs/fsck_claims_failed_checksum_when_less_copies_than_required_are_found.mdwn ./doc/bugs/add_range_argument_to___34__git_annex_dropunused__34___.mdwn ./doc/bugs/git_rename_detection_on_file_move.mdwn ./doc/bugs/problem_commit_normal_links.mdwn ./doc/bugs/extraneous_shell_escaping_for_rsync_remotes.mdwn ./doc/bugs/problems_with_utf8_names/comment_1_3c7e3f021c2c94277eecf9c8af6cec5f._comment ./doc/bugs/problems_with_utf8_names/comment_4_93bee35f5fa7744834994bc7a253a6f9._comment ./doc/bugs/problems_with_utf8_names/comment_3_4f936a5d3f9c7df64c8a87e62b7fbfdc._comment ./doc/bugs/problems_with_utf8_names/comment_2_bad4c4c5f54358d1bc0ab2adc713782a._comment ./doc/bugs/git_annex_unused_seems_to_check_for_current_path.mdwn ./doc/bugs/Makefile_is_missing_dependancies/comment_6_24119fc5d5963ce9dd669f7dcf006859._comment ./doc/bugs/Makefile_is_missing_dependancies/comment_3_c38b6f4abc9b9ad413c3b83ca04386c3._comment ./doc/bugs/Makefile_is_missing_dependancies/comment_8_a3555e3286cdc2bfeb9cde0ff727ba74._comment ./doc/bugs/Makefile_is_missing_dependancies/comment_2_416f12dbd0c2b841fac8164645b81df5._comment ./doc/bugs/Makefile_is_missing_dependancies/comment_5_0a1c52e2c96d19b9c3eb7e99b8c2434f._comment ./doc/bugs/Makefile_is_missing_dependancies/comment_7_96fd4725df4b54e670077a18d3ac4943._comment ./doc/bugs/Makefile_is_missing_dependancies/comment_1_5a3da5f79c8563c7a450aa29728abe7c._comment ./doc/bugs/Makefile_is_missing_dependancies/comment_4_cc13873175edf191047282700315beee._comment ./doc/bugs/Trouble_initializing_git_annex_on_NFS.mdwn ./doc/bugs/touch.hsc_has_problems_on_non-linux_based_systems.mdwn ./doc/bugs/build_issue_with_latest_release_0.20110522-1-gde817ba.mdwn ./doc/bugs/weird_local_clone_confuses.mdwn ./doc/bugs/fsck_output.mdwn ./doc/bugs/git-annex_branch_push_race.mdwn ./doc/bugs/wishlist:_allow_users_to_provide_UUID_when_running___96__git_annex_init__96__.mdwn ./doc/bugs/git-annex_has_issues_with_git_when_staging__47__commiting_logs.mdwn ./doc/bugs/git_annex_gets_confused_about_remotes_with_dots_in_their_names.mdwn ./doc/bugs/unannex_vs_unlock_hook_confusion.mdwn ./doc/bugs/Cabal_dependency_monadIO_missing/comment_2_4f4d8e1e00a2a4f7e8a8ab082e16adac._comment ./doc/bugs/Cabal_dependency_monadIO_missing/comment_1_14be660aa57fadec0d81b32a8b52c66f._comment ./doc/bugs/conflicting_haskell_packages.mdwn ./doc/bugs/git_command_line_constructed_by_unannex_command_has_tons_of_redundant_-a_paramters.mdwn ./doc/bugs/backend_version_upgrade_leaves_repo_unusable.mdwn ./doc/bugs/fat_support/comment_3_df3b943bc1081a8f3f7434ae0c8e061e._comment ./doc/bugs/fat_support/comment_4_90a8a15bedd94480945a374f9d706b86._comment ./doc/bugs/fat_support/comment_5_64bbf89de0836673224b83fdefa0407b._comment ./doc/bugs/fat_support/comment_1_04bcc4795d431e8cb32293aab29bbfe2._comment ./doc/bugs/fat_support/comment_2_bb4a97ebadb5c53809fc78431eabd7c8._comment ./doc/bugs/unannex_command_doesn__39__t_all_files.mdwn ./doc/bugs/annex_unannex__47__uninit_should_handle_copies.mdwn ./doc/bugs/git-annex_branch_corruption.mdwn ./doc/bugs/git_annex_fsck_is_a_no-op_in_bare_repos.mdwn ./doc/bugs/Unfortunate_interaction_with_Calibre.mdwn ./doc/bugs/error_propigation.mdwn ./doc/bugs/wishlist:_support_drop__44___find_on_special_remotes.mdwn ./doc/bugs/scp_interrupt_to_background.mdwn ./doc/bugs/copy_fast_confusing_with_broken_locationlog.mdwn ./doc/bugs/uninit_does_not_work_in_old_repos/comment_1_bc0619c6e17139df74639448aa6a0f72._comment ./doc/bugs/git-annex_losing_rsync_remotes_with_encryption_enabled.mdwn ./doc/bugs/configure_script_should_detect_uuidgen_instead_of_just_uuid.mdwn ./doc/bugs/check_for_curl_in_configure.hs.mdwn ./doc/bugs/fails_to_handle_lot_of_files/comment_1_09d8e4e66d8273fab611bd29e82dc7fc._comment ./doc/bugs/fails_to_handle_lot_of_files/comment_2_fd2ec05f4b5a7a6ae6bd9f5dbc3156de._comment ./doc/bugs/Name_scheme_does_not_follow_git__39__s_rules.mdwn ./doc/bugs/concurrent_git-annex_processes_can_lead_to_locking_issues.mdwn ./doc/bugs/Prevent_accidental_merges.mdwn ./doc/bugs/building_on_lenny.mdwn ./doc/bugs/case_sensitivity_on_FAT.mdwn ./doc/bugs/encrypted_S3_stalls.mdwn ./doc/bugs/support_bare_git_repo__44___with_the_annex_directory_exposed_to_http.mdwn ./doc/bugs/WORM:_Handle_long_filenames_correctly.mdwn ./doc/logo_small.png ./doc/tips.mdwn ./doc/use_case/Bob.mdwn ./doc/use_case/Alice.mdwn ./doc/upgrades/SHA_size.mdwn ./doc/news/sharebox_a_FUSE_filesystem_for_git-annex.mdwn ./doc/news/version_3.20120113.mdwn ./doc/news/version_3.20120105.mdwn ./doc/news/version_3.20111231.mdwn ./doc/news/LWN_article.mdwn ./doc/news/version_3.20120106.mdwn ./doc/news/version_3.20120106/comment_1_fb1a3135e2d9f39f2c372ccc2c50c85a._comment ./doc/news/version_3.20120106/comment_2_ae292ca7294b6790233e545086c3ac2f._comment ./doc/news/version_3.20120106/comment_3_29ccda9ac458fd5cc9ec5508c62df6ea._comment ./doc/git-union-merge.mdwn ./doc/special_remotes/S3.mdwn ./doc/special_remotes/web.mdwn ./doc/special_remotes/bup.mdwn ./doc/special_remotes/directory.mdwn ./doc/special_remotes/hook.mdwn ./doc/special_remotes/rsync.mdwn ./doc/how_it_works.mdwn ./doc/sitemap.mdwn ./doc/users/joey.mdwn ./doc/users/fmarier.mdwn ./doc/users/chrysn.mdwn ./doc/users/gebi.mdwn ./doc/templates/walkthrough.tmpl ./doc/templates/bare.tmpl ./doc/index.mdwn ./doc/summary.mdwn ./doc/forum.mdwn ./doc/encryption/comment_1_1afca8d7182075d46db41f6ad3dd5911._comment ./doc/transferring_data.mdwn ./doc/download.mdwn ./doc/future_proofing.mdwn ./doc/todo/auto_remotes/discussion.mdwn ./doc/todo/link_file_to_remote_repo_feature.mdwn ./doc/todo/file_copy_progress_bar.mdwn ./doc/todo/use_cp_reflink.mdwn ./doc/todo/gitrm.mdwn ./doc/todo/exclude_files_on_a_given_remote.mdwn ./doc/todo/git-annex_unused_eats_memory.mdwn ./doc/todo/Please_abort_build_if___34__make_test__34___fails.mdwn ./doc/todo/add_--exclude_option_to_git_annex_find.mdwn ./doc/todo/tahoe_lfs_for_reals/comment_2_80b9e848edfdc7be21baab7d0cef0e3a._comment ./doc/todo/tahoe_lfs_for_reals/comment_1_0a4793ce6a867638f6e510e71dd4bb44._comment ./doc/todo/object_dir_reorg_v2.mdwn ./doc/todo/S3.mdwn ./doc/todo/auto_remotes.mdwn ./doc/todo/wishlist:_support_for_more_ssh_urls_.mdwn ./doc/todo/support-non-utf8-locales.mdwn ./doc/todo/done.mdwn ./doc/todo/fsck.mdwn ./doc/todo/support_S3_multipart_uploads.mdwn ./doc/todo/wishlist:_Provide_a___34__git_annex__34___command_that_will_skip_duplicates.mdwn ./doc/todo/pushpull.mdwn ./doc/todo/smudge.mdwn ./doc/todo/cache_key_info/comment_1_578df1b3b2cbfdc4aa1805378f35dc48._comment ./doc/todo/windows_support.mdwn ./doc/todo/optimise_git-annex_merge.mdwn ./doc/todo/object_dir_reorg_v2/comment_3_79bdf9c51dec9f52372ce95b53233bb2._comment ./doc/todo/object_dir_reorg_v2/comment_7_42501404c82ca07147e2cce0cff59474._comment ./doc/todo/object_dir_reorg_v2/comment_5_821c382987f105da72a50e0a5ce61fdc._comment ./doc/todo/object_dir_reorg_v2/comment_1_ba03333dc76ff49eccaba375e68cb525._comment ./doc/todo/object_dir_reorg_v2/comment_2_81276ac309959dc741bc90101c213ab7._comment ./doc/todo/object_dir_reorg_v2/comment_6_8834c3a3f1258c4349d23aff8549bf35._comment ./doc/todo/object_dir_reorg_v2/comment_4_93aada9b1680fed56cc6f0f7c3aca5e5._comment ./doc/todo/union_mounting.mdwn ./doc/todo/wishlist:_swift_backend.mdwn ./doc/todo/Please_add_support_for_monad-control_0.3.x.mdwn ./doc/todo/wishlist:_swift_backend/comment_1_e6efbb35f61ee521b473a92674036788._comment ./doc/todo/wishlist:_swift_backend/comment_2_5d8c83b0485112e98367b7abaab3f4e3._comment ./doc/todo/git_annex_init_:_include_repo_description_and__47__or_UUID_in_commit_message.mdwn ./doc/todo/gitolite_and_gitosis_support.mdwn ./doc/todo/wishlist:___34__git_annex_add__34___multiple_processes.mdwn ./doc/todo/hidden_files.mdwn ./doc/todo/smudge/comment_1_4ea616bcdbc9e9a6fae9f2e2795c31c9._comment ./doc/todo/smudge/comment_2_e04b32caa0d2b4c577cdaf382a3ff7f6._comment ./doc/todo/network_remotes.mdwn ./doc/todo/add_a_git_backend.mdwn ./doc/todo/parallel_possibilities/comment_1_d8e34fc2bc4e5cf761574608f970d496._comment ./doc/todo/parallel_possibilities/comment_2_adb76f06a7997abe4559d3169a3181c3._comment ./doc/todo/checkout.mdwn ./doc/todo/immutable_annexed_files.mdwn ./doc/todo/wishlist:_Prevent_repeated_password_prompts_for_one_command.mdwn ./doc/todo/git-annex-shell.mdwn ./doc/todo/speed_up_fsck.mdwn ./doc/todo/tahoe_lfs_for_reals.mdwn ./doc/todo/avoid_unnecessary_union_merges.mdwn ./doc/todo/support_fsck_in_bare_repos.mdwn ./doc/todo/add_-all_option.mdwn ./doc/todo/using_url_backend.mdwn ./doc/todo/branching.mdwn ./doc/todo/rsync.mdwn ./doc/todo/backendSHA1.mdwn ./doc/todo/cache_key_info.mdwn ./doc/todo/parallel_possibilities.mdwn ./doc/todo/symlink_farming_commit_hook.mdwn ./doc/feeds.mdwn ./doc/sync.mdwn ./doc/copies.mdwn ./doc/repomap.png ./doc/special_remotes.mdwn ./doc/todo.mdwn ./doc/walkthrough/using_ssh_remotes.mdwn ./doc/walkthrough/automatically_managing_content.mdwn ./doc/walkthrough/removing_files/comment_1_cb65e7c510b75be1c51f655b058667c6._comment ./doc/walkthrough/removing_files/comment_2_64709ea4558915edd5c8ca4486965b07._comment ./doc/walkthrough/moving_file_content_between_repositories.mdwn ./doc/walkthrough/modifying_annexed_files.mdwn ./doc/walkthrough/more.mdwn ./doc/walkthrough/removing_files.mdwn ./doc/walkthrough/creating_a_repository.mdwn ./doc/walkthrough/adding_a_remote.mdwn ./doc/walkthrough/adding_a_remote/comment_1_0a59355bd33a796aec97173607e6adc9._comment ./doc/walkthrough/adding_a_remote/comment_2_f8cd79ef1593a8181a7f1086a87713e8._comment ./doc/walkthrough/adding_a_remote/comment_3_60691af4400521b5a8c8d75efe3b44cb._comment ./doc/walkthrough/adding_a_remote/comment_4_6f7cf5c330272c96b3abeb6612075c9d._comment ./doc/walkthrough/removing_files:_When_things_go_wrong.mdwn ./doc/walkthrough/renaming_files.mdwn ./doc/walkthrough/using_bup.mdwn ./doc/walkthrough/fsck:_when_things_go_wrong.mdwn ./doc/walkthrough/syncing.mdwn ./doc/walkthrough/adding_files.mdwn ./doc/walkthrough/unused_data.mdwn ./doc/walkthrough/fsck:_verifying_your_data.mdwn ./doc/walkthrough/getting_file_content.mdwn ./doc/walkthrough/backups.mdwn ./doc/walkthrough/transferring_files:_When_things_go_wrong.mdwn ./doc/GPL ./doc/logo.png ./doc/location_tracking.mdwn ./doc/design.mdwn ./doc/news.mdwn ./doc/tips/visualizing_repositories_with_gource/screenshot.jpg ./doc/tips/untrusted_repositories.mdwn ./doc/tips/automatically_getting_files_on_checkout.mdwn ./doc/tips/what_to_do_when_a_repository_is_corrupted.mdwn ./doc/tips/Internet_Archive_via_S3.mdwn ./doc/tips/what_to_do_when_you_lose_a_repository.mdwn ./doc/tips/using_Amazon_S3.mdwn ./doc/tips/using_the_web_as_a_special_remote.mdwn ./doc/tips/powerful_file_matching.mdwn ./doc/tips/using_gitolite_with_git-annex.mdwn ./doc/tips/recover_data_from_lost+found.mdwn ./doc/tips/visualizing_repositories_with_gource.mdwn ./doc/tips/centralized_git_repository_tutorial.mdwn ./doc/tips/finding_duplicate_files/comment_1_ddb477ca242ffeb21e0df394d8fdf5d2._comment ./doc/tips/using_git_annex_with_no_fixed_hostname_and_optimising_ssh.mdwn ./doc/tips/using_gitolite_with_git-annex/comment_4_eb81f824aadc97f098379c5f7e4fba4c._comment ./doc/tips/using_gitolite_with_git-annex/comment_6_3e203e010a4df5bf03899f867718adc5._comment ./doc/tips/using_gitolite_with_git-annex/comment_1_9a2a2a8eac9af97e0c984ad105763a73._comment ./doc/tips/using_gitolite_with_git-annex/comment_8_8249772c142117f88e37975d058aa936._comment ./doc/tips/using_gitolite_with_git-annex/comment_5_f688309532d2993630e9e72e87fb9c46._comment ./doc/tips/using_gitolite_with_git-annex/comment_7_f8fd08b6ab47378ad88c87348057220d._comment ./doc/tips/using_gitolite_with_git-annex/comment_3_807035f38509ccb9f93f1929ecd37417._comment ./doc/tips/using_gitolite_with_git-annex/comment_9_28418635a6ed7231b89e02211cd3c236._comment ./doc/tips/using_gitolite_with_git-annex/comment_2_d8efea4ab9576555fadbb47666ecefa9._comment ./doc/tips/finding_duplicate_files.mdwn ./doc/tips/centralised_repository:_starting_from_nothing.mdwn ./doc/tips/using_the_SHA1_backend.mdwn ./doc/tips/migrating_data_to_a_new_backend.mdwn ./doc/encryption.mdwn ./doc/not.mdwn ./doc/download/comment_7_a5eebd214b135f34b18274a682211943._comment ./doc/download/comment_3_cf6044ebe99f71158034e21197228abd._comment ./doc/download/comment_5_c6b1bc40226fc2c8ba3e558150856992._comment ./doc/download/comment_6_3a52993d3553deb9a413debec9a5f92d._comment ./doc/download/comment_2_f85f72b33aedc3425f0c0c47867d02f3._comment ./doc/download/comment_8_59a976de6c7d333709b92f7cd5830850._comment ./doc/download/comment_4_10fc013865c7542c2ed9d6c0963bb391._comment ./doc/download/comment_1_fbd8b6d39e9d3c71791551358c863966._comment ./doc/contact.mdwn ./doc/trust.mdwn ./doc/bare_repositories.mdwn ./doc/NixOS.mdwn ./doc/distributed_version_control.mdwn ./doc/install.mdwn ./doc/git-annex-shell.mdwn ./doc/bugs.mdwn ./doc/meta.mdwn ./doc/design/encryption/comment_2_a610b3d056a059899178859a3a821ea5._comment ./doc/design/encryption/comment_3_cca186a9536cd3f6e86994631b14231c._comment ./doc/design/encryption/comment_1_4715ffafb3c4a9915bc33f2b26aaa9c1._comment ./doc/design/encryption/comment_4_8f3ba3e504b058791fc6e6f9c38154cf._comment ./doc/design/encryption.mdwn ./doc/comments.mdwn ./doc/git-annex.mdwn ./doc/internals.mdwn ./doc/users.mdwn ./doc/install/Ubuntu.mdwn ./doc/install/Debian.mdwn ./doc/install/openSUSE.mdwn ./doc/install/OSX.mdwn ./doc/install/FreeBSD.mdwn ./doc/install/OSX/comment_1_0a1760bf0db1f1ba89bdb4c62032f631._comment ./doc/install/ArchLinux.mdwn ./doc/install/Debian/comment_2_648e3467e260cdf233acdb0b53313ce0._comment ./doc/install/Debian/comment_1_029486088d098c2d4f1099f2f0e701a9._comment ./doc/install/Fedora.mdwn ./doc/walkthrough.mdwn ./CmdLine.hs ./Messages.hs ./Setup.hs ./GPL ./mdwn2man ./Remote.hs ./git-annex.hs ./Locations.hs ./Usage.hs ./Backend/WORM.hs ./Backend/URL.hs ./Backend/SHA.hs ./git-annex-shell.hs ./test.hs ./INSTALL ./Remote/Web.hs ./Remote/Helper/Encryptable.hs ./Remote/Helper/Ssh.hs ./Remote/Helper/Special.hs ./Remote/Directory.hs ./Remote/List.hs ./Remote/Bup.hs ./Remote/Hook.hs ./Remote/S3.hs ./Remote/Rsync.hs ./Remote/Git.hs ./Build/TestConfig.hs ./Upgrade.hs ./Annex/Version.hs ./Annex/Exception.hs ./Annex/Journal.hs ./Annex/CatFile.hs ./Annex/Queue.hs ./Annex/Branch.hs ./Annex/UUID.hs ./Annex/BranchState.hs ./Annex/Content.hs ./git-union-merge.hs ./Utility/Path.hs ./Utility/Matcher.hs ./Utility/TempFile.hs ./Utility/Url.hs ./Utility/DataUnits.hs ./Utility/StatFS.hsc ./Utility/Conditional.hs ./Utility/Monad.hs ./Utility/RsyncFile.hs ./Utility/CopyFile.hs ./Utility/Misc.hs ./Utility/SafeCommand.hs ./Utility/Gpg.hs ./Utility/Directory.hs ./Utility/FileMode.hs ./Utility/PartialPrelude.hs ./Utility/JSONStream.hs ./Utility/Dot.hs ./Utility/Touch.hsc ./Utility/Base64.hs ./Utility/Format.hs ./Types/Option.hs ./Types/Crypto.hs ./Types/UUID.hs ./Types/TrustLevel.hs ./Types/Remote.hs ./Types/BranchState.hs ./Types/Command.hs ./Types/Backend.hs ./Types/Key.hs ./Config.hs ./Checks.hs ./Command.hs ./.gitignore ./Backend.hs ./Logs/Web.hs ./Logs/UUIDBased.hs ./Logs/Trust.hs ./Logs/Location.hs ./Logs/UUID.hs ./Logs/Remote.hs ./Logs/Presence.hs ./.gitattributes ./Git.hs ./Limit.hs ./GitAnnex.hs Homepage: http://git-annex.branchable.com/ Build-type: Custom Category: Utility@@ -31,7 +31,7 @@ Build-Depends: MissingH, hslogger, directory, filepath, unix, containers, utf8-string, network, mtl, bytestring, old-locale, time, pcre-light, extensible-exceptions, dataenc, SHA, process, hS3, json, HTTP,- base < 5, monad-control, transformers-base, lifted-base+ base < 5, monad-control, transformers-base, lifted-base, quickcheck >= 2.1 Executable git-annex-shell Main-Is: git-annex-shell.hs
git-union-merge.hs view
@@ -28,9 +28,7 @@ setup = cleanup -- idempotency cleanup :: Git.Repo -> IO ()-cleanup g = do- e' <- doesFileExist (tmpIndex g)- when e' $ removeFile (tmpIndex g)+cleanup g = whenM (doesFileExist $ tmpIndex g) $ removeFile $ tmpIndex g parseArgs :: IO [String] parseArgs = do@@ -42,8 +40,8 @@ main :: IO () main = do [aref, bref, newref] <- map Git.Ref <$> parseArgs- g <- Git.Config.read =<< Git.Construct.fromCwd- _ <- Git.Index.override (tmpIndex g)+ g <- Git.Config.read =<< Git.Construct.fromCurrent+ _ <- Git.Index.override $ tmpIndex g setup g Git.UnionMerge.merge aref bref g _ <- Git.Branch.commit "union merge" newref [aref, bref] g
test.hs view
@@ -32,7 +32,6 @@ import qualified Types.Backend import qualified Types import qualified GitAnnex-import qualified Logs.Location import qualified Logs.UUIDBased import qualified Logs.Trust import qualified Logs.Remote@@ -663,6 +662,8 @@ -- gpg is not a build dependency, so only test when it's available test_crypto :: Test test_crypto = "git-annex crypto" ~: intmpclonerepo $ when Build.SysConfig.gpg $ do+ -- force gpg into batch mode for the tests+ setEnv "GPG_BATCH" "1" True Utility.Gpg.testTestHarness @? "test harness self-test failed" Utility.Gpg.testHarness $ do createDirectory "dir"@@ -726,7 +727,7 @@ -- are not run; this should only be used for actions that query state. annexeval :: Types.Annex a -> IO a annexeval a = do- g <- Git.Construct.fromCwd+ g <- Git.Construct.fromCurrent g' <- Git.Config.read g s <- Annex.new g' Annex.eval s { Annex.output = Annex.QuietOutput } a@@ -845,7 +846,7 @@ r <- annexeval $ Backend.lookupFile f case r of Just (k, _) -> do- uuids <- annexeval $ Logs.Location.keyLocations k+ uuids <- annexeval $ Remote.keyLocations k assertEqual ("bad content in location log for " ++ f ++ " key " ++ (show k) ++ " uuid " ++ show thisuuid) expected (thisuuid `elem` uuids) _ -> assertFailure $ f ++ " failed to look up key"