summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoeyHess <>2019-09-13 16:54:00 (GMT)
committerhdiff <hdiff@hdiff.luite.com>2019-09-13 16:54:00 (GMT)
commit09e89c7ef80c7e879bfe1376102101cca6baf130 (patch)
tree538b27694f3cd8ac0861907ce1d0bd3d0d5efc82
parent9383df3bee6ee096ffd27c6b43ddc11a3816ffe4 (diff)
version 7.201909127.20190912
-rw-r--r--Annex.hs2
-rw-r--r--Annex/AdjustedBranch.hs16
-rw-r--r--Annex/AutoMerge.hs24
-rw-r--r--Annex/CheckIgnore.hs16
-rw-r--r--Annex/Content.hs252
-rw-r--r--Annex/Content/Direct.hs181
-rw-r--r--Annex/Content/LowLevel.hs11
-rw-r--r--Annex/Direct.hs484
-rw-r--r--Annex/Drop.hs12
-rw-r--r--Annex/Fixup.hs7
-rw-r--r--Annex/Ingest.hs56
-rw-r--r--Annex/Init.hs66
-rw-r--r--Annex/Locations.hs3
-rw-r--r--Annex/Tmp.hs26
-rw-r--r--Annex/UpdateInstead.hs12
-rw-r--r--Annex/Version.hs29
-rw-r--r--Annex/WorkTree.hs17
-rw-r--r--Assistant/MakeRepo.hs (renamed from Annex/MakeRepo.hs)13
-rw-r--r--Assistant/Threads/Committer.hs101
-rw-r--r--Assistant/Threads/SanityChecker.hs4
-rw-r--r--Assistant/Threads/Watcher.hs65
-rw-r--r--Assistant/Upgrade.hs2
-rw-r--r--Assistant/WebApp/Configurators/Local.hs2
-rw-r--r--Build/BundledPrograms.hs2
-rw-r--r--Build/Configure.hs2
-rw-r--r--CHANGELOG40
-rw-r--r--CmdLine/Seek.hs25
-rw-r--r--Command.hs5
-rw-r--r--Command/Add.hs29
-rw-r--r--Command/AddUnused.hs7
-rw-r--r--Command/Adjust.hs2
-rw-r--r--Command/DiffDriver.hs7
-rw-r--r--Command/Direct.hs50
-rw-r--r--Command/EnableTor.hs4
-rw-r--r--Command/Fix.hs9
-rw-r--r--Command/FromKey.hs2
-rw-r--r--Command/Fsck.hs122
-rw-r--r--Command/FuzzTest.hs8
-rw-r--r--Command/Indirect.hs79
-rw-r--r--Command/Info.hs29
-rw-r--r--Command/Lock.hs10
-rw-r--r--Command/Migrate.hs2
-rw-r--r--Command/Multicast.hs5
-rw-r--r--Command/PreCommit.hs75
-rw-r--r--Command/Proxy.hs60
-rw-r--r--Command/ReKey.hs9
-rw-r--r--Command/RegisterUrl.hs2
-rw-r--r--Command/Status.hs44
-rw-r--r--Command/Sync.hs40
-rw-r--r--Command/Unannex.hs82
-rw-r--r--Command/Undo.hs13
-rw-r--r--Command/Uninit.hs2
-rw-r--r--Command/Unlock.hs60
-rw-r--r--Command/Unused.hs4
-rw-r--r--Command/Upgrade.hs10
-rw-r--r--Command/VAdd.hs2
-rw-r--r--Command/VCycle.hs2
-rw-r--r--Command/VFilter.hs2
-rw-r--r--Command/VPop.hs2
-rw-r--r--Command/View.hs2
-rw-r--r--Database/Keys.hs8
-rw-r--r--Git/Branch.hs4
-rw-r--r--Git/CheckAttr.hs23
-rw-r--r--Git/CheckIgnore.hs16
-rw-r--r--Git/Fsck.hs37
-rw-r--r--Git/Index.hs16
-rw-r--r--Git/Merge.hs3
-rw-r--r--Git/Remote/Remove.hs17
-rw-r--r--NEWS28
-rw-r--r--Remote/Git.hs41
-rw-r--r--Test.hs314
-rw-r--r--Test/Framework.hs45
-rw-r--r--Types/GitConfig.hs2
-rw-r--r--Upgrade.hs26
-rw-r--r--Upgrade/V4.hs14
-rw-r--r--Upgrade/V5.hs143
-rw-r--r--Upgrade/V5/Direct.hs126
-rw-r--r--Utility/CopyFile.hs3
-rw-r--r--Utility/DottedVersion.hs5
-rw-r--r--Utility/InodeCache.hs2
-rw-r--r--Utility/Path/Max.hs2
-rw-r--r--doc/git-annex-add.mdwn5
-rw-r--r--doc/git-annex-adjust.mdwn2
-rw-r--r--doc/git-annex-contentlocation.mdwn4
-rw-r--r--doc/git-annex-direct.mdwn21
-rw-r--r--doc/git-annex-examinekey.mdwn3
-rw-r--r--doc/git-annex-indirect.mdwn10
-rw-r--r--doc/git-annex-pre-commit.mdwn3
-rw-r--r--doc/git-annex-proxy.mdwn35
-rw-r--r--doc/git-annex-status.mdwn2
-rw-r--r--doc/git-annex-unlock.mdwn38
-rw-r--r--doc/git-annex-upgrade.mdwn13
-rw-r--r--doc/git-annex.mdwn365
-rw-r--r--git-annex.cabal7
94 files changed, 1075 insertions, 2559 deletions
diff --git a/Annex.hs b/Annex.hs
index d642885..efb3cc6 100644
--- a/Annex.hs
+++ b/Annex.hs
@@ -118,7 +118,7 @@ data AnnexState = AnnexState
, catfilehandles :: M.Map FilePath CatFileHandle
, hashobjecthandle :: Maybe HashObjectHandle
, checkattrhandle :: Maybe CheckAttrHandle
- , checkignorehandle :: Maybe (Maybe CheckIgnoreHandle)
+ , checkignorehandle :: Maybe CheckIgnoreHandle
, forcebackend :: Maybe String
, globalnumcopies :: Maybe NumCopies
, forcenumcopies :: Maybe NumCopies
diff --git a/Annex/AdjustedBranch.hs b/Annex/AdjustedBranch.hs
index 9cc449b..cc041e5 100644
--- a/Annex/AdjustedBranch.hs
+++ b/Annex/AdjustedBranch.hs
@@ -26,7 +26,6 @@ module Annex.AdjustedBranch (
propigateAdjustedCommits,
AdjustedClone(..),
checkAdjustedClone,
- isSupported,
checkVersionSupported,
isGitVersionSupported,
) where
@@ -50,7 +49,6 @@ import Git.Index
import Git.FilePath
import qualified Git.LockFile
import qualified Git.Version
-import Annex.Version
import Annex.CatFile
import Annex.Link
import Annex.AutoMerge
@@ -572,7 +570,7 @@ diffTreeToTreeItem dti = TreeItem
(Git.DiffTree.dstmode dti)
(Git.DiffTree.dstsha dti)
-data AdjustedClone = InAdjustedClone | NotInAdjustedClone | NeedUpgradeForAdjustedClone
+data AdjustedClone = InAdjustedClone | NotInAdjustedClone
{- Cloning a repository that has an adjusted branch checked out will
- result in the clone having the same adjusted branch checked out -- but
@@ -611,18 +609,10 @@ checkAdjustedClone = ifM isBareRepo
case aps of
Just [p] -> setBasisBranch basis p
_ -> giveup $ "Unable to clean up from clone of adjusted branch; perhaps you should check out " ++ Git.Ref.describe origbranch
- ifM versionSupportsUnlockedPointers
- ( return InAdjustedClone
- , return NeedUpgradeForAdjustedClone
- )
-
-isSupported :: Annex Bool
-isSupported = versionSupportsAdjustedBranch <&&> liftIO isGitVersionSupported
+ return InAdjustedClone
checkVersionSupported :: Annex ()
-checkVersionSupported = do
- unlessM versionSupportsAdjustedBranch $
- giveup "Adjusted branches are only supported in v6 or newer repositories."
+checkVersionSupported =
unlessM (liftIO isGitVersionSupported) $
giveup "Your version of git is too old; upgrade it to 2.2.0 or newer to use adjusted branches."
diff --git a/Annex/AutoMerge.hs b/Annex/AutoMerge.hs
index 36b67af..766e527 100644
--- a/Annex/AutoMerge.hs
+++ b/Annex/AutoMerge.hs
@@ -13,7 +13,6 @@ module Annex.AutoMerge
import Annex.Common
import qualified Annex.Queue
-import Annex.Direct
import Annex.CatFile
import Annex.Link
import Annex.Content
@@ -25,7 +24,6 @@ import qualified Git
import qualified Git.Branch
import Git.Types (TreeItemType(..), fromTreeItemType)
import Git.FilePath
-import Config
import Annex.ReplaceFile
import Annex.VariantFile
import qualified Database.Keys
@@ -50,9 +48,7 @@ autoMergeFrom branch currbranch mergeconfig canresolvemerge commitmode = do
Nothing -> go Nothing
Just b -> go =<< inRepo (Git.Ref.sha b)
where
- go old = ifM isDirect
- ( mergeDirect currbranch old branch resolvemerge mergeconfig commitmode
- , do
+ go old = do
r <- inRepo (Git.Merge.merge branch mergeconfig commitmode)
<||> (resolvemerge <&&> commitResolvedMerge commitmode)
-- Merging can cause new associated files to appear
@@ -61,7 +57,6 @@ autoMergeFrom branch currbranch mergeconfig canresolvemerge commitmode = do
-- close the database if it was open.
Database.Keys.closeDb
return r
- )
where
resolvemerge = ifM canresolvemerge
( resolveMerge old branch False
@@ -88,13 +83,9 @@ autoMergeFrom branch currbranch mergeconfig canresolvemerge commitmode = do
- the other as a directory or non-annexed file. The annexed file
- is renamed to resolve the merge, and the other object is preserved as-is.
-
- - In indirect mode, the merge is resolved in the work tree and files
+ - The merge is resolved in the work tree and files
- staged, to clean up from a conflicted merge that was run in the work
- tree.
- -
- - In direct mode, the work tree is not touched here; files are staged to
- - the index, and written to the gitAnnexMergeDir, for later handling by
- - the direct mode merge code.
-
- This is complicated by needing to support merges run in an overlay
- work tree, in which case the CWD won't be within the work tree.
@@ -126,7 +117,7 @@ resolveMerge us them inoverlay = do
let merged = not (null mergedfs')
void $ liftIO cleanup
- unlessM (pure inoverlay <||> isDirect) $ do
+ unless inoverlay $ do
(deleted, cleanup2) <- inRepo (LsFiles.deleted [top])
unless (null deleted) $
Annex.Queue.addCommand "rm"
@@ -136,7 +127,7 @@ resolveMerge us them inoverlay = do
when merged $ do
Annex.Queue.flush
- unlessM (pure inoverlay <||> isDirect) $ do
+ unless inoverlay $ do
unstagedmap <- inodeMap $ inRepo $ LsFiles.notInRepo False [top]
cleanConflictCruft mergedks' mergedfs' unstagedmap
showLongNote "Merge conflict was automatically resolved; you may want to examine the result."
@@ -230,12 +221,7 @@ resolveMerge' unstagedmap (Just us) them inoverlay u = do
Database.Keys.addAssociatedFile key
=<< inRepo (toTopFilePath dest)
- withworktree f a = ifM isDirect
- ( do
- d <- fromRepo gitAnnexMergeDir
- a (d </> f)
- , a f
- )
+ withworktree f a = a f
{- Stage a graft of a directory or file from a branch
- and update the work tree. -}
diff --git a/Annex/CheckIgnore.hs b/Annex/CheckIgnore.hs
index c8cd08c..4745470 100644
--- a/Annex/CheckIgnore.hs
+++ b/Annex/CheckIgnore.hs
@@ -19,23 +19,19 @@ import qualified Annex
checkIgnored :: FilePath -> Annex Bool
checkIgnored file = go =<< checkIgnoreHandle
where
- go Nothing = return False
- go (Just h) = liftIO $ Git.checkIgnored h file
+ go h = liftIO $ Git.checkIgnored h file
-checkIgnoreHandle :: Annex (Maybe Git.CheckIgnoreHandle)
+checkIgnoreHandle :: Annex Git.CheckIgnoreHandle
checkIgnoreHandle = maybe startup return =<< Annex.getState Annex.checkignorehandle
where
startup = do
- v <- inRepo Git.checkIgnoreStart
- when (isNothing v) $
- warning "The installed version of git is too old for .gitignores to be honored by git-annex."
- Annex.changeState $ \s -> s { Annex.checkignorehandle = Just v }
- return v
+ h <- inRepo Git.checkIgnoreStart
+ Annex.changeState $ \s -> s { Annex.checkignorehandle = Just h }
+ return h
checkIgnoreStop :: Annex ()
checkIgnoreStop = maybe noop stop =<< Annex.getState Annex.checkignorehandle
where
- stop (Just h) = do
+ stop h = do
liftIO $ Git.checkIgnoreStop h
Annex.changeState $ \s -> s { Annex.checkignorehandle = Nothing }
- stop Nothing = noop
diff --git a/Annex/Content.hs b/Annex/Content.hs
index a47485b..3b41784 100644
--- a/Annex/Content.hs
+++ b/Annex/Content.hs
@@ -1,6 +1,6 @@
{- git-annex file content managing
-
- - Copyright 2010-2018 Joey Hess <id@joeyh.name>
+ - Copyright 2010-2019 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
@@ -38,7 +38,7 @@ module Annex.Content (
removeAnnex,
moveBad,
KeyLocation(..),
- getKeysPresent,
+ listKeys,
saveState,
downloadUrl,
preseedTmp,
@@ -70,12 +70,9 @@ import Utility.FileMode
import qualified Annex.Url as Url
import Utility.CopyFile
import Utility.Metered
-import Config
import Git.FilePath
import Annex.Perms
import Annex.Link
-import qualified Annex.Content.Direct as Direct
-import Annex.ReplaceFile
import Annex.LockPool
import Messages.Progress
import Types.Remote (unVerified, Verification(..), RetrievalSecurityPolicy(..))
@@ -103,36 +100,22 @@ inAnnexCheck key check = inAnnex' id False check key
{- inAnnex that performs an arbitrary check of the key's content. -}
inAnnex' :: (a -> Bool) -> a -> (FilePath -> Annex a) -> Key -> Annex a
-inAnnex' isgood bad check key = withObjectLoc key checkindirect checkdirect
- where
- checkindirect loc = do
- r <- check loc
- if isgood r
- then ifM (annexThin <$> Annex.getGitConfig)
- -- When annex.thin is set, the object file
- -- could be modified; make sure it's not.
- -- (Suppress any messages about
- -- checksumming, to avoid them cluttering
- -- the display.)
- ( ifM (doQuietAction $ isUnmodified key loc)
- ( return r
- , return bad
- )
- , return r
- )
- else return bad
-
- -- In direct mode, at least one of the associated files must pass the
- -- check. Additionally, the file must be unmodified.
- checkdirect [] = return bad
- checkdirect (loc:locs) = do
- r <- check loc
- if isgood r
- then ifM (Direct.goodContent key loc)
+inAnnex' isgood bad check key = withObjectLoc key $ \loc -> do
+ r <- check loc
+ if isgood r
+ then ifM (annexThin <$> Annex.getGitConfig)
+ -- When annex.thin is set, the object file
+ -- could be modified; make sure it's not.
+ -- (Suppress any messages about
+ -- checksumming, to avoid them cluttering
+ -- the display.)
+ ( ifM (doQuietAction $ isUnmodified key loc)
( return r
- , checkdirect locs
+ , return bad
)
- else checkdirect locs
+ , return r
+ )
+ else return bad
{- Like inAnnex, checks if the object file for a key exists,
- but there are no guarantees it has the right content. -}
@@ -148,15 +131,13 @@ inAnnexSafe key = inAnnex' (fromMaybe True) (Just False) go key
is_unlocked = Just True
is_missing = Just False
- go contentfile = maybe (checkindirect contentfile) (checkdirect contentfile)
- =<< contentLockFile key
+ go contentfile = flip checklock contentfile =<< contentLockFile key
#ifndef mingw32_HOST_OS
- checkindirect contentfile = checkOr is_missing contentfile
- {- In direct mode, the content file must exist, but
- - the lock file generally won't exist unless a removal is in
- - process. -}
- checkdirect contentfile lockfile =
+ checklock Nothing contentfile = checkOr is_missing contentfile
+ {- The content file must exist, but the lock file generally
+ - won't exist unless a removal is in process. -}
+ checklock (Just lockfile) contentfile =
ifM (liftIO $ doesFileExist contentfile)
( checkOr is_unlocked lockfile
, return is_missing
@@ -166,8 +147,8 @@ inAnnexSafe key = inAnnex' (fromMaybe True) (Just False) go key
Just True -> is_locked
Just False -> is_unlocked
#else
- checkindirect f = liftIO $ ifM (doesFileExist f)
- ( lockShared f >>= \case
+ checklock Nothing contentfile = liftIO $ ifM (doesFileExist contentfile)
+ ( lockShared contentfile >>= \case
Nothing -> return is_locked
Just lockhandle -> do
dropLock lockhandle
@@ -176,7 +157,7 @@ inAnnexSafe key = inAnnex' (fromMaybe True) (Just False) go key
)
{- In Windows, see if we can take a shared lock. If so,
- remove the lock file to clean up after ourselves. -}
- checkdirect contentfile lockfile =
+ checklock (Just lockfile) contentfile =
ifM (liftIO $ doesFileExist contentfile)
( modifyContent lockfile $ liftIO $
lockShared lockfile >>= \case
@@ -189,15 +170,12 @@ inAnnexSafe key = inAnnex' (fromMaybe True) (Just False) go key
)
#endif
-{- Direct mode and especially Windows has to use a separate lock
- - file from the content, since locking the actual content file
- - would interfere with the user's use of it. -}
+{- Windows has to use a separate lock file from the content, since
+ - locking the actual content file would interfere with the user's
+ - use of it. -}
contentLockFile :: Key -> Annex (Maybe FilePath)
#ifndef mingw32_HOST_OS
-contentLockFile key = ifM isDirect
- ( Just <$> calcRepo (gitAnnexContentLock key)
- , return Nothing
- )
+contentLockFile _ = pure Nothing
#else
contentLockFile key = Just <$> calcRepo (gitAnnexContentLock key)
#endif
@@ -207,9 +185,6 @@ contentLockFile key = Just <$> calcRepo (gitAnnexContentLock key)
-
- If locking fails, or the content is not present, throws an exception
- rather than running the action.
- -
- - Note that, in direct mode, nothing prevents the user from directly
- - editing or removing the content, even while it's locked by this.
-}
lockContentShared :: Key -> (VerifiedCopy -> Annex a) -> Annex a
lockContentShared key a = lockContentUsing lock key $ ifM (inAnnex key)
@@ -467,8 +442,6 @@ withTmp key action = do
-
- When a key has associated pointer files, the object is hard
- linked (or copied) to the files, and the object file is left thawed.
- -
- - In direct mode, moves the object file to the associated file, or files.
-
- What if the key there already has content? This could happen for
- various reasons; perhaps the same content is being annexed again.
@@ -496,7 +469,7 @@ withTmp key action = do
moveAnnex :: Key -> FilePath -> Annex Bool
moveAnnex key src = ifM (checkSecureHashes key)
( do
- withObjectLoc key storeobject storedirect
+ withObjectLoc key storeobject
return True
, return False
)
@@ -513,32 +486,6 @@ moveAnnex key src = ifM (checkSecureHashes key)
ics <- mapM (populatePointerFile (Restage True) key dest) fs
Database.Keys.storeInodeCaches' key [dest] (catMaybes ics)
)
- storeindirect = storeobject =<< calcRepo (gitAnnexLocation key)
-
- {- In direct mode, the associated file's content may be locally
- - modified. In that case, it's preserved. However, the content
- - we're moving into the annex may be the only extant copy, so
- - it's important we not lose it. So, when the key's content
- - cannot be moved to any associated file, it's stored in indirect
- - mode.
- -}
- storedirect = storedirect' storeindirect
- storedirect' fallback [] = fallback
- storedirect' fallback (f:fs) = do
- thawContent src
- v <- isAnnexLink f
- if Just key == v
- then do
- Direct.updateInodeCache key src
- replaceFile f $ liftIO . moveFile src
- chmodContent f
- forM_ fs $
- Direct.addContentWhenNotPresent key f
- else ifM (Direct.goodContent key f)
- ( storedirect' alreadyhave fs
- , storedirect' fallback fs
- )
-
alreadyhave = liftIO $ removeFile src
checkSecureHashes :: Key -> Annex Bool
@@ -647,8 +594,8 @@ sendAnnex key rollback sendobject = go =<< prepSendAnnex key
{- Returns a file that contains an object's content,
- and a check to run after the transfer is complete.
-
- - When a file is unlocked (or in direct mode), it's possble for its
- - content to change as it's being sent. The check detects this case
+ - When a file is unlocked, it's possble for its content to
+ - change as it's being sent. The check detects this case
- and returns False.
-
- Note that the returned check action is, in some cases, run in the
@@ -656,47 +603,24 @@ sendAnnex key rollback sendobject = go =<< prepSendAnnex key
- the sender. So it cannot rely on Annex state.
-}
prepSendAnnex :: Key -> Annex (Maybe (FilePath, Annex Bool))
-prepSendAnnex key = withObjectLoc key indirect direct
- where
- indirect f = do
- cache <- Database.Keys.getInodeCaches key
- cache' <- if null cache
- -- Since no inode cache is in the database, this
- -- object is not currently unlocked. But that could
- -- change while the transfer is in progress, so
- -- generate an inode cache for the starting
- -- content.
- then maybeToList <$>
- withTSDelta (liftIO . genInodeCache f)
- else pure cache
- return $ if null cache'
- then Nothing
- else Just (f, sameInodeCache f cache')
- direct [] = return Nothing
- direct (f:fs) = do
- cache <- Direct.recordedInodeCache key
- -- check that we have a good file
- ifM (sameInodeCache f cache)
- ( return $ Just (f, sameInodeCache f cache)
- , direct fs
- )
-
-{- Performs an action, passing it the location to use for a key's content.
- -
- - In direct mode, the associated files will be passed. But, if there are
- - no associated files for a key, the indirect mode action will be
- - performed instead. -}
-withObjectLoc :: Key -> (FilePath -> Annex a) -> ([FilePath] -> Annex a) -> Annex a
-withObjectLoc key indirect direct = ifM isDirect
- ( do
- fs <- Direct.associatedFiles key
- if null fs
- then goindirect
- else direct fs
- , goindirect
- )
- where
- goindirect = indirect =<< calcRepo (gitAnnexLocation key)
+prepSendAnnex key = withObjectLoc key $ \f -> do
+ cache <- Database.Keys.getInodeCaches key
+ cache' <- if null cache
+ -- Since no inode cache is in the database, this
+ -- object is not currently unlocked. But that could
+ -- change while the transfer is in progress, so
+ -- generate an inode cache for the starting
+ -- content.
+ then maybeToList <$>
+ withTSDelta (liftIO . genInodeCache f)
+ else pure cache
+ return $ if null cache'
+ then Nothing
+ else Just (f, sameInodeCache f cache')
+
+{- Performs an action, passing it the location to use for a key's content. -}
+withObjectLoc :: Key -> (FilePath -> Annex a) -> Annex a
+withObjectLoc key a = a =<< calcRepo (gitAnnexLocation key)
cleanObjectLoc :: Key -> Annex () -> Annex ()
cleanObjectLoc key cleaner = do
@@ -714,17 +638,15 @@ cleanObjectLoc key cleaner = do
{- Removes a key's file from .git/annex/objects/
-}
removeAnnex :: ContentRemovalLock -> Annex ()
-removeAnnex (ContentRemovalLock key) = withObjectLoc key remove removedirect
- where
- remove file = cleanObjectLoc key $ do
+removeAnnex (ContentRemovalLock key) = withObjectLoc key $ \file ->
+ cleanObjectLoc key $ do
secureErase file
liftIO $ nukeFile file
g <- Annex.gitRepo
mapM_ (\f -> void $ tryIO $ resetpointer $ fromTopFilePath f g)
=<< Database.Keys.getAssociatedFiles key
Database.Keys.removeInodeCaches key
- Direct.removeInodeCache key
-
+ where
-- Check associated pointer file for modifications, and reset if
-- it's unmodified.
resetpointer file = ifM (isUnmodified key file)
@@ -736,18 +658,6 @@ removeAnnex (ContentRemovalLock key) = withObjectLoc key remove removedirect
, void $ tryIO $ thawContent file
)
- -- In direct mode, deletes the associated files or files, and replaces
- -- them with symlinks.
- removedirect fs = do
- cache <- Direct.recordedInodeCache key
- Direct.removeInodeCache key
- mapM_ (resetfile cache) fs
-
- resetfile cache f = whenM (Direct.sameInodeCache f cache) $ do
- l <- calcRepo $ gitAnnexLink f key
- secureErase f
- replaceFile f $ makeAnnexLink l
-
{- Check if a file contains the unmodified content of the key.
-
- The expensive way to tell is to do a verification of its content.
@@ -802,35 +712,32 @@ moveBad key = do
logStatus key InfoMissing
return dest
-data KeyLocation = InAnnex | InRepository | InAnywhere
+data KeyLocation = InAnnex | InAnywhere
-{- List of keys whose content exists in the specified location.
-
- - InAnnex only lists keys with content in .git/annex/objects,
- - while InRepository, in direct mode, also finds keys with content
- - in the work tree. InAnywhere lists all keys that have directories
- - in .git/annex/objects, whether or not the content is present.
- -
- - Note that InRepository has to check whether direct mode files
- - have goodContent.
+{- InAnnex only lists keys with content in .git/annex/objects.
+ - InAnywhere lists all keys that have directories in
+ - .git/annex/objects, whether or not the content is present.
-}
-getKeysPresent :: KeyLocation -> Annex [Key]
-getKeysPresent keyloc = do
- direct <- isDirect
+listKeys :: KeyLocation -> Annex [Key]
+listKeys keyloc = do
dir <- fromRepo gitAnnexObjectDir
- s <- getstate direct
+ {- In order to run Annex monad actions within unsafeInterleaveIO,
+ - the current state is taken and reused. No changes made to this
+ - state will be preserved.
+ -}
+ s <- Annex.getState id
depth <- gitAnnexLocationDepth <$> Annex.getGitConfig
- liftIO $ walk s direct depth dir
+ liftIO $ walk s depth dir
where
- walk s direct depth dir = do
+ walk s depth dir = do
contents <- catchDefaultIO [] (dirContents dir)
if depth < 2
then do
- contents' <- filterM (present s direct) contents
+ contents' <- filterM (present s) contents
let keys = mapMaybe (fileKey . takeFileName) contents'
continue keys []
else do
- let deeper = walk s direct (depth - 1)
+ let deeper = walk s (depth - 1)
continue [] (map deeper contents)
continue keys [] = return keys
continue keys (a:as) = do
@@ -842,33 +749,12 @@ getKeysPresent keyloc = do
InAnywhere -> True
_ -> False
- present _ _ _ | inanywhere = pure True
- present _ False d = presentInAnnex d
- present s True d = presentDirect s d <||> presentInAnnex d
+ present _ _ | inanywhere = pure True
+ present _ d = presentInAnnex d
presentInAnnex = doesFileExist . contentfile
contentfile d = d </> takeFileName d
- presentDirect s d = case keyloc of
- InAnnex -> return False
- InRepository -> case fileKey (takeFileName d) of
- Nothing -> return False
- Just k -> Annex.eval s $
- anyM (Direct.goodContent k) =<< Direct.associatedFiles k
- InAnywhere -> return True
-
- {- In order to run Annex monad actions within unsafeInterleaveIO,
- - the current state is taken and reused. No changes made to this
- - state will be preserved.
- -
- - As an optimsation, call inodesChanged to prime the state with
- - a cached value that will be used in the call to goodContent.
- -}
- getstate direct = do
- when direct $
- void inodesChanged
- Annex.getState id
-
{- Things to do to record changes to content when shutting down.
-
- It's acceptable to avoid committing changes to the branch,
diff --git a/Annex/Content/Direct.hs b/Annex/Content/Direct.hs
deleted file mode 100644
index 040070e..0000000
--- a/Annex/Content/Direct.hs
+++ /dev/null
@@ -1,181 +0,0 @@
-{- git-annex file content managing for direct mode
- -
- - This is deprecated, and will be removed when direct mode gets removed
- - from git-annex.
- -
- - Copyright 2012-2014 Joey Hess <id@joeyh.name>
- -
- - Licensed under the GNU AGPL version 3 or higher.
- -}
-
-module Annex.Content.Direct (
- associatedFiles,
- associatedFilesRelative,
- removeAssociatedFile,
- removeAssociatedFileUnchecked,
- removeAssociatedFiles,
- addAssociatedFile,
- goodContent,
- recordedInodeCache,
- updateInodeCache,
- addInodeCache,
- writeInodeCache,
- compareInodeCaches,
- sameInodeCache,
- elemInodeCaches,
- sameFileStatus,
- removeInodeCache,
- toInodeCache,
- addContentWhenNotPresent,
-) where
-
-import Annex.Common
-import Annex.Perms
-import qualified Git
-import Logs.Location
-import Logs.File
-import Utility.InodeCache
-import Utility.CopyFile
-import Annex.ReplaceFile
-import Annex.Link
-import Annex.InodeSentinal
-
-{- Absolute FilePaths of Files in the tree that are associated with a key. -}
-associatedFiles :: Key -> Annex [FilePath]
-associatedFiles key = do
- files <- associatedFilesRelative key
- top <- fromRepo Git.repoPath
- return $ map (top </>) files
-
-{- List of files in the tree that are associated with a key, relative to
- - the top of the repo. -}
-associatedFilesRelative :: Key -> Annex [FilePath]
-associatedFilesRelative key = do
- mapping <- calcRepo $ gitAnnexMapping key
- liftIO $ catchDefaultIO [] $ withFile mapping ReadMode $ \h ->
- -- Read strictly to ensure the file is closed
- -- before changeAssociatedFiles tries to write to it.
- -- (Especially needed on Windows.)
- lines <$> hGetContentsStrict h
-
-{- Changes the associated files information for a key, applying a
- - transformation to the list. Returns new associatedFiles value. -}
-changeAssociatedFiles :: Key -> ([FilePath] -> [FilePath]) -> Annex [FilePath]
-changeAssociatedFiles key transform = do
- mapping <- calcRepo $ gitAnnexMapping key
- files <- associatedFilesRelative key
- let files' = transform files
- when (files /= files') $
- modifyContent mapping $
- writeLogFile mapping $ unlines files'
- top <- fromRepo Git.repoPath
- return $ map (top </>) files'
-
-{- Removes the list of associated files. -}
-removeAssociatedFiles :: Key -> Annex ()
-removeAssociatedFiles key = do
- mapping <- calcRepo $ gitAnnexMapping key
- modifyContent mapping $
- liftIO $ nukeFile mapping
-
-{- Removes an associated file. Returns new associatedFiles value.
- - Checks if this was the last copy of the object, and updates location
- - log. -}
-removeAssociatedFile :: Key -> FilePath -> Annex [FilePath]
-removeAssociatedFile key file = do
- fs <- removeAssociatedFileUnchecked key file
- when (null fs) $
- logStatus key InfoMissing
- return fs
-
-{- Removes an associated file. Returns new associatedFiles value. -}
-removeAssociatedFileUnchecked :: Key -> FilePath -> Annex [FilePath]
-removeAssociatedFileUnchecked key file = do
- file' <- normaliseAssociatedFile file
- changeAssociatedFiles key $ filter (/= file')
-
-{- Adds an associated file. Returns new associatedFiles value. -}
-addAssociatedFile :: Key -> FilePath -> Annex [FilePath]
-addAssociatedFile key file = do
- file' <- normaliseAssociatedFile file
- changeAssociatedFiles key $ \files ->
- if file' `elem` files
- then files
- else file':files
-
-{- Associated files are always stored relative to the top of the repository.
- - The input FilePath is relative to the CWD, or is absolute. -}
-normaliseAssociatedFile :: FilePath -> Annex FilePath
-normaliseAssociatedFile file = do
- top <- fromRepo Git.repoPath
- liftIO $ relPathDirToFile top file
-
-{- Checks if a file in the tree, associated with a key, has not been modified.
- -
- - To avoid needing to fsck the file's content, which can involve an
- - expensive checksum, this relies on a cache that contains the file's
- - expected mtime and inode.
- -}
-goodContent :: Key -> FilePath -> Annex Bool
-goodContent key file = sameInodeCache file =<< recordedInodeCache key
-
-{- Gets the recorded inode cache for a key.
- -
- - A key can be associated with multiple files, so may return more than
- - one. -}
-recordedInodeCache :: Key -> Annex [InodeCache]
-recordedInodeCache key = withInodeCacheFile key $ \f ->
- liftIO $ catchDefaultIO [] $
- mapMaybe readInodeCache . lines <$> readFileStrict f
-
-{- Caches an inode for a file.
- -
- - Anything else already cached is preserved.
- -}
-updateInodeCache :: Key -> FilePath -> Annex ()
-updateInodeCache key file = maybe noop (addInodeCache key)
- =<< withTSDelta (liftIO . genInodeCache file)
-
-{- Adds another inode to the cache for a key. -}
-addInodeCache :: Key -> InodeCache -> Annex ()
-addInodeCache key cache = do
- oldcaches <- recordedInodeCache key
- unlessM (elemInodeCaches cache oldcaches) $
- writeInodeCache key (cache:oldcaches)
-
-{- Writes inode cache for a key. -}
-writeInodeCache :: Key -> [InodeCache] -> Annex ()
-writeInodeCache key caches = withInodeCacheFile key $ \f ->
- modifyContent f $
- liftIO $ writeFile f $
- unlines $ map showInodeCache caches
-
-{- Removes an inode cache. -}
-removeInodeCache :: Key -> Annex ()
-removeInodeCache key = withInodeCacheFile key $ \f ->
- modifyContent f $
- liftIO $ nukeFile f
-
-withInodeCacheFile :: Key -> (FilePath -> Annex a) -> Annex a
-withInodeCacheFile key a = a =<< calcRepo (gitAnnexInodeCache key)
-
-{- Checks if a FileStatus matches the recorded InodeCache of a file. -}
-sameFileStatus :: Key -> FilePath -> FileStatus -> Annex Bool
-sameFileStatus key f status = do
- old <- recordedInodeCache key
- curr <- withTSDelta $ \delta -> liftIO $ toInodeCache delta f status
- case (old, curr) of
- (_, Just c) -> elemInodeCaches c old
- ([], Nothing) -> return True
- _ -> return False
-
-{- Copies the contentfile to the associated file, if the associated
- - file has no content. If the associated file does have content,
- - even if the content differs, it's left unchanged. -}
-addContentWhenNotPresent :: Key -> FilePath -> FilePath -> Annex ()
-addContentWhenNotPresent key contentfile associatedfile = do
- v <- isAnnexLink associatedfile
- when (Just key == v) $
- replaceFile associatedfile $
- liftIO . void . copyFileExternal CopyAllMetaData contentfile
- updateInodeCache key associatedfile
diff --git a/Annex/Content/LowLevel.hs b/Annex/Content/LowLevel.hs
index 86d0826..599ff7d 100644
--- a/Annex/Content/LowLevel.hs
+++ b/Annex/Content/LowLevel.hs
@@ -48,12 +48,11 @@ linkOrCopy :: Key -> FilePath -> FilePath -> Maybe FileMode -> Annex (Maybe Link
linkOrCopy = linkOrCopy' (annexThin <$> Annex.getGitConfig)
linkOrCopy' :: Annex Bool -> Key -> FilePath -> FilePath -> Maybe FileMode -> Annex (Maybe LinkedOrCopied)
-linkOrCopy' canhardlink key src dest destmode
- | otherwise = catchDefaultIO Nothing $
- ifM canhardlink
- ( hardlink
- , copy =<< getstat
- )
+linkOrCopy' canhardlink key src dest destmode = catchDefaultIO Nothing $
+ ifM canhardlink
+ ( hardlink
+ , copy =<< getstat
+ )
where
hardlink = do
s <- getstat
diff --git a/Annex/Direct.hs b/Annex/Direct.hs
deleted file mode 100644
index 458f0e5..0000000
--- a/Annex/Direct.hs
+++ /dev/null
@@ -1,484 +0,0 @@
-{- git-annex direct mode
- -
- - This is deprecated, and will be removed when direct mode gets removed
- - from git-annex.
- -
- - Copyright 2012-2014 Joey Hess <id@joeyh.name>
- -
- - Licensed under the GNU AGPL version 3 or higher.
- -}
-
-module Annex.Direct where
-
-import Annex.Common
-import qualified Annex
-import qualified Git
-import qualified Git.LsFiles
-import qualified Git.Merge
-import qualified Git.DiffTree as DiffTree
-import qualified Git.Config
-import qualified Git.Ref
-import qualified Git.Branch
-import Git.Sha
-import Git.FilePath
-import Git.Types
-import Config
-import Annex.CatFile
-import qualified Annex.Queue
-import Logs.Location
-import Backend
-import Types.KeySource
-import Annex.Content
-import Annex.Content.Direct
-import Annex.Link
-import Utility.InodeCache
-import Utility.CopyFile
-import Annex.Perms
-import Annex.ReplaceFile
-import Annex.VariantFile
-import Git.Index
-import Annex.GitOverlay
-import Annex.LockFile
-import Annex.InodeSentinal
-import Utility.Metered
-
-{- Uses git ls-files to find files that need to be committed, and stages
- - them into the index. Returns True if some changes were staged. -}
-stageDirect :: Annex Bool
-stageDirect = do
- Annex.Queue.flush
- top <- fromRepo Git.repoPath
- (l, cleanup) <- inRepo $ Git.LsFiles.stagedOthersDetails [top]
- forM_ l go
- void $ liftIO cleanup
- staged <- Annex.Queue.size
- Annex.Queue.flush
- return $ staged /= 0
- where
- {- Determine what kind of modified or deleted file this is, as
- - efficiently as we can, by getting any key that's associated
- - with it in git, as well as its stat info. -}
- go (file, Just sha, Just _mode) = withTSDelta $ \delta -> do
- shakey <- catKey sha
- mstat <- liftIO $ catchMaybeIO $ getSymbolicLinkStatus file
- mcache <- liftIO $ maybe (pure Nothing) (toInodeCache delta file) mstat
- filekey <- isAnnexLink file >>= \case
- Just k -> return (Just k)
- -- v7 unlocked pointer file
- Nothing -> liftIO (isPointerFile file)
- case (shakey, filekey, mstat, mcache) of
- (_, Just key, _, _)
- | shakey == filekey -> noop
- {- A changed symlink. -}
- | otherwise -> stageannexlink file key
- (Just key, _, _, Just cache) -> do
- {- All direct mode files will show as
- - modified, so compare the cache to see if
- - it really was. -}
- oldcache <- recordedInodeCache key
- case oldcache of
- [] -> modifiedannexed file key cache
- _ -> unlessM (elemInodeCaches cache oldcache) $
- modifiedannexed file key cache
- (Just key, _, Nothing, _) -> deletedannexed file key
- (Nothing, _, Nothing, _) -> deletegit file
- (_, _, Just _, _) -> addgit file
- go _ = noop
-
- modifiedannexed file oldkey cache = do
- void $ removeAssociatedFile oldkey file
- void $ addDirect file cache
-
- deletedannexed file key = do
- void $ removeAssociatedFile key file
- deletegit file
-
- stageannexlink file key = do
- l <- calcRepo $ gitAnnexLink file key
- stageSymlink file =<< hashSymlink l
- void $ addAssociatedFile key file
-
- addgit file = Annex.Queue.addCommand "add" [Param "-f"] [file]
-
- deletegit file = Annex.Queue.addCommand "rm" [Param "-qf"] [file]
-
-{- Run before a commit to update direct mode bookeeping to reflect the
- - staged changes being committed. -}
-preCommitDirect :: Annex Bool
-preCommitDirect = do
- (diffs, clean) <- inRepo $ DiffTree.diffIndex Git.Ref.headRef
- makeabs <- flip fromTopFilePath <$> gitRepo
- forM_ diffs (go makeabs)
- liftIO clean
- where
- go makeabs diff = do
- withkey (DiffTree.srcsha diff) (DiffTree.srcmode diff) removeAssociatedFile
- withkey (DiffTree.dstsha diff) (DiffTree.dstmode diff) addAssociatedFile
- where
- withkey sha _mode a = when (sha /= nullSha) $
- catKey sha >>= \case
- Nothing -> noop
- Just key -> void $ a key $
- makeabs $ DiffTree.file diff
-
-{- Adds a file to the annex in direct mode. Can fail, if the file is
- - modified or deleted while it's being added. -}
-addDirect :: FilePath -> InodeCache -> Annex Bool
-addDirect file cache = do
- showStart "add" file
- let source = KeySource
- { keyFilename = file
- , contentLocation = file
- , inodeCache = Just cache
- }
- got =<< genKey source nullMeterUpdate=<< chooseBackend file
- where
- got Nothing = do
- showEndFail
- return False
- got (Just (key, _)) = ifM (sameInodeCache file [cache])
- ( do
- l <- calcRepo $ gitAnnexLink file key
- stageSymlink file =<< hashSymlink l
- addInodeCache key cache
- void $ addAssociatedFile key file
- logStatus key InfoPresent
- showEndOk
- return True
- , do
- showEndFail
- return False
- )
-
-{- In direct mode, git merge would usually refuse to do anything, since it
- - sees present direct mode files as type changed files.
- -
- - So, to handle a merge, it's run with the work tree set to a temp
- - directory, and the merge is staged into a copy of the index.
- - Then the work tree is updated to reflect the merge, and
- - finally, the merge is committed and the real index updated.
- -
- - A lock file is used to avoid races with any other caller of mergeDirect.
- -
- - To avoid other git processes from making changes to the index while our
- - merge is in progress, the index lock file is used as the temp index
- - file. This is the same as what git does when updating the index
- - normally.
- -}
-mergeDirect :: Maybe Git.Ref -> Maybe Git.Ref -> Git.Branch -> Annex Bool -> [Git.Merge.MergeConfig] -> Git.Branch.CommitMode -> Annex Bool
-mergeDirect startbranch oldref branch resolvemerge mergeconfig commitmode = exclusively $ do
- reali <- liftIO . absPath =<< fromRepo indexFile
- tmpi <- liftIO . absPath =<< fromRepo (indexFileLock . indexFile)
- liftIO $ whenM (doesFileExist reali) $
- copyFile reali tmpi
-
- d <- fromRepo gitAnnexMergeDir
- liftIO $ do
- whenM (doesDirectoryExist d) $
- removeDirectoryRecursive d
- createDirectoryIfMissing True d
-
- withIndexFile tmpi $ do
- merged <- stageMerge d branch mergeconfig commitmode
- ok <- if merged
- then return True
- else resolvemerge
- if ok
- then do
- mergeDirectCleanup d (fromMaybe Git.Sha.emptyTree oldref)
- mergeDirectCommit merged startbranch branch commitmode
- liftIO $ whenM (doesFileExist tmpi) $
- rename tmpi reali
- else do
- liftIO $ nukeFile tmpi
- liftIO $ removeDirectoryRecursive d
- return ok
- where
- exclusively = withExclusiveLock gitAnnexMergeLock
-
-{- Stage a merge into the index, avoiding changing HEAD or the current
- - branch. -}
-stageMerge :: FilePath -> Git.Branch -> [Git.Merge.MergeConfig] -> Git.Branch.CommitMode -> Annex Bool
-stageMerge d branch mergeconfig commitmode = do
- -- XXX A bug in git makes stageMerge unsafe to use if the git repo
- -- is configured with core.symlinks=false
- -- Using merge is not ideal though, since it will
- -- update the current branch immediately, before the work tree
- -- has been updated, which would leave things in an inconsistent
- -- state if mergeDirectCleanup is interrupted.
- -- <http://marc.info/?l=git&m=140262402204212&w=2>
- merger <- ifM (coreSymlinks <$> Annex.getGitConfig)
- ( return $ \ref -> Git.Merge.stageMerge ref mergeconfig
- , return $ \ref -> Git.Merge.merge ref mergeconfig commitmode
- )
- inRepo $ \g -> do
- wd <- liftIO $ absPath d
- gd <- liftIO $ absPath $ Git.localGitDir g
- merger branch $
- g { location = Local { gitdir = gd, worktree = Just (addTrailingPathSeparator wd) } }
-
-{- Commits after a direct mode merge is complete, and after the work
- - tree has been updated by mergeDirectCleanup.
- -}
-mergeDirectCommit :: Bool -> Maybe Git.Ref -> Git.Branch -> Git.Branch.CommitMode -> Annex ()
-mergeDirectCommit allowff old branch commitmode = do
- void preCommitDirect
- d <- fromRepo Git.localGitDir
- let merge_head = d </> "MERGE_HEAD"
- let merge_msg = d </> "MERGE_MSG"
- let merge_mode = d </> "MERGE_MODE"
- ifM (pure allowff <&&> canff)
- ( inRepo $ Git.Branch.update "merge" Git.Ref.headRef branch -- fast forward
- , do
- msg <- liftIO $
- catchDefaultIO ("merge " ++ fromRef branch) $
- readFile merge_msg
- void $ inRepo $ Git.Branch.commit commitmode False msg
- Git.Ref.headRef [Git.Ref.headRef, branch]
- )
- liftIO $ mapM_ nukeFile [merge_head, merge_msg, merge_mode]
- where
- canff = maybe (return False) (\o -> inRepo $ Git.Branch.fastForwardable o branch) old
-
-mergeDirectCleanup :: FilePath -> Git.Ref -> Annex ()
-mergeDirectCleanup d oldref = updateWorkTree d oldref False
-
-{- Updates the direct mode work tree to reflect the changes staged in the
- - index by a git command, that was run in a temporary work tree.
- -
- - Uses diff-index to compare the staged changes with provided ref
- - which should be the tree before the merge, and applies those
- - changes to the work tree.
- -
- - There are really only two types of changes: An old item can be deleted,
- - or a new item added. Two passes are made, first deleting and then
- - adding. This is to handle cases where eg, a file is deleted and a
- - directory is added. (The diff-tree output may list these in the opposite
- - order, but we cannot add the directory until the file with the
- - same name is removed.)
- -}
-updateWorkTree :: FilePath -> Git.Ref -> Bool -> Annex ()
-updateWorkTree d oldref force = do
- (items, cleanup) <- inRepo $ DiffTree.diffIndex oldref
- makeabs <- flip fromTopFilePath <$> gitRepo
- let fsitems = zip (map (makeabs . DiffTree.file) items) items
- forM_ fsitems $
- go makeabs DiffTree.srcsha moveout moveout_raw
- forM_ fsitems $
- go makeabs DiffTree.dstsha movein movein_raw
- void $ liftIO cleanup
- where
- go makeabs getsha a araw (f, item)
- | getsha item == nullSha = noop
- | otherwise = void $
- tryNonAsync . maybe (araw item makeabs f) (\k -> void $ a item makeabs k f)
- =<< catKey (getsha item)
-
- moveout _ _ = removeDirect
-
- {- Files deleted by the merge are removed from the work tree.
- - Empty work tree directories are removed, per git behavior. -}
- moveout_raw _ _ f = liftIO $ do
- nukeFile f
- void $ tryIO $ removeDirectory $ parentDir f
-
- {- If the file is already present, with the right content for the
- - key, it's left alone.
- -
- - If the file is already present, and does not exist in the
- - oldref, preserve this local file.
- -
- - Otherwise, create the symlink and then if possible, replace it
- - with the content. -}
- movein item makeabs k f = unlessM (goodContent k f) $ do
- unless force $ preserveUnannexed item makeabs f oldref
- l <- calcRepo $ gitAnnexLink f k
- replaceFile f $ makeAnnexLink l
- toDirect k f
-
- {- Any new, modified, or renamed files were written to the temp
- - directory by the merge, and are moved to the real work tree. -}
- movein_raw item makeabs f = do
- unless force $ preserveUnannexed item makeabs f oldref
- liftIO $ do
- createDirectoryIfMissing True $ parentDir f
- void $ tryIO $ rename (d </> getTopFilePath (DiffTree.file item)) f
-
-{- If the file that's being moved in is already present in the work
- - tree, but did not exist in the oldref, preserve this
- - local, unannexed file (or directory), as "variant-local".
- -
- - It's also possible that the file that's being moved in
- - is in a directory that collides with an exsting, non-annexed
- - file (not a directory), which should be preserved.
- -}
-preserveUnannexed :: DiffTree.DiffTreeItem -> (TopFilePath -> FilePath) -> FilePath -> Ref -> Annex ()
-preserveUnannexed item makeabs absf oldref = do
- whenM (liftIO (collidingitem absf) <&&> unannexed absf) $
- liftIO $ findnewname absf 0
- checkdirs (DiffTree.file item)
- where
- checkdirs from = case upFrom (getTopFilePath from) of
- Nothing -> noop
- Just p -> do
- let d = asTopFilePath p
- let absd = makeabs d
- whenM (liftIO (colliding_nondir absd) <&&> unannexed absd) $
- liftIO $ findnewname absd 0
- checkdirs d
-
- collidingitem f = isJust
- <$> catchMaybeIO (getSymbolicLinkStatus f)
- colliding_nondir f = maybe False (not . isDirectory)
- <$> catchMaybeIO (getSymbolicLinkStatus f)
-
- unannexed f = (isNothing <$> isAnnexLink f)
- <&&> (isNothing <$> catFileDetails oldref f)
-
- findnewname :: FilePath -> Int -> IO ()
- findnewname f n = do
- let localf = mkVariant f
- ("local" ++ if n > 0 then show n else "")
- ifM (collidingitem localf)
- ( findnewname f (n+1)
- , rename f localf
- `catchIO` const (findnewname f (n+1))
- )
-
-{- If possible, converts a symlink in the working tree into a direct
- - mode file. If the content is not available, leaves the symlink
- - unchanged. -}
-toDirect :: Key -> FilePath -> Annex ()
-toDirect k f = fromMaybe noop =<< toDirectGen k f
-
-toDirectGen :: Key -> FilePath -> Annex (Maybe (Annex ()))
-toDirectGen k f = do
- loc <- calcRepo $ gitAnnexLocation k
- ifM (liftIO $ doesFileExist loc)
- ( return $ Just $ fromindirect loc
- , do
- {- Copy content from another direct file. -}
- absf <- liftIO $ absPath f
- dlocs <- filterM (goodContent k) =<<
- filterM (\l -> isNothing <$> getAnnexLinkTarget l) =<<
- (filter (/= absf) <$> addAssociatedFile k f)
- case dlocs of
- [] -> return Nothing
- (dloc:_) -> return $ Just $ fromdirect dloc
- )
- where
- fromindirect loc = do
- {- Move content from annex to direct file. -}
- updateInodeCache k loc
- void $ addAssociatedFile k f
- modifyContent loc $ do
- thawContent loc
- liftIO (replaceFileFrom loc f)
- `catchIO` (\_ -> freezeContent loc)
- fromdirect loc = do
- replaceFile f $
- liftIO . void . copyFileExternal CopyAllMetaData loc
- updateInodeCache k f
-
-{- Removes a direct mode file, while retaining its content in the annex
- - (unless its content has already been changed). -}
-removeDirect :: Key -> FilePath -> Annex ()
-removeDirect k f = do
- void $ removeAssociatedFileUnchecked k f
- unlessM (inAnnex k) $
- -- If moveAnnex rejects the content of the key,
- -- treat that the same as its content having changed.
- ifM (goodContent k f)
- ( unlessM (moveAnnex k f) $
- logStatus k InfoMissing
- , logStatus k InfoMissing
- )
- liftIO $ do
- nukeFile f
- void $ tryIO $ removeDirectory $ parentDir f
-
-{- Called when a direct mode file has been changed. Its old content may be
- - lost. -}
-changedDirect :: Key -> FilePath -> Annex ()
-changedDirect oldk f = do
- locs <- removeAssociatedFile oldk f
- whenM (pure (null locs) <&&> not <$> inAnnex oldk) $
- logStatus oldk InfoMissing
-
-{- Git config settings to enable/disable direct mode. -}
-setDirect :: Bool -> Annex ()
-setDirect wantdirect = do
- if wantdirect
- then do
- switchHEAD
- setbare
- else do
- setbare
- switchHEADBack
- setConfig (annexConfig "direct") val
- Annex.changeGitConfig $ \c -> c { annexDirect = wantdirect }
- where
- val = Git.Config.boolConfig wantdirect
- coreworktree = ConfigKey "core.worktree"
- indirectworktree = ConfigKey "core.indirect-worktree"
- setbare = do
- -- core.worktree is not compatable with
- -- core.bare; git does not allow both to be set, so
- -- unset it when enabling direct mode, caching in
- -- core.indirect-worktree
- if wantdirect
- then moveconfig coreworktree indirectworktree
- else moveconfig indirectworktree coreworktree
- setConfig (ConfigKey Git.Config.coreBare) val
- moveconfig src dest = getConfigMaybe src >>= \case
- Nothing -> noop
- Just wt -> do
- unsetConfig src
- setConfig dest wt
- reloadConfig
-
-{- Since direct mode sets core.bare=true, incoming pushes could change
- - the currently checked out branch. To avoid this problem, HEAD
- - is changed to a internal ref that nothing is going to push to.
- -
- - For refs/heads/master, use refs/heads/annex/direct/master;
- - this way things that show HEAD (eg shell prompts) will
- - hopefully show just "master". -}
-directBranch :: Ref -> Ref
-directBranch orighead = case splitc '/' $ fromRef orighead of
- ("refs":"heads":"annex":"direct":_) -> orighead
- ("refs":"heads":rest) ->
- Ref $ "refs/heads/annex/direct/" ++ intercalate "/" rest
- _ -> Ref $ "refs/heads/" ++ fromRef (Git.Ref.base orighead)
-
-{- Converts a directBranch back to the original branch.
- -
- - Any other ref is left unchanged.
- -}
-fromDirectBranch :: Ref -> Ref
-fromDirectBranch directhead = case splitc '/' $ fromRef directhead of
- ("refs":"heads":"annex":"direct":rest) ->
- Ref $ "refs/heads/" ++ intercalate "/" rest
- _ -> directhead
-
-switchHEAD :: Annex ()
-switchHEAD = maybe noop switch =<< inRepo Git.Branch.currentUnsafe
- where
- switch orighead = do
- let newhead = directBranch orighead
- maybe noop (inRepo . Git.Branch.update "entering direct mode" newhead)
- =<< inRepo (Git.Ref.sha orighead)
- inRepo $ Git.Branch.checkout newhead
-
-switchHEADBack :: Annex ()
-switchHEADBack = maybe noop switch =<< inRepo Git.Branch.currentUnsafe
- where
- switch currhead = do
- let orighead = fromDirectBranch currhead
- inRepo (Git.Ref.sha currhead) >>= \case
- Just headsha
- | orighead /= currhead -> do
- inRepo $ Git.Branch.update "leaving direct mode" orighead headsha
- inRepo $ Git.Branch.checkout orighead
- inRepo $ Git.Branch.delete currhead
- _ -> inRepo $ Git.Branch.checkout orighead
diff --git a/Annex/Drop.hs b/Annex/Drop.hs
index 3fd3010..96f0eb7 100644
--- a/Annex/Drop.hs
+++ b/Annex/Drop.hs
@@ -17,7 +17,6 @@ import qualified Command.Drop
import Command
import Annex.Wanted
import Config
-import Annex.Content.Direct
import qualified Database.Keys
import Git.FilePath
@@ -44,20 +43,13 @@ type Reason = String
- A VerifiedCopy can be provided as an optimisation when eg, a key
- has just been uploaded to a remote.
-
- - In direct mode, all associated files are checked, and only if all
- - of them are unwanted are they dropped.
- -
- The runner is used to run CommandStart sequentially, it's typically
- callCommandAction.
-}
handleDropsFrom :: [UUID] -> [Remote] -> Reason -> Bool -> Key -> AssociatedFile -> [VerifiedCopy] -> (CommandStart -> CommandCleanup) -> Annex ()
handleDropsFrom locs rs reason fromhere key afile preverified runner = do
- l <- ifM isDirect
- ( associatedFilesRelative key
- , do
- g <- Annex.gitRepo
- map (`fromTopFilePath` g) <$> Database.Keys.getAssociatedFiles key
- )
+ g <- Annex.gitRepo
+ l <- map (`fromTopFilePath` g) <$> Database.Keys.getAssociatedFiles key
let fs = case afile of
AssociatedFile (Just f) -> nub (f : l)
AssociatedFile Nothing -> l
diff --git a/Annex/Fixup.hs b/Annex/Fixup.hs
index 449c284..d167086 100644
--- a/Annex/Fixup.hs
+++ b/Annex/Fixup.hs
@@ -12,7 +12,6 @@ import Git.Config
import Types.GitConfig
import Config.Files
import qualified Git
-import qualified Git.BuildVersion
import Utility.Path
import Utility.SafeCommand
import Utility.Directory
@@ -42,10 +41,8 @@ fixupRepo r c = do
{- Disable git's built-in wildcard expansion, which is not wanted
- when using it as plumbing by git-annex. -}
disableWildcardExpansion :: Repo -> Repo
-disableWildcardExpansion r
- | Git.BuildVersion.older "1.8.1" = r
- | otherwise = r
- { gitGlobalOpts = gitGlobalOpts r ++ [Param "--literal-pathspecs"] }
+disableWildcardExpansion r = r
+ { gitGlobalOpts = gitGlobalOpts r ++ [Param "--literal-pathspecs"] }
{- Direct mode repos have core.bare=true, but are not really bare.
- Fix up the Repo to be a non-bare repo, and arrange for git commands
diff --git a/Annex/Ingest.hs b/Annex/Ingest.hs
index 376aa46..1406c40 100644
--- a/Annex/Ingest.hs
+++ b/Annex/Ingest.hs
@@ -13,7 +13,6 @@ module Annex.Ingest (
ingestAdd',
ingest,
ingest',
- finishIngestDirect,
finishIngestUnlocked,
cleanOldKeys,
addLink,
@@ -28,12 +27,10 @@ import Annex.Common
import Types.KeySource
import Backend
import Annex.Content
-import Annex.Content.Direct
import Annex.Perms
import Annex.Link
import Annex.MetaData
import Annex.CurrentBranch
-import Annex.Version
import Logs.Location
import qualified Annex
import qualified Annex.Queue
@@ -137,14 +134,9 @@ ingestAdd' meterupdate ld@(Just (LockedDown cfg source)) mk = do
let f = keyFilename source
if lockingFile cfg
then addLink f k mic
- else ifM isDirect
- ( do
- l <- calcRepo $ gitAnnexLink f k
- stageSymlink f =<< hashSymlink l
- , do
- mode <- liftIO $ catchMaybeIO $ fileMode <$> getFileStatus (contentLocation source)
- stagePointerFile f mode =<< hashPointerFile k
- )
+ else do
+ mode <- liftIO $ catchMaybeIO $ fileMode <$> getFileStatus (contentLocation source)
+ stagePointerFile f mode =<< hashPointerFile k
return (Just k)
{- Ingests a locked down file into the annex. Does not update the working
@@ -170,10 +162,7 @@ ingest' preferredbackend meterupdate (Just (LockedDown cfg source)) mk restage =
where
go (Just key) mcache (Just s)
| lockingFile cfg = golocked key mcache s
- | otherwise = ifM isDirect
- ( godirect key mcache s
- , gounlocked key mcache s
- )
+ | otherwise = gounlocked key mcache s
go _ _ _ = failure "failed to generate a key"
golocked key mcache s =
@@ -197,12 +186,6 @@ ingest' preferredbackend meterupdate (Just (LockedDown cfg source)) mk restage =
success key (Just cache) s
gounlocked _ _ _ = failure "failed statting file"
- godirect key (Just cache) s = do
- addInodeCache key cache
- finishIngestDirect key source
- success key (Just cache) s
- godirect _ _ _ = failure "failed statting file"
-
success k mcache s = do
genMetaData k (keyFilename source) s
return (Just k, mcache)
@@ -212,16 +195,6 @@ ingest' preferredbackend meterupdate (Just (LockedDown cfg source)) mk restage =
cleanCruft source
return (Nothing, Nothing)
-finishIngestDirect :: Key -> KeySource -> Annex ()
-finishIngestDirect key source = do
- void $ addAssociatedFile key $ keyFilename source
- cleanCruft source
-
- {- Copy to any other locations using the same key. -}
- otherfs <- filter (/= keyFilename source) <$> associatedFiles key
- forM_ otherfs $
- addContentWhenNotPresent key (keyFilename source)
-
finishIngestUnlocked :: Key -> KeySource -> Annex ()
finishIngestUnlocked key source = do
cleanCruft source
@@ -333,12 +306,10 @@ forceParams = ifM (Annex.getState Annex.force)
- Also, when in an adjusted unlocked branch, always add files unlocked.
-}
addUnlocked :: Annex Bool
-addUnlocked = isDirect <||>
- (versionSupportsUnlockedPointers <&&>
- ((not . coreSymlinks <$> Annex.getGitConfig) <||>
- (annexAddUnlocked <$> Annex.getGitConfig) <||>
- (maybe False isadjustedunlocked . snd <$> getCurrentBranch)
- )
+addUnlocked =
+ ((not . coreSymlinks <$> Annex.getGitConfig) <||>
+ (annexAddUnlocked <$> Annex.getGitConfig) <||>
+ (maybe False isadjustedunlocked . snd <$> getCurrentBranch)
)
where
isadjustedunlocked (LinkAdjustment UnlockAdjustment) = True
@@ -352,7 +323,7 @@ addUnlocked = isDirect <||>
- When the content of the key is not accepted into the annex, returns False.
-}
addAnnexedFile :: FilePath -> Key -> Maybe FilePath -> Annex Bool
-addAnnexedFile file key mtmp = ifM (addUnlocked <&&> not <$> isDirect)
+addAnnexedFile file key mtmp = ifM addUnlocked
( do
mode <- maybe
(pure Nothing)
@@ -371,15 +342,8 @@ addAnnexedFile file key mtmp = ifM (addUnlocked <&&> not <$> isDirect)
)
, do
addLink file key Nothing
- whenM isDirect $ do
- void $ addAssociatedFile key file
case mtmp of
- Just tmp -> do
- {- For moveAnnex to work in direct mode, the
- - symlink must already exist, so flush the queue. -}
- whenM isDirect $
- Annex.Queue.flush
- moveAnnex key tmp
+ Just tmp -> moveAnnex key tmp
Nothing -> return True
)
where
diff --git a/Annex/Init.hs b/Annex/Init.hs
index 6a49f4b..bcfe017 100644
--- a/Annex/Init.hs
+++ b/Annex/Init.hs
@@ -22,7 +22,6 @@ import qualified Annex
import qualified Git
import qualified Git.Config
import qualified Git.Objects
-import qualified Git.LsFiles
import qualified Annex.Branch
import Logs.UUID
import Logs.Trust.Basic
@@ -32,12 +31,11 @@ import Types.RepoVersion
import Annex.Version
import Annex.Difference
import Annex.UUID
-import Annex.Link
import Annex.WorkTree
import Config
import Config.Files
import Config.Smudge
-import Annex.Direct
+import qualified Upgrade.V5.Direct as Direct
import qualified Annex.AdjustedBranch as AdjustedBranch
import Annex.Environment
import Annex.Hook
@@ -50,6 +48,7 @@ import Annex.Perms
import Utility.FileMode
import System.Posix.User
import qualified Utility.LockFile.Posix as Posix
+import Data.Either
#endif
import qualified Data.Map as M
@@ -107,27 +106,22 @@ initialize' mversion = checkCanInitialize $ do
hookWrite postReceiveHook
setDifferences
unlessM (isJust <$> getVersion) $
- ifM (crippledFileSystem <&&> (not <$> isBareRepo))
- ( setVersion (fromMaybe versionForCrippledFilesystem mversion)
- , setVersion (fromMaybe defaultVersion mversion)
- )
- whenM versionSupportsUnlockedPointers $ do
- configureSmudgeFilter
- scanUnlockedFiles
- unlessM isBareRepo $ do
- hookWrite postCheckoutHook
- hookWrite postMergeHook
+ setVersion (fromMaybe defaultVersion mversion)
+ configureSmudgeFilter
+ showSideAction "scanning for unlocked files"
+ scanUnlockedFiles True
+ unlessM isBareRepo $ do
+ hookWrite postCheckoutHook
+ hookWrite postMergeHook
AdjustedBranch.checkAdjustedClone >>= \case
- AdjustedBranch.NeedUpgradeForAdjustedClone ->
- void $ upgrade True versionForAdjustedClone
AdjustedBranch.InAdjustedClone -> return ()
AdjustedBranch.NotInAdjustedClone ->
ifM (crippledFileSystem <&&> (not <$> isBareRepo))
- ( adjustToCrippledFilesystem
+ ( AdjustedBranch.adjustToCrippledFileSystem
-- Handle case where this repo was cloned from a
-- direct mode repo
, unlessM isBareRepo
- switchHEADBack
+ Direct.switchHEADBack
)
propigateSecureHashesOnly
createInodeSentinalFile False
@@ -150,9 +144,9 @@ ensureInitialized :: Annex ()
ensureInitialized = getVersion >>= maybe needsinit checkUpgrade
where
needsinit = ifM Annex.Branch.hasSibling
- ( initialize Nothing Nothing
- , giveup "First run: git-annex init"
- )
+ ( initialize Nothing Nothing
+ , giveup $ "First run: git-annex init"
+ )
{- Checks if a repository is initialized. Does not check version for ugrade. -}
isInitialized :: Annex Bool
@@ -161,7 +155,7 @@ isInitialized = maybe Annex.Branch.hasSibling (const $ return True) =<< getVersi
{- A crippled filesystem is one that does not allow making symlinks,
- or removing write access from files. -}
probeCrippledFileSystem :: Annex Bool
-probeCrippledFileSystem = withOtherTmp $ \tmp -> do
+probeCrippledFileSystem = withEventuallyCleanedOtherTmp $ \tmp -> do
(r, warnings) <- liftIO $ probeCrippledFileSystem' tmp
mapM_ warning warnings
return r
@@ -218,14 +212,15 @@ probeLockSupport = do
#ifdef mingw32_HOST_OS
return True
#else
- withOtherTmp $ \tmp -> do
+ withEventuallyCleanedOtherTmp $ \tmp -> do
let f = tmp </> "lockprobe"
mode <- annexFileMode
liftIO $ do
nukeFile f
- ok <- catchBoolIO $ do
- Posix.dropLock =<< Posix.lockExclusive (Just mode) f
- return True
+ let locktest =
+ Posix.lockExclusive (Just mode) f
+ >>= Posix.dropLock
+ ok <- isRight <$> tryNonAsync locktest
nukeFile f
return ok
#endif
@@ -235,7 +230,7 @@ probeFifoSupport = do
#ifdef mingw32_HOST_OS
return False
#else
- withOtherTmp $ \tmp -> do
+ withEventuallyCleanedOtherTmp $ \tmp -> do
let f = tmp </> "gaprobe"
let f2 = tmp </> "gaprobe2"
liftIO $ do
@@ -281,22 +276,3 @@ propigateSecureHashesOnly :: Annex ()
propigateSecureHashesOnly =
maybe noop (setConfig (ConfigKey "annex.securehashesonly"))
=<< getGlobalConfig "annex.securehashesonly"
-
-adjustToCrippledFilesystem :: Annex ()
-adjustToCrippledFilesystem = ifM versionSupportsAdjustedBranch
- ( ifM (liftIO $ AdjustedBranch.isGitVersionSupported)
- ( AdjustedBranch.adjustToCrippledFileSystem
- , enableDirectMode
- )
- , enableDirectMode
- )
-
-enableDirectMode :: Annex ()
-enableDirectMode = unlessM isDirect $ do
- warning "Enabling direct mode."
- top <- fromRepo Git.repoPath
- (l, clean) <- inRepo $ Git.LsFiles.inRepo [top]
- forM_ l $ \f ->
- maybe noop (`toDirect` f) =<< isAnnexLink f
- void $ liftIO clean
- setDirect True
diff --git a/Annex/Locations.hs b/Annex/Locations.hs
index 0dfd138..96ab104 100644
--- a/Annex/Locations.hs
+++ b/Annex/Locations.hs
@@ -266,7 +266,8 @@ gitAnnexTmpOtherDir r = addTrailingPathSeparator $ gitAnnexDir r </> "othertmp"
gitAnnexTmpOtherLock :: Git.Repo -> FilePath
gitAnnexTmpOtherLock r = gitAnnexDir r </> "othertmp.lck"
-{- Tmp directory used by old versions of git-annex. -}
+{- .git/annex/misctmp/ was used by old versions of git-annex and is still
+ - used during initialization -}
gitAnnexTmpOtherDirOld :: Git.Repo -> FilePath
gitAnnexTmpOtherDirOld r = addTrailingPathSeparator $ gitAnnexDir r </> "misctmp"
diff --git a/Annex/Tmp.hs b/Annex/Tmp.hs
index 38262f5..1adc26d 100644
--- a/Annex/Tmp.hs
+++ b/Annex/Tmp.hs
@@ -7,9 +7,8 @@
module Annex.Tmp where
-import Common
-import Annex
-import Annex.Locations
+import Annex.Common
+import qualified Annex
import Annex.LockFile
import Annex.Perms
import Types.CleanupActions
@@ -24,13 +23,30 @@ import Data.Time.Clock.POSIX
-- any time.
withOtherTmp :: (FilePath -> Annex a) -> Annex a
withOtherTmp a = do
- addCleanup OtherTmpCleanup cleanupOtherTmp
+ Annex.addCleanup OtherTmpCleanup cleanupOtherTmp
tmpdir <- fromRepo gitAnnexTmpOtherDir
tmplck <- fromRepo gitAnnexTmpOtherLock
withSharedLock (const tmplck) $ do
void $ createAnnexDirectory tmpdir
a tmpdir
+-- | This uses an alternate temp directory. The action should normally
+-- clean up whatever files it writes there, but if it leaves files
+-- there (perhaps due to being interrupted), the files will be eventually
+-- cleaned up by another git-annex process (after they're a week old).
+--
+-- Unlike withOtherTmp, this does not rely on locking working.
+-- Its main use is in situations where the state of lockfile is not
+-- determined yet, eg during initialization.
+withEventuallyCleanedOtherTmp :: (FilePath -> Annex a) -> Annex a
+withEventuallyCleanedOtherTmp = bracket setup cleanup
+ where
+ setup = do
+ tmpdir <- fromRepo gitAnnexTmpOtherDirOld
+ void $ createAnnexDirectory tmpdir
+ return tmpdir
+ cleanup = liftIO . void . tryIO . removeDirectory
+
-- | Cleans up any tmp files that were left by a previous
-- git-annex process that got interrupted or failed to clean up after
-- itself for some other reason.
@@ -42,8 +58,6 @@ cleanupOtherTmp = do
void $ tryIO $ tryExclusiveLock (const tmplck) $ do
tmpdir <- fromRepo gitAnnexTmpOtherDir
void $ liftIO $ tryIO $ removeDirectoryRecursive tmpdir
- -- This is only to clean up cruft left by old versions of
- -- git-annex; it can be removed eventually.
oldtmp <- fromRepo gitAnnexTmpOtherDirOld
liftIO $ mapM_ cleanold =<< dirContentsRecursive oldtmp
liftIO $ void $ tryIO $ removeDirectory oldtmp -- when empty
diff --git a/Annex/UpdateInstead.hs b/Annex/UpdateInstead.hs
index a3a1dec..3f197cb 100644
--- a/Annex/UpdateInstead.hs
+++ b/Annex/UpdateInstead.hs
@@ -9,19 +9,15 @@ module Annex.UpdateInstead where
import qualified Annex
import Annex.Common
-import Config
-import Annex.Version
import Annex.AdjustedBranch
import Git.Branch
import Git.ConfigTypes
-{- receive.denyCurrentBranch=updateInstead does not work in direct mode
- - repositories or when an adjusted branch is checked out, so must be
- - emulated. -}
+{- receive.denyCurrentBranch=updateInstead does not work
+ - when an adjusted branch is checked out, so must be emulated. -}
needUpdateInsteadEmulation :: Annex Bool
-needUpdateInsteadEmulation = updateinsteadset <&&> (isDirect <||> isadjusted)
+needUpdateInsteadEmulation = updateinsteadset <&&> isadjusted
where
updateinsteadset = (== UpdateInstead) . receiveDenyCurrentBranch
<$> Annex.getGitConfig
- isadjusted = versionSupportsUnlockedPointers
- <&&> (maybe False (isJust . getAdjustment) <$> inRepo Git.Branch.current)
+ isadjusted = (maybe False (isJust . getAdjustment) <$> inRepo Git.Branch.current)
diff --git a/Annex/Version.hs b/Annex/Version.hs
index 5827dcb..6e0fd4f 100644
--- a/Annex/Version.hs
+++ b/Annex/Version.hs
@@ -17,19 +17,13 @@ import qualified Annex
import qualified Data.Map as M
defaultVersion :: RepoVersion
-defaultVersion = RepoVersion 5
+defaultVersion = RepoVersion 7
latestVersion :: RepoVersion
latestVersion = RepoVersion 7
supportedVersions :: [RepoVersion]
-supportedVersions = map RepoVersion [5, 7]
-
-versionForAdjustedClone :: RepoVersion
-versionForAdjustedClone = RepoVersion 7
-
-versionForCrippledFilesystem :: RepoVersion
-versionForCrippledFilesystem = RepoVersion 7
+supportedVersions = map RepoVersion [7]
upgradableVersions :: [RepoVersion]
#ifndef mingw32_HOST_OS
@@ -42,6 +36,7 @@ autoUpgradeableVersions :: M.Map RepoVersion RepoVersion
autoUpgradeableVersions = M.fromList
[ (RepoVersion 3, RepoVersion 5)
, (RepoVersion 4, RepoVersion 5)
+ , (RepoVersion 5, RepoVersion 6)
, (RepoVersion 6, RepoVersion 7)
]
@@ -51,24 +46,6 @@ versionField = annexConfig "version"
getVersion :: Annex (Maybe RepoVersion)
getVersion = annexVersion <$> Annex.getGitConfig
-versionSupportsDirectMode :: Annex Bool
-versionSupportsDirectMode = go <$> getVersion
- where
- go (Just v) | v >= RepoVersion 6 = False
- go _ = True
-
-versionSupportsUnlockedPointers :: Annex Bool
-versionSupportsUnlockedPointers = go <$> getVersion
- where
- go (Just v) | v >= RepoVersion 6 = True
- go _ = False
-
-versionSupportsAdjustedBranch :: Annex Bool
-versionSupportsAdjustedBranch = versionSupportsUnlockedPointers
-
-versionUsesKeysDatabase :: Annex Bool
-versionUsesKeysDatabase = versionSupportsUnlockedPointers
-
setVersion :: RepoVersion -> Annex ()
setVersion (RepoVersion v) = setConfig versionField (show v)
diff --git a/Annex/WorkTree.hs b/Annex/WorkTree.hs
index 419118f..eb64e0c 100644
--- a/Annex/WorkTree.hs
+++ b/Annex/WorkTree.hs
@@ -10,13 +10,11 @@ module Annex.WorkTree where
import Annex.Common
import Annex.Link
import Annex.CatFile
-import Annex.Version
import Annex.Content
import Annex.ReplaceFile
import Annex.CurrentBranch
import Annex.InodeSentinal
import Utility.InodeCache
-import Config
import Git.FilePath
import qualified Git.Ref
import qualified Git.LsTree
@@ -55,10 +53,7 @@ lookupFileNotHidden = lookupFile' catkeyfile
lookupFile' :: (FilePath -> Annex (Maybe Key)) -> FilePath -> Annex (Maybe Key)
lookupFile' catkeyfile file = isAnnexLink file >>= \case
Just key -> return (Just key)
- Nothing -> ifM (versionSupportsUnlockedPointers <||> isDirect)
- ( catkeyfile file
- , return Nothing
- )
+ Nothing -> catkeyfile file
{- Modifies an action to only act on files that are already annexed,
- and passes the key on to it. -}
@@ -75,11 +70,11 @@ ifAnnexed file yes no = maybe no yes =<< lookupFile file
- when initializing/upgrading a v6+ mode repository.
-
- Also, the content for the unlocked file may already be present as
- - an annex object. If so, make the unlocked file use that content.
+ - an annex object. If so, make the unlocked file use that content
+ - when replacefiles is True.
-}
-scanUnlockedFiles :: Annex ()
-scanUnlockedFiles = whenM (inRepo Git.Ref.headExists) $ do
- showSideAction "scanning for unlocked files"
+scanUnlockedFiles :: Bool -> Annex ()
+scanUnlockedFiles replacefiles = whenM (inRepo Git.Ref.headExists) $ do
Database.Keys.runWriter $
liftIO . Database.Keys.SQL.dropAllAssociatedFiles
(l, cleanup) <- inRepo $ Git.LsTree.lsTree Git.LsTree.LsTreeRecursive Git.Ref.headRef
@@ -97,7 +92,7 @@ scanUnlockedFiles = whenM (inRepo Git.Ref.headExists) $ do
let tf = Git.LsTree.file i
Database.Keys.runWriter $
liftIO . Database.Keys.SQL.addAssociatedFileFast (toIKey k) tf
- whenM (inAnnex k) $ do
+ whenM (pure replacefiles <&&> inAnnex k) $ do
f <- fromRepo $ fromTopFilePath tf
destmode <- liftIO $ catchMaybeIO $ fileMode <$> getFileStatus f
ic <- replaceFile f $ \tmp ->
diff --git a/Annex/MakeRepo.hs b/Assistant/MakeRepo.hs
index 9092fb3..372f216 100644
--- a/Annex/MakeRepo.hs
+++ b/Assistant/MakeRepo.hs
@@ -1,11 +1,11 @@
-{- making local repositories (used by webapp mostly)
+{- making local repositories
-
- Copyright 2012-2014 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
-module Annex.MakeRepo where
+module Assistant.MakeRepo where
import Assistant.WebApp.Common
import Annex.Init
@@ -15,12 +15,13 @@ import qualified Git.Command
import qualified Git.Branch
import qualified Annex
import Annex.UUID
-import Annex.Direct
+import Annex.AdjustedBranch
import Annex.Action
import Types.StandardGroups
import Logs.PreferredContent
import qualified Annex.Branch
import Utility.Process.Transcript
+import Config
{- Makes a new git repository. Or, if a git repository already
- exists, returns False. -}
@@ -59,13 +60,15 @@ initRepo True primary_assistant_repo dir desc mgroup = inDir dir $ do
, Param "-m"
, Param "created repository"
]
- {- Repositories directly managed by the assistant use direct mode.
+ {- Repositories directly managed by the assistant use
+ - an adjusted unlocked branch with annex.thin set.
-
- Automatic gc is disabled, as it can be slow. Insted, gc is done
- once a day.
-}
when primary_assistant_repo $ do
- setDirect True
+ void $ enterAdjustedBranch (LinkAdjustment UnlockAdjustment)
+ setConfig (annexConfig "thin") (Git.Config.boolConfig True)
inRepo $ Git.Command.run
[Param "config", Param "gc.auto", Param "0"]
getUUID
diff --git a/Assistant/Threads/Committer.hs b/Assistant/Threads/Committer.hs
index 865f7b0..a81f21f 100644
--- a/Assistant/Threads/Committer.hs
+++ b/Assistant/Threads/Committer.hs
@@ -20,7 +20,6 @@ import Assistant.Drop
import Types.Transfer
import Logs.Location
import qualified Annex.Queue
-import qualified Git.LsFiles
import Utility.ThreadScheduler
import qualified Utility.Lsof as Lsof
import qualified Utility.DirWatcher as DirWatcher
@@ -32,11 +31,9 @@ import Annex.Link
import Annex.Perms
import Annex.CatFile
import Annex.InodeSentinal
-import Annex.Version
import Annex.CurrentBranch
import qualified Annex
import Utility.InodeCache
-import Annex.Content.Direct
import qualified Database.Keys
import qualified Command.Sync
import qualified Git.Branch
@@ -54,8 +51,7 @@ commitThread :: NamedThread
commitThread = namedThread "Committer" $ do
havelsof <- liftIO $ inPath "lsof"
delayadd <- liftAnnex $
- maybe delayaddDefault (return . Just . Seconds)
- =<< annexDelayAdd <$> Annex.getGitConfig
+ fmap Seconds . annexDelayAdd <$> Annex.getGitConfig
msg <- liftAnnex Command.Sync.commitMsg
lockdowndir <- liftAnnex $ fromRepo gitAnnexTmpWatcherDir
liftAnnex $ do
@@ -240,19 +236,6 @@ commitStaged msg = do
Command.Sync.updateBranches =<< getCurrentBranch
return ok
-{- OSX needs a short delay after a file is added before locking it down,
- - as pasting a file seems to try to set file permissions or otherwise
- - access the file after closing it. -}
-delayaddDefault :: Annex (Maybe Seconds)
-#ifdef darwin_HOST_OS
-delayaddDefault = ifM (isDirect <||> versionSupportsUnlockedPointers)
- ( return Nothing
- , return $ Just $ Seconds 1
- )
-#else
-delayaddDefault = return Nothing
-#endif
-
{- If there are PendingAddChanges, or InProcessAddChanges, the files
- have not yet actually been added to the annex, and that has to be done
- now, before committing.
@@ -275,50 +258,22 @@ delayaddDefault = return Nothing
handleAdds :: FilePath -> Bool -> Maybe Seconds -> [Change] -> Assistant [Change]
handleAdds lockdowndir havelsof delayadd cs = returnWhen (null incomplete) $ do
let (pending, inprocess) = partition isPendingAddChange incomplete
- direct <- liftAnnex isDirect
- unlocked <- liftAnnex versionSupportsUnlockedPointers
- let lockingfiles = not (unlocked || direct)
let lockdownconfig = LockDownConfig
- { lockingFile = lockingfiles
+ { lockingFile = False
, hardlinkFileTmpDir = Just lockdowndir
}
- (pending', cleanup) <- if unlocked || direct
- then return (pending, noop)
- else findnew pending
(postponed, toadd) <- partitionEithers
- <$> safeToAdd lockdowndir lockdownconfig havelsof delayadd pending' inprocess
- cleanup
+ <$> safeToAdd lockdowndir lockdownconfig havelsof delayadd pending inprocess
unless (null postponed) $
refillChanges postponed
returnWhen (null toadd) $ do
added <- addaction toadd $
- catMaybes <$>
- if not lockingfiles
- then addunlocked direct toadd
- else forM toadd (add lockdownconfig)
- if DirWatcher.eventsCoalesce || null added || unlocked || direct
- then return $ added ++ otherchanges
- else do
- r <- handleAdds lockdowndir havelsof delayadd =<< getChanges
- return $ r ++ added ++ otherchanges
+ catMaybes <$> addunlocked toadd
+ return $ added ++ otherchanges
where
(incomplete, otherchanges) = partition (\c -> isPendingAddChange c || isInProcessAddChange c) cs
-
- -- Find files that are actually new, and not unlocked annexed
- -- files. The ls-files is run on a batch of files.
- findnew [] = return ([], noop)
- findnew pending@(exemplar:_) = do
- let segments = segmentXargsUnordered $ map changeFile pending
- rs <- liftAnnex $ forM segments $ \fs ->
- inRepo (Git.LsFiles.notInRepo False fs)
- let (newfiles, cleanup) = foldl'
- (\(l1, a1) (l2, a2) -> (l1 ++ l2, a1 >> a2))
- ([], return True) rs
- -- note: timestamp info is lost here
- let ts = changeTime exemplar
- return (map (PendingAddChange ts) newfiles, void $ liftIO cleanup)
returnWhen c a
| c = return otherchanges
@@ -330,10 +285,10 @@ handleAdds lockdowndir havelsof delayadd cs = returnWhen (null incomplete) $ do
where
ks = keySource ld
doadd = sanitycheck ks $ do
- (mkey, mcache) <- liftAnnex $ do
+ (mkey, _mcache) <- liftAnnex $ do
showStart "add" $ keyFilename ks
ingest nullMeterUpdate (Just $ LockedDown lockdownconfig ks) Nothing
- maybe (failedingest change) (done change mcache $ keyFilename ks) mkey
+ maybe (failedingest change) (done change $ keyFilename ks) mkey
add _ _ = return Nothing
{- Avoid overhead of re-injesting a renamed unlocked file, by
@@ -341,10 +296,10 @@ handleAdds lockdowndir havelsof delayadd cs = returnWhen (null incomplete) $ do
- same InodeCache as the new file. If so, we can just update
- bookkeeping, and stage the file in git.
-}
- addunlocked :: Bool -> [Change] -> Assistant [Maybe Change]
- addunlocked isdirect toadd = do
+ addunlocked :: [Change] -> Assistant [Maybe Change]
+ addunlocked toadd = do
ct <- liftAnnex compareInodeCachesWith
- m <- liftAnnex $ removedKeysMap isdirect ct cs
+ m <- liftAnnex $ removedKeysMap ct cs
delta <- liftAnnex getTSDelta
let cfg = LockDownConfig
{ lockingFile = False
@@ -359,46 +314,32 @@ handleAdds lockdowndir havelsof delayadd cs = returnWhen (null incomplete) $ do
Just cache ->
case M.lookup (inodeCacheToKey ct cache) m of
Nothing -> add cfg c
- Just k -> fastadd isdirect c k
+ Just k -> fastadd c k
- fastadd :: Bool -> Change -> Key -> Assistant (Maybe Change)
- fastadd isdirect change key = do
+ fastadd :: Change -> Key -> Assistant (Maybe Change)
+ fastadd change key = do
let source = keySource $ lockedDown change
- liftAnnex $ if isdirect
- then finishIngestDirect key source
- else finishIngestUnlocked key source
- done change Nothing (keyFilename source) key
+ liftAnnex $ finishIngestUnlocked key source
+ done change (keyFilename source) key
- removedKeysMap :: Bool -> InodeComparisonType -> [Change] -> Annex (M.Map InodeCacheKey Key)
- removedKeysMap isdirect ct l = do
+ removedKeysMap :: InodeComparisonType -> [Change] -> Annex (M.Map InodeCacheKey Key)
+ removedKeysMap ct l = do
mks <- forM (filter isRmChange l) $ \c ->
catKeyFile $ changeFile c
M.fromList . concat <$> mapM mkpairs (catMaybes mks)
where
mkpairs k = map (\c -> (inodeCacheToKey ct c, k)) <$>
- if isdirect
- then recordedInodeCache k
- else Database.Keys.getInodeCaches k
+ Database.Keys.getInodeCaches k
failedingest change = do
refill [retryChange change]
liftAnnex showEndFail
return Nothing
- done change mcache file key = liftAnnex $ do
+ done change file key = liftAnnex $ do
logStatus key InfoPresent
- ifM versionSupportsUnlockedPointers
- ( do
- mode <- liftIO $ catchMaybeIO $ fileMode <$> getFileStatus file
- stagePointerFile file mode =<< hashPointerFile key
- , do
- link <- ifM isDirect
- ( calcRepo $ gitAnnexLink file key
- , makeLink file key mcache
- )
- whenM (pure DirWatcher.eventsCoalesce <||> isDirect) $
- stageSymlink file =<< hashSymlink link
- )
+ mode <- liftIO $ catchMaybeIO $ fileMode <$> getFileStatus file
+ stagePointerFile file mode =<< hashPointerFile key
showEndOk
return $ Just $ finishedChange change key
diff --git a/Assistant/Threads/SanityChecker.hs b/Assistant/Threads/SanityChecker.hs
index abdba7d..bc65d9a 100644
--- a/Assistant/Threads/SanityChecker.hs
+++ b/Assistant/Threads/SanityChecker.hs
@@ -32,7 +32,6 @@ import Utility.ThreadScheduler
import qualified Assistant.Threads.Watcher as Watcher
import Utility.Batch
import Utility.NotificationBroadcaster
-import Config
import Utility.HumanTime
import Utility.Tense
import Git.Repair
@@ -200,8 +199,7 @@ dailyCheck urlrenderer = do
liftAnnex $ warning msg
void $ addAlert $ sanityCheckFixAlert msg
addsymlink file s = do
- isdirect <- liftAnnex isDirect
- Watcher.runHandler (Watcher.onAddSymlink isdirect) file s
+ Watcher.runHandler Watcher.onAddSymlink file s
insanity $ "found unstaged symlink: " ++ file
hourlyCheck :: Assistant ()
diff --git a/Assistant/Threads/Watcher.hs b/Assistant/Threads/Watcher.hs
index b24f6c4..cef02f0 100644
--- a/Assistant/Threads/Watcher.hs
+++ b/Assistant/Threads/Watcher.hs
@@ -23,25 +23,22 @@ import Assistant.Types.Changes
import Assistant.Alert
import Utility.DirWatcher
import Utility.DirWatcher.Types
+import Utility.InodeCache
import qualified Annex
import qualified Annex.Queue
import qualified Git
import qualified Git.UpdateIndex
import qualified Git.LsFiles as LsFiles
import Annex.WorkTree
-import Annex.Direct
-import Annex.Content.Direct
import Annex.CatFile
import Annex.CheckIgnore
import Annex.Link
import Annex.FileMatcher
import Annex.Content
import Annex.ReplaceFile
-import Annex.Version
import Annex.InodeSentinal
import Git.Types
import Git.FilePath
-import Config
import Config.GitConfig
import Utility.ThreadScheduler
import Logs.Location
@@ -92,16 +89,10 @@ runWatcher :: Assistant ()
runWatcher = do
startup <- asIO1 startupScan
matcher <- liftAnnex largeFilesMatcher
- direct <- liftAnnex isDirect
- unlocked <- liftAnnex versionSupportsUnlockedPointers
symlinkssupported <- liftAnnex $ coreSymlinks <$> Annex.getGitConfig
- addhook <- hook $ if unlocked
- then onAddUnlocked symlinkssupported matcher
- else if direct
- then onAddDirect symlinkssupported matcher
- else onAdd matcher
+ addhook <- hook $ onAddUnlocked symlinkssupported matcher
delhook <- hook onDel
- addsymlinkhook <- hook $ onAddSymlink direct
+ addsymlinkhook <- hook onAddSymlink
deldirhook <- hook onDelDir
errhook <- hook onErr
let hooks = mkWatchHooks
@@ -210,13 +201,6 @@ add largefilematcher file = ifM (liftAnnex $ checkFileMatcher largefilematcher f
madeChange file AddFileChange
)
-onAdd :: GetFileMatcher -> Handler
-onAdd matcher file filestatus
- | maybe False isRegularFile filestatus =
- unlessIgnored file $
- add matcher file
- | otherwise = noChange
-
shouldRestage :: DaemonStatus -> Bool
shouldRestage ds = scanComplete ds || forceRestage ds
@@ -224,7 +208,7 @@ onAddUnlocked :: Bool -> GetFileMatcher -> Handler
onAddUnlocked symlinkssupported matcher f fs = do
mk <- liftIO $ isPointerFile f
case mk of
- Nothing -> onAddUnlocked' False contentchanged addassociatedfile addlink samefilestatus symlinkssupported matcher f fs
+ Nothing -> onAddUnlocked' contentchanged addassociatedfile addlink samefilestatus symlinkssupported matcher f fs
Just k -> addlink f k
where
addassociatedfile key file =
@@ -247,27 +231,15 @@ onAddUnlocked symlinkssupported matcher f fs = do
liftAnnex $ stagePointerFile file mode =<< hashPointerFile key
madeChange file $ LinkChange (Just key)
-{- In direct mode, add events are received for both new files, and
- - modified existing files.
- -}
-onAddDirect :: Bool -> GetFileMatcher -> Handler
-onAddDirect = onAddUnlocked' True changedDirect addassociatedfile addlink sameFileStatus
- where
- addassociatedfile key file = void $ addAssociatedFile key file
- addlink file key = do
- link <- liftAnnex $ calcRepo $ gitAnnexLink file key
- addLink file link (Just key)
-
onAddUnlocked'
- :: Bool
- -> (Key -> FilePath -> Annex ())
+ :: (Key -> FilePath -> Annex ())
-> (Key -> FilePath -> Annex ())
-> (FilePath -> Key -> Assistant (Maybe Change))
-> (Key -> FilePath -> FileStatus -> Annex Bool)
-> Bool
-> GetFileMatcher
-> Handler
-onAddUnlocked' isdirect contentchanged addassociatedfile addlink samefilestatus symlinkssupported matcher file fs = do
+onAddUnlocked' contentchanged addassociatedfile addlink samefilestatus symlinkssupported matcher file fs = do
v <- liftAnnex $ catKeyFile file
case (v, fs) of
(Just key, Just filestatus) ->
@@ -306,31 +278,28 @@ onAddUnlocked' isdirect contentchanged addassociatedfile addlink samefilestatus
Nothing -> noop
Just key -> liftAnnex $
addassociatedfile key file
- onAddSymlink' (Just $ fromRawFilePath lt) mk isdirect file fs
+ onAddSymlink' (Just $ fromRawFilePath lt) mk file fs
{- A symlink might be an arbitrary symlink, which is just added.
- Or, if it is a git-annex symlink, ensure it points to the content
- before adding it.
-}
-onAddSymlink :: Bool -> Handler
-onAddSymlink isdirect file filestatus = unlessIgnored file $ do
+onAddSymlink :: Handler
+onAddSymlink file filestatus = unlessIgnored file $ do
linktarget <- liftIO (catchMaybeIO $ readSymbolicLink file)
kv <- liftAnnex (lookupFile file)
- onAddSymlink' linktarget kv isdirect file filestatus
+ onAddSymlink' linktarget kv file filestatus
-onAddSymlink' :: Maybe String -> Maybe Key -> Bool -> Handler
-onAddSymlink' linktarget mk isdirect file filestatus = go mk
+onAddSymlink' :: Maybe String -> Maybe Key -> Handler
+onAddSymlink' linktarget mk file filestatus = go mk
where
go (Just key) = do
- when isdirect $
- liftAnnex $ void $ addAssociatedFile key file
link <- liftAnnex $ calcRepo $ gitAnnexLink file key
if linktarget == Just link
then ensurestaged (Just link) =<< getDaemonStatus
else do
- unless isdirect $
- liftAnnex $ replaceFile file $
- makeAnnexLink link
+ liftAnnex $ replaceFile file $
+ makeAnnexLink link
addLink file link (Just key)
-- other symlink, not git-annex
go Nothing = ensurestaged linktarget =<< getDaemonStatus
@@ -376,11 +345,7 @@ onDel file _ = do
onDel' :: FilePath -> Annex ()
onDel' file = do
topfile <- inRepo (toTopFilePath file)
- ifM versionSupportsUnlockedPointers
- ( withkey $ flip Database.Keys.removeAssociatedFile topfile
- , whenM isDirect $
- withkey $ \key -> void $ removeAssociatedFile key file
- )
+ withkey $ flip Database.Keys.removeAssociatedFile topfile
Annex.Queue.addUpdateIndex =<<
inRepo (Git.UpdateIndex.unstageFile file)
where
diff --git a/Assistant/Upgrade.hs b/Assistant/Upgrade.hs
index 9f07d5b..a8920bb 100644
--- a/Assistant/Upgrade.hs
+++ b/Assistant/Upgrade.hs
@@ -113,7 +113,7 @@ distributionDownloadComplete d dest cleanup t
| transferDirection t == Download = do
debug ["finished downloading git-annex distribution"]
maybe (failedupgrade "bad download") go
- =<< liftAnnex (withObjectLoc k fsckit (getM fsckit))
+ =<< liftAnnex (withObjectLoc k fsckit)
| otherwise = cleanup
where
k = distributionKey d
diff --git a/Assistant/WebApp/Configurators/Local.hs b/Assistant/WebApp/Configurators/Local.hs
index bdc576e..eb52be0 100644
--- a/Assistant/WebApp/Configurators/Local.hs
+++ b/Assistant/WebApp/Configurators/Local.hs
@@ -15,7 +15,7 @@ import Assistant.WebApp.Gpg
import Assistant.WebApp.MakeRemote
import Assistant.Sync
import Assistant.Restart
-import Annex.MakeRepo
+import Assistant.MakeRepo
import qualified Annex
import qualified Git
import qualified Git.Config
diff --git a/Build/BundledPrograms.hs b/Build/BundledPrograms.hs
index 3af2b1e..096eeee 100644
--- a/Build/BundledPrograms.hs
+++ b/Build/BundledPrograms.hs
@@ -83,5 +83,7 @@ preferredBundledPrograms = catMaybes
-- its kernel, and avoid using them if not available.
]
where
+#ifndef mingw32_HOST_OS
ifset True s = Just s
ifset False _ = Nothing
+#endif
diff --git a/Build/Configure.hs b/Build/Configure.hs
index 3edb0f2..6efd593 100644
--- a/Build/Configure.hs
+++ b/Build/Configure.hs
@@ -62,7 +62,7 @@ getGitVersion = go =<< getEnv "FORCE_GIT_VERSION"
go (Just s) = return $ Config "gitversion" $ StringConfig s
go Nothing = do
v <- Git.Version.installed
- let oldestallowed = Git.Version.normalize "1.7.1.0"
+ let oldestallowed = Git.Version.normalize "2.1"
when (v < oldestallowed) $
error $ "installed git version " ++ show v ++ " is too old! (Need " ++ show oldestallowed ++ " or newer)"
return $ Config "gitversion" $ StringConfig $ show v
diff --git a/CHANGELOG b/CHANGELOG
index 23d78ac..231c843 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,43 @@
+git-annex (7.20190912) upstream; urgency=medium
+
+ * Default to v7 for new repositories.
+ * Automatically upgrade v5 repositories to v7.
+ * Automatically convert direct mode repositories to v7 with adjusted
+ unlocked branches and set annex.thin.
+ * Added annex.autoupgraderepository configuration that can be set to false
+ to prevent any automatic repository upgrades.
+ * Refuse to upgrade direct mode repositories when git is older than 2.22,
+ which fixed a memory leak that could cause an OOM during the upgrade.
+ * Removed support for git versions older than 2.1.
+ * assistant: When creating a new repository, no longer use direct
+ mode, instead use v7 adjusted branches with annex.thin.
+ * init: When run on a crippled filesystem with --version=5,
+ will error out, since version 7 is needed for adjusted unlocked branch.
+ * direct: This command always errors out as direct mode is no longer
+ supported.
+ * indirect: This command has become a deprecated noop.
+ * proxy: This command is deprecated because it was only needed in direct
+ mode. (But it continues to work.)
+ * info: Removed the "repository mode" from its output (including the
+ --json output) since with the removal of direct mode, there is no
+ repository mode.
+ * info: When file matching options are specified when getting
+ info of something other than a directory, they won't have any effect,
+ so error out to avoid confusion.
+ * info: Display trust level when getting info on a uuid, same as a remote.
+ * When upgrading a direct mode repo to v7 with adjusted unlocked branches,
+ fix a bug that prevented annex.thin from taking effect for the files
+ in working tree.
+ * Avoid making a commit when upgrading from direct mode to v7.
+ * init: Catch more exceptions when testing locking.
+ * init: Fix a reversion that broke initialization on systems that
+ need to use pid locking.
+ * A git-annex-standalone rpm is now distributed along with the standalone
+ tarball.
+ * Added standalone/rpm/rpmbuild-from-standalone-tarball script.
+
+ -- Joey Hess <id@joeyh.name> Fri, 13 Sep 2019 12:53:06 -0400
+
git-annex (7.20190819) upstream; urgency=medium
* New git-lfs special remote, which can be used to store data on any git-lfs
diff --git a/CmdLine/Seek.hs b/CmdLine/Seek.hs
index 9196a6d..4107e9d 100644
--- a/CmdLine/Seek.hs
+++ b/CmdLine/Seek.hs
@@ -114,38 +114,21 @@ withFilesToBeCommitted :: (FilePath -> CommandSeek) -> [WorkTreeItem] -> Command
withFilesToBeCommitted a l = seekActions $ prepFiltered a $
seekHelper LsFiles.stagedNotDeleted l
-withFilesOldUnlocked :: (FilePath -> CommandSeek) -> [WorkTreeItem] -> CommandSeek
-withFilesOldUnlocked = withFilesOldUnlocked' LsFiles.typeChanged
-
-{- Unlocked files before v6 have changed type from a symlink to a regular file.
- -
- - Furthermore, unlocked files used to be a git-annex symlink,
- - not some other sort of symlink.
- -}
-withFilesOldUnlocked' :: ([FilePath] -> Git.Repo -> IO ([FilePath], IO Bool)) -> (FilePath -> CommandSeek) -> [WorkTreeItem] -> CommandSeek
-withFilesOldUnlocked' typechanged a l = seekActions $
- prepFiltered a unlockedfiles
- where
- unlockedfiles = filterM isOldUnlocked =<< seekHelper typechanged l
-
isOldUnlocked :: FilePath -> Annex Bool
isOldUnlocked f = liftIO (notSymlink f) <&&>
(isJust <$> catKeyFile f <||> isJust <$> catKeyFileHEAD f)
-withFilesOldUnlockedToBeCommitted :: (FilePath -> CommandSeek) -> [WorkTreeItem] -> CommandSeek
-withFilesOldUnlockedToBeCommitted = withFilesOldUnlocked' LsFiles.typeChangedStaged
-
-{- v6 unlocked pointer files that are staged, and whose content has not been
+{- unlocked pointer files that are staged, and whose content has not been
- modified-}
withUnmodifiedUnlockedPointers :: (FilePath -> CommandSeek) -> [WorkTreeItem] -> CommandSeek
withUnmodifiedUnlockedPointers a l = seekActions $
prepFiltered a unlockedfiles
where
- unlockedfiles = filterM isV6UnmodifiedUnlocked
+ unlockedfiles = filterM isUnmodifiedUnlocked
=<< seekHelper LsFiles.typeChangedStaged l
-isV6UnmodifiedUnlocked :: FilePath -> Annex Bool
-isV6UnmodifiedUnlocked f = catKeyFile f >>= \case
+isUnmodifiedUnlocked :: FilePath -> Annex Bool
+isUnmodifiedUnlocked f = catKeyFile f >>= \case
Nothing -> return False
Just k -> sameInodeCache f =<< Database.Keys.getInodeCaches k
diff --git a/Command.hs b/Command.hs
index f64c8dc..54415d0 100644
--- a/Command.hs
+++ b/Command.hs
@@ -24,7 +24,6 @@ import CmdLine.Batch as ReExported
import Options.Applicative as ReExported hiding (command)
import qualified Git
import Annex.Init
-import Config
import Utility.Daemon
import Types.Transfer
import Types.ActionItem
@@ -120,10 +119,6 @@ commonChecks = [repoExists]
repoExists :: CommandCheck
repoExists = CommandCheck 0 ensureInitialized
-notDirect :: Command -> Command
-notDirect = addCheck $ whenM isDirect $
- giveup "You cannot run this command in a direct mode repository."
-
notBareRepo :: Command -> Command
notBareRepo = addCheck $ whenM (fromRepo Git.repoIsLocalBare) $
giveup "You cannot run this command in a bare repository."
diff --git a/Command/Add.hs b/Command/Add.hs
index 9304f28..200f66e 100644
--- a/Command/Add.hs
+++ b/Command/Add.hs
@@ -11,14 +11,11 @@ import Command
import Annex.Ingest
import Logs.Location
import Annex.Content
-import Annex.Content.Direct
import qualified Annex
import qualified Annex.Queue
import qualified Database.Keys
-import Config
import Annex.FileMatcher
import Annex.Link
-import Annex.Version
import Annex.Tmp
import Messages.Progress
import Git.FilePath
@@ -71,11 +68,7 @@ seek o = startConcurrency commandStages $ do
unless (updateOnly o) $
go (withFilesNotInGit (not $ includeDotFiles o))
go withFilesMaybeModified
- ifM versionSupportsUnlockedPointers
- ( go withUnmodifiedUnlockedPointers
- , unlessM isDirect $
- go withFilesOldUnlocked
- )
+ go withUnmodifiedUnlockedPointers
{- Pass file off to git-add. -}
startSmall :: FilePath -> CommandStart
@@ -95,12 +88,8 @@ addFile file = do
start :: FilePath -> CommandStart
start file = do
- ifM versionSupportsUnlockedPointers
- ( do
- mk <- liftIO $ isPointerFile file
- maybe go fixuppointer mk
- , go
- )
+ mk <- liftIO $ isPointerFile file
+ maybe go fixuppointer mk
where
go = ifAnnexed file addpresent add
add = liftIO (catchMaybeIO $ getSymbolicLinkStatus file) >>= \case
@@ -112,18 +101,10 @@ start file = do
if isSymbolicLink s
then next $ addFile file
else perform file
- addpresent key = ifM versionSupportsUnlockedPointers
- ( liftIO (catchMaybeIO $ getSymbolicLinkStatus file) >>= \case
+ addpresent key =
+ liftIO (catchMaybeIO $ getSymbolicLinkStatus file) >>= \case
Just s | isSymbolicLink s -> fixuplink key
_ -> add
- , ifM isDirect
- ( liftIO (catchMaybeIO $ getSymbolicLinkStatus file) >>= \case
- Just s | isSymbolicLink s -> fixuplink key
- _ -> ifM (goodContent key file)
- ( stop , add )
- , fixuplink key
- )
- )
fixuplink key = starting "add" (ActionItemWorkTreeFile file) $ do
-- the annexed symlink is present but not yet added to git
liftIO $ removeFile file
diff --git a/Command/AddUnused.hs b/Command/AddUnused.hs
index 5aa035f..025b25e 100644
--- a/Command/AddUnused.hs
+++ b/Command/AddUnused.hs
@@ -13,10 +13,9 @@ import Annex.Ingest
import Command.Unused (withUnusedMaps, UnusedMaps(..), startUnused)
cmd :: Command
-cmd = notDirect $
- command "addunused" SectionMaintenance
- "add back unused files"
- (paramRepeating paramNumRange) (withParams seek)
+cmd = command "addunused" SectionMaintenance
+ "add back unused files"
+ (paramRepeating paramNumRange) (withParams seek)
seek :: CmdParams -> CommandSeek
seek = withUnusedMaps start
diff --git a/Command/Adjust.hs b/Command/Adjust.hs
index 6930e2c..679f98a 100644
--- a/Command/Adjust.hs
+++ b/Command/Adjust.hs
@@ -11,7 +11,7 @@ import Command
import Annex.AdjustedBranch
cmd :: Command
-cmd = notBareRepo $ notDirect $ noDaemonRunning $
+cmd = notBareRepo $ noDaemonRunning $
command "adjust" SectionSetup "enter adjusted branch"
paramNothing (seek <$$> optParser)
diff --git a/Command/DiffDriver.hs b/Command/DiffDriver.hs
index 2ed0a41..f4251c0 100644
--- a/Command/DiffDriver.hs
+++ b/Command/DiffDriver.hs
@@ -90,12 +90,7 @@ fixupReq req@(Req {}) =
v <- getAnnexLinkTarget' (getfile r) False
case parseLinkTargetOrPointer =<< v of
Nothing -> return r
- Just k -> setfile r <$>
- withObjectLoc k
- -- indirect mode
- return
- -- direct mode
- (return . Prelude.head)
+ Just k -> withObjectLoc k (pure . setfile r)
_ -> return r
externalDiffer :: String -> [String] -> Differ
diff --git a/Command/Direct.hs b/Command/Direct.hs
index c0ebf54..ac29541 100644
--- a/Command/Direct.hs
+++ b/Command/Direct.hs
@@ -8,60 +8,14 @@
module Command.Direct where
import Command
-import qualified Git
-import qualified Git.LsFiles
-import qualified Git.Branch
-import Config
-import Annex.Direct
-import Annex.Version
cmd :: Command
cmd = notBareRepo $ noDaemonRunning $
- command "direct" SectionSetup "switch repository to direct mode"
+ command "direct" SectionSetup "switch repository to direct mode (deprecated)"
paramNothing (withParams seek)
seek :: CmdParams -> CommandSeek
seek = withNothing (commandAction start)
start :: CommandStart
-start = ifM versionSupportsDirectMode
- ( ifM isDirect
- ( stop
- , starting "direct" (ActionItemOther Nothing)
- perform
- )
- , giveup "Direct mode is not supported by this repository version. Use git-annex unlock instead."
- )
-
-perform :: CommandPerform
-perform = do
- showOutput
- _ <- inRepo $ Git.Branch.commitCommand Git.Branch.ManualCommit
- [ Param "-a"
- , Param "-m"
- , Param "commit before switching to direct mode"
- ]
-
- top <- fromRepo Git.repoPath
- (l, clean) <- inRepo $ Git.LsFiles.inRepo [top]
- forM_ l go
- void $ liftIO clean
- next cleanup
- where
- go = whenAnnexed $ \f k -> do
- toDirectGen k f >>= \case
- Nothing -> noop
- Just a -> tryNonAsync a >>= \case
- Left e -> warnlocked f e
- Right _ -> return ()
- return Nothing
-
- warnlocked :: FilePath -> SomeException -> Annex ()
- warnlocked f e = do
- warning $ f ++ ": " ++ show e
- warning "leaving this file as-is; correct this problem and run git annex fsck on it"
-
-cleanup :: CommandCleanup
-cleanup = do
- setDirect True
- return True
+start = giveup "Direct mode is not supported by this repository version. Use git-annex unlock instead."
diff --git a/Command/EnableTor.hs b/Command/EnableTor.hs
index f05fcce..1807660 100644
--- a/Command/EnableTor.hs
+++ b/Command/EnableTor.hs
@@ -41,7 +41,11 @@ seek = withWords (commandAction . start)
-- This runs as root, so avoid making any commits or initializing
-- git-annex, or doing other things that create root-owned files.
start :: [String] -> CommandStart
+#ifndef mingw32_HOST_OS
start os = do
+#else
+start _os = do
+#endif
uuid <- getUUID
when (uuid == NoUUID) $
giveup "This can only be run in a git-annex repository."
diff --git a/Command/Fix.hs b/Command/Fix.hs
index 6432a46..c3f818b 100644
--- a/Command/Fix.hs
+++ b/Command/Fix.hs
@@ -12,7 +12,6 @@ module Command.Fix where
import Command
import Config
import qualified Annex
-import Annex.Version
import Annex.ReplaceFile
import Annex.Content
import Annex.Perms
@@ -25,19 +24,15 @@ import System.Posix.Files
#endif
cmd :: Command
-cmd = notDirect $ noCommit $ withGlobalOptions [annexedMatchingOptions] $
+cmd = noCommit $ withGlobalOptions [annexedMatchingOptions] $
command "fix" SectionMaintenance
"fix up links to annexed content"
paramPaths (withParams seek)
seek :: CmdParams -> CommandSeek
seek ps = unlessM crippledFileSystem $ do
- fixwhat <- ifM versionSupportsUnlockedPointers
- ( return FixAll
- , return FixSymlinks
- )
withFilesInGit
- (commandAction . (whenAnnexed $ start fixwhat))
+ (commandAction . (whenAnnexed $ start FixAll))
=<< workTreeItems ps
data FixWhat = FixSymlinks | FixAll
diff --git a/Command/FromKey.hs b/Command/FromKey.hs
index cc94912..7f1ef6f 100644
--- a/Command/FromKey.hs
+++ b/Command/FromKey.hs
@@ -19,7 +19,7 @@ import qualified Backend.URL
import Network.URI
cmd :: Command
-cmd = notDirect $ notBareRepo $ withGlobalOptions [jsonOptions] $
+cmd = notBareRepo $ withGlobalOptions [jsonOptions] $
command "fromkey" SectionPlumbing "adds a file using a specific key"
(paramRepeating (paramPair paramKey paramPath))
(seek <$$> optParser)
diff --git a/Command/Fsck.hs b/Command/Fsck.hs
index 5f5b873..bed59a5 100644
--- a/Command/Fsck.hs
+++ b/Command/Fsck.hs
@@ -15,8 +15,6 @@ import qualified Remote
import qualified Types.Backend
import qualified Backend
import Annex.Content
-import qualified Annex.Content.Direct as Direct
-import Annex.Direct
import Annex.Perms
import Annex.Link
import Logs.Location
@@ -28,7 +26,6 @@ import Annex.NumCopies
import Annex.UUID
import Annex.ReplaceFile
import Utility.DataUnits
-import Config
import Utility.HumanTime
import Utility.CopyFile
import Git.FilePath
@@ -225,16 +222,15 @@ fixLink key file = do
- in this repository only. -}
verifyLocationLog :: Key -> KeyStatus -> ActionItem -> Annex Bool
verifyLocationLog key keystatus ai = do
- direct <- isDirect
obj <- calcRepo $ gitAnnexLocation key
- present <- if not direct && isKeyUnlockedThin keystatus
+ present <- if isKeyUnlockedThin keystatus
then liftIO (doesFileExist obj)
else inAnnex key
u <- getUUID
{- Since we're checking that a key's object file is present, throw
- in a permission fixup here too. -}
- when (present && not direct) $ do
+ when present $ do
void $ tryIO $ case keystatus of
KeyUnlockedThin -> thawContent obj
KeyLockedThin -> thawContent obj
@@ -252,11 +248,7 @@ verifyLocationLog key keystatus ai = do
whenM (annexSecureHashesOnly <$> Annex.getGitConfig) $
warning $ "** Despite annex.securehashesonly being set, " ++ obj ++ " has content present in the annex using an insecure " ++ decodeBS (formatKeyVariety (keyVariety key)) ++ " key"
- {- In direct mode, modified files will show up as not present,
- - but that is expected and not something to do anything about. -}
- if direct && not present
- then return True
- else verifyLocationLog' key ai present u (logChange key u)
+ verifyLocationLog' key ai present u (logChange key u)
verifyLocationLogRemote :: Key -> ActionItem -> Remote -> Bool -> Annex Bool
verifyLocationLogRemote key ai remote present =
@@ -319,56 +311,38 @@ verifyRequiredContent _ _ = return True
{- Verifies the associated file records. -}
verifyAssociatedFiles :: Key -> KeyStatus -> FilePath -> Annex Bool
verifyAssociatedFiles key keystatus file = do
- ifM isDirect (godirect, goindirect)
- return True
- where
- godirect = do
- fs <- Direct.addAssociatedFile key file
- forM_ fs $ \f ->
- unlessM (liftIO $ doesFileExist f) $
- void $ Direct.removeAssociatedFile key f
- goindirect = when (isKeyUnlockedThin keystatus) $ do
+ when (isKeyUnlockedThin keystatus) $ do
f <- inRepo $ toTopFilePath file
afs <- Database.Keys.getAssociatedFiles key
unless (getTopFilePath f `elem` map getTopFilePath afs) $
Database.Keys.addAssociatedFile key f
+ return True
verifyWorkTree :: Key -> FilePath -> Annex Bool
verifyWorkTree key file = do
- ifM isDirect ( godirect, goindirect )
- return True
- where
- {- Ensures that files whose content is available are in direct mode. -}
- godirect = whenM (isJust <$> isAnnexLink file) $ do
- v <- toDirectGen key file
- case v of
- Nothing -> noop
- Just a -> do
- showNote "fixing direct mode"
- a
{- Make sure that a pointer file is replaced with its content,
- when the content is available. -}
- goindirect = do
- mk <- liftIO $ isPointerFile file
- case mk of
- Just k | k == key -> whenM (inAnnex key) $ do
- showNote "fixing worktree content"
- replaceFile file $ \tmp -> do
- mode <- liftIO $ catchMaybeIO $ fileMode <$> getFileStatus file
- ifM (annexThin <$> Annex.getGitConfig)
- ( void $ linkFromAnnex key tmp mode
- , do
- obj <- calcRepo $ gitAnnexLocation key
- void $ checkedCopyFile key obj tmp mode
- thawContent tmp
- )
- Database.Keys.storeInodeCaches key [file]
- _ -> return ()
+ mk <- liftIO $ isPointerFile file
+ case mk of
+ Just k | k == key -> whenM (inAnnex key) $ do
+ showNote "fixing worktree content"
+ replaceFile file $ \tmp -> do
+ mode <- liftIO $ catchMaybeIO $ fileMode <$> getFileStatus file
+ ifM (annexThin <$> Annex.getGitConfig)
+ ( void $ linkFromAnnex key tmp mode
+ , do
+ obj <- calcRepo $ gitAnnexLocation key
+ void $ checkedCopyFile key obj tmp mode
+ thawContent tmp
+ )
+ Database.Keys.storeInodeCaches key [file]
+ _ -> return ()
+ return True
{- The size of the data for a key is checked against the size encoded in
- the key's metadata, if available.
-
- - Not checked when a file is unlocked, or in direct mode.
+ - Not checked when a file is unlocked.
-}
checkKeySize :: Key -> KeyStatus -> ActionItem -> Annex Bool
checkKeySize _ KeyUnlockedThin _ = return True
@@ -439,28 +413,15 @@ checkKeyUpgrade _ _ _ (AssociatedFile Nothing) =
- thus when the user modifies the file, the object will be modified and
- not pass the check, and we don't want to find an error in this case.
- So, skip the check if the key is unlocked and modified.
- -
- - In direct mode this is not done if the file has clearly been modified,
- - because modification of direct mode files is allowed. It's still done
- - if the file does not appear modified, to catch disk corruption, etc.
-}
checkBackend :: Backend -> Key -> KeyStatus -> AssociatedFile -> Annex Bool
-checkBackend backend key keystatus afile = go =<< isDirect
- where
- go False = do
- content <- calcRepo $ gitAnnexLocation key
- ifM (pure (isKeyUnlockedThin keystatus) <&&> (not <$> isUnmodified key content))
- ( nocheck
- , checkBackendOr badContent backend key content ai
- )
- go True = case afile of
- AssociatedFile Nothing -> nocheck
- AssociatedFile (Just f) -> checkdirect f
- checkdirect file = ifM (Direct.goodContent key file)
- ( checkBackendOr' (badContentDirect file) backend key file ai
- (Direct.goodContent key file)
- , nocheck
+checkBackend backend key keystatus afile = do
+ content <- calcRepo $ gitAnnexLocation key
+ ifM (pure (isKeyUnlockedThin keystatus) <&&> (not <$> isUnmodified key content))
+ ( nocheck
+ , checkBackendOr badContent backend key content ai
)
+ where
nocheck = return True
ai = mkActionItem (key, afile)
@@ -475,7 +436,7 @@ checkBackendOr bad backend key file ai =
-- The postcheck action is run after the content is verified,
-- in order to detect situations where the file is changed while being
--- verified (particularly in direct mode).
+-- verified.
checkBackendOr' :: (Key -> Annex String) -> Backend -> Key -> FilePath -> ActionItem -> Annex Bool -> Annex Bool
checkBackendOr' bad backend key file ai postcheck =
case Types.Backend.verifyKeyContent backend of
@@ -546,14 +507,6 @@ badContent key = do
dest <- moveBad key
return $ "moved to " ++ dest
-{- Bad content is left where it is, but we touch the file, so it'll be
- - committed to a new key. -}
-badContentDirect :: FilePath -> Key -> Annex String
-badContentDirect file key = do
- void $ liftIO $ catchMaybeIO $ touchFile file
- logStatus key InfoMissing
- return "left in place for you to examine"
-
{- Bad content is dropped from the remote. We have downloaded a copy
- from the remote to a temp file already (in some cases, it's just a
- symlink to a file in the remote). To avoid any further data loss,
@@ -714,16 +667,13 @@ isKeyUnlockedThin KeyPresent = False
isKeyUnlockedThin KeyMissing = False
getKeyStatus :: Key -> Annex KeyStatus
-getKeyStatus key = ifM isDirect
- ( return KeyUnlockedThin
- , catchDefaultIO KeyMissing $ do
- afs <- not . null <$> Database.Keys.getAssociatedFiles key
- obj <- calcRepo $ gitAnnexLocation key
- multilink <- ((> 1) . linkCount <$> liftIO (getFileStatus obj))
- return $ if multilink && afs
- then KeyUnlockedThin
- else KeyPresent
- )
+getKeyStatus key = catchDefaultIO KeyMissing $ do
+ afs <- not . null <$> Database.Keys.getAssociatedFiles key
+ obj <- calcRepo $ gitAnnexLocation key
+ multilink <- ((> 1) . linkCount <$> liftIO (getFileStatus obj))
+ return $ if multilink && afs
+ then KeyUnlockedThin
+ else KeyPresent
getKeyFileStatus :: Key -> FilePath -> Annex KeyStatus
getKeyFileStatus key file = do
diff --git a/Command/FuzzTest.hs b/Command/FuzzTest.hs
index de872bc..5e08125 100644
--- a/Command/FuzzTest.hs
+++ b/Command/FuzzTest.hs
@@ -155,7 +155,6 @@ data FuzzAction
= FuzzAdd FuzzFile
| FuzzDelete FuzzFile
| FuzzMove FuzzFile FuzzFile
- | FuzzModify FuzzFile
| FuzzDeleteDir FuzzDir
| FuzzMoveDir FuzzDir FuzzDir
| FuzzPause Delay
@@ -166,7 +165,6 @@ instance Arbitrary FuzzAction where
[ (50, FuzzAdd <$> arbitrary)
, (50, FuzzDelete <$> arbitrary)
, (10, FuzzMove <$> arbitrary <*> arbitrary)
- , (10, FuzzModify <$> arbitrary)
, (10, FuzzDeleteDir <$> arbitrary)
, (10, FuzzMoveDir <$> arbitrary <*> arbitrary)
, (10, FuzzPause <$> arbitrary)
@@ -180,9 +178,6 @@ runFuzzAction (FuzzAdd (FuzzFile f)) = liftIO $ do
runFuzzAction (FuzzDelete (FuzzFile f)) = liftIO $ nukeFile f
runFuzzAction (FuzzMove (FuzzFile src) (FuzzFile dest)) = liftIO $
rename src dest
-runFuzzAction (FuzzModify (FuzzFile f)) = whenM isDirect $ liftIO $ do
- n <- getStdRandom random :: IO Int
- appendFile f $ show n ++ "\n"
runFuzzAction (FuzzDeleteDir (FuzzDir d)) = liftIO $
removeDirectoryRecursive d
runFuzzAction (FuzzMoveDir (FuzzDir src) (FuzzDir dest)) = liftIO $
@@ -216,9 +211,6 @@ genFuzzAction = do
FuzzDeleteDir _ -> do
d <- liftIO existingDir
maybe genFuzzAction (return . FuzzDeleteDir) d
- FuzzModify _ -> do
- f <- liftIO $ existingFile 0 ""
- maybe genFuzzAction (return . FuzzModify) f
FuzzPause _ -> return tmpl
existingFile :: Int -> FilePath -> IO (Maybe FuzzFile)
diff --git a/Command/Indirect.hs b/Command/Indirect.hs
index f1e4e65..fe5a929 100644
--- a/Command/Indirect.hs
+++ b/Command/Indirect.hs
@@ -8,89 +8,14 @@
module Command.Indirect where
import Command
-import qualified Git
-import qualified Git.Branch
-import qualified Git.LsFiles
-import Git.FileMode
-import Config
-import qualified Annex
-import Annex.Direct
-import Annex.Content
-import Annex.Content.Direct
-import Annex.CatFile
-import Annex.Init
-import Annex.Ingest
cmd :: Command
cmd = notBareRepo $ noDaemonRunning $
- command "indirect" SectionSetup "switch repository to indirect mode"
+ command "indirect" SectionSetup "switch repository to indirect mode (deprecated)"
paramNothing (withParams seek)
seek :: CmdParams -> CommandSeek
seek = withNothing (commandAction start)
start :: CommandStart
-start = ifM isDirect
- ( do
- unlessM (coreSymlinks <$> Annex.getGitConfig) $
- giveup "Git is configured to not use symlinks, so you must use direct mode."
- whenM probeCrippledFileSystem $
- giveup "This repository seems to be on a crippled filesystem, you must use direct mode."
- starting "indirect" (ActionItemOther Nothing)
- perform
- , stop
- )
-
-perform :: CommandPerform
-perform = do
- whenM stageDirect $ do
- showOutput
- void $ inRepo $ Git.Branch.commitCommand Git.Branch.ManualCommit
- [ Param "-m"
- , Param "commit before switching to indirect mode"
- ]
-
- -- Note that we set indirect mode early, so that we can use
- -- moveAnnex in indirect mode.
- setDirect False
-
- top <- fromRepo Git.repoPath
- (l, clean) <- inRepo $ Git.LsFiles.stagedOthersDetails [top]
- forM_ l go
- void $ liftIO clean
- next $ return True
- where
- {- Walk tree from top and move all present direct mode files into
- - the annex, replacing with symlinks. Also delete direct mode
- - caches and mappings. -}
- go (f, Just sha, Just mode) | isSymLink mode = do
- r <- liftIO $ catchMaybeIO $ getSymbolicLinkStatus f
- case r of
- Just s
- | isSymbolicLink s -> void $ flip whenAnnexed f $
- \_ k -> do
- removeInodeCache k
- removeAssociatedFiles k
- return Nothing
- | otherwise ->
- maybe noop (fromdirect f)
- =<< catKey sha
- _ -> noop
- go _ = noop
-
- fromdirect f k = do
- removeInodeCache k
- removeAssociatedFiles k
- whenM (liftIO $ not . isSymbolicLink <$> getSymbolicLinkStatus f) $ do
- v <- tryNonAsync (moveAnnex k f)
- case v of
- Right True -> do
- l <- calcRepo $ gitAnnexLink f k
- liftIO $ createSymbolicLink l f
- Right False -> warnlocked "Failed to move file to annex"
- Left e -> catchNonAsync (restoreFile f k e) $
- warnlocked . show
-
- warnlocked msg = do
- warning msg
- warning "leaving this file as-is; correct this problem and run git annex add on it"
+start = stop
diff --git a/Command/Info.hs b/Command/Info.hs
index c52b99d..23a8fc2 100644
--- a/Command/Info.hs
+++ b/Command/Info.hs
@@ -31,7 +31,6 @@ import Logs.Trust
import Logs.Location
import Annex.NumCopies
import Remote
-import Config
import Git.Config (boolConfig)
import qualified Git.LsTree as LsTree
import Utility.Percentage
@@ -132,6 +131,7 @@ start o ps = do
globalInfo :: InfoOptions -> Annex ()
globalInfo o = do
+ disallowMatchingOptions
u <- getUUID
whenM ((==) DeadTrusted <$> lookupTrust u) $
earlyWarning "Warning: This repository is currently marked as dead."
@@ -144,6 +144,7 @@ itemInfo :: InfoOptions -> String -> Annex ()
itemInfo o p = ifM (isdir p)
( dirInfo o p
, do
+ disallowMatchingOptions
v <- Remote.byName' p
case v of
Right r -> remoteInfo o r
@@ -164,6 +165,10 @@ noInfo s = do
showNote $ "not a directory or an annexed file or a treeish or a remote or a uuid"
showEndFail
+disallowMatchingOptions :: Annex ()
+disallowMatchingOptions = whenM Limit.limited $
+ giveup "File matching options can only be used when getting info on a directory."
+
dirInfo :: InfoOptions -> FilePath -> Annex ()
dirInfo o dir = showCustom (unwords ["info", dir]) $ do
stats <- selStats
@@ -221,8 +226,7 @@ selStats fast_stats slow_stats = do
-}
global_fast_stats :: [Stat]
global_fast_stats =
- [ repository_mode
- , repo_list Trusted
+ [ repo_list Trusted
, repo_list SemiTrusted
, repo_list UnTrusted
, transfer_list
@@ -267,7 +271,6 @@ file_stats f k =
remote_fast_stats :: Remote -> [Stat]
remote_fast_stats r = map (\s -> s r)
[ remote_name
- , remote_trust
, remote_cost
, remote_type
]
@@ -276,6 +279,7 @@ uuid_fast_stats :: UUID -> [Stat]
uuid_fast_stats u = map (\s -> s u)
[ repo_uuid
, repo_description
+ , repo_trust
]
uuid_slow_stats :: UUID -> [Stat]
@@ -310,16 +314,6 @@ showStat s = maybe noop calc =<< s
(lift . showHeader) desc
lift . showRaw =<< a
-repository_mode :: Stat
-repository_mode = simpleStat "repository mode" $ lift $
- ifM isDirect
- ( return "direct"
- , ifM (fromRepo Git.repoIsLocalBare)
- ( return "bare"
- , return "indirect"
- )
- )
-
repo_list :: TrustLevel -> Stat
repo_list level = stat n $ nojson $ lift $ do
us <- filter (/= NoUUID) . M.keys
@@ -353,9 +347,8 @@ repo_description = simpleStat "description" . lift . Remote.prettyUUID
repo_uuid :: UUID -> Stat
repo_uuid = simpleStat "uuid" . pure . fromUUID
-remote_trust :: Remote -> Stat
-remote_trust r = simpleStat "trust" $ lift $
- showTrustLevel <$> lookupTrust (Remote.uuid r)
+repo_trust :: UUID -> Stat
+repo_trust u = simpleStat "trust" $ lift $ showTrustLevel <$> lookupTrust u
remote_cost :: Remote -> Stat
remote_cost r = simpleStat "cost" $ pure $
@@ -525,7 +518,7 @@ cachedPresentData = do
case presentData s of
Just v -> return v
Nothing -> do
- v <- foldKeys <$> lift (getKeysPresent InRepository)
+ v <- foldKeys <$> lift (listKeys InAnnex)
put s { presentData = Just v }
return v
diff --git a/Command/Lock.hs b/Command/Lock.hs
index c42def8..2f2eab2 100644
--- a/Command/Lock.hs
+++ b/Command/Lock.hs
@@ -10,7 +10,6 @@ module Command.Lock where
import Command
import qualified Annex.Queue
import qualified Annex
-import Annex.Version
import Annex.Content
import Annex.Link
import Annex.InodeSentinal
@@ -23,7 +22,7 @@ import Logs.Location
import Git.FilePath
cmd :: Command
-cmd = notDirect $ withGlobalOptions [jsonOptions, annexedMatchingOptions] $
+cmd = withGlobalOptions [jsonOptions, annexedMatchingOptions] $
command "lock" SectionCommon
"undo unlock command"
paramPaths (withParams seek)
@@ -31,12 +30,7 @@ cmd = notDirect $ withGlobalOptions [jsonOptions, annexedMatchingOptions] $
seek :: CmdParams -> CommandSeek
seek ps = do
l <- workTreeItems ps
- ifM versionSupportsUnlockedPointers
- ( withFilesInGit (commandAction . (whenAnnexed startNew)) l
- , do
- withFilesOldUnlocked (commandAction . startOld) l
- withFilesOldUnlockedToBeCommitted (commandAction . startOld) l
- )
+ withFilesInGit (commandAction . (whenAnnexed startNew)) l
startNew :: FilePath -> Key -> CommandStart
startNew file key = ifM (isJust <$> isAnnexLink file)
diff --git a/Command/Migrate.hs b/Command/Migrate.hs
index 3bc7c08..ca656e0 100644
--- a/Command/Migrate.hs
+++ b/Command/Migrate.hs
@@ -20,7 +20,7 @@ import Logs.Web
import Utility.Metered
cmd :: Command
-cmd = notDirect $ withGlobalOptions [annexedMatchingOptions] $
+cmd = withGlobalOptions [annexedMatchingOptions] $
command "migrate" SectionUtility
"switch data to different backend"
paramPaths (withParams seek)
diff --git a/Command/Multicast.hs b/Command/Multicast.hs
index e34ef56..6c6d2c4 100644
--- a/Command/Multicast.hs
+++ b/Command/Multicast.hs
@@ -27,7 +27,6 @@ import Utility.Hash
import Utility.Tmp
import Utility.Tmp.Dir
import Utility.Process.Transcript
-import Config
import Data.Char
import qualified Data.ByteString.Lazy.UTF8 as B8
@@ -128,8 +127,6 @@ send ups fs = do
-- In a direct mode repository, the annex objects do not have
-- the names of keys, and would have to be copied, which is too
-- expensive.
- whenM isDirect $
- giveup "Sorry, multicast send cannot be done from a direct mode repository."
starting "sending files" (ActionItemOther Nothing) $
withTmpFile "send" $ \t h -> do
fs' <- seekHelper LsFiles.inRepo =<< workTreeItems fs
@@ -140,7 +137,7 @@ send ups fs = do
mk <- lookupFile f
case mk of
Nothing -> noop
- Just k -> withObjectLoc k (addlist f) (const noop)
+ Just k -> withObjectLoc k (addlist f)
liftIO $ hClose h
serverkey <- uftpKey
diff --git a/Command/PreCommit.hs b/Command/PreCommit.hs
index 56b3805..8c366ec 100644
--- a/Command/PreCommit.hs
+++ b/Command/PreCommit.hs
@@ -10,23 +10,17 @@
module Command.PreCommit where
import Command
-import Config
-import qualified Command.Add
import qualified Command.Fix
import qualified Command.Smudge
-import Annex.Direct
import Annex.Hook
import Annex.Link
import Annex.View
-import Annex.Version
import Annex.View.ViewedFile
import Annex.LockFile
import Logs.View
import Logs.MetaData
import Types.View
import Types.MetaData
-import qualified Git.Index as Git
-import qualified Git.LsFiles as Git
import qualified Data.Set as S
import qualified Data.Text as T
@@ -38,60 +32,25 @@ cmd = command "pre-commit" SectionPlumbing
(withParams seek)
seek :: CmdParams -> CommandSeek
-seek ps = lockPreCommitHook $ ifM isDirect
- ( do
- -- update direct mode mappings for committed files
- withWords (commandAction . startDirect) ps
- runAnnexHook preCommitAnnexHook
- , do
- ifM (not <$> versionSupportsUnlockedPointers <&&> liftIO Git.haveFalseIndex)
- ( do
- (fs, cleanup) <- inRepo $ Git.typeChangedStaged ps
- whenM (anyM isOldUnlocked fs) $
- giveup "Cannot make a partial commit with unlocked annexed files. You should `git annex add` the files you want to commit, and then run git commit."
- void $ liftIO cleanup
- , do
- l <- workTreeItems ps
- -- fix symlinks to files being committed
- flip withFilesToBeCommitted l $ \f -> commandAction $
- maybe stop (Command.Fix.start Command.Fix.FixSymlinks f)
- =<< isAnnexLink f
- ifM versionSupportsUnlockedPointers
- -- after a merge conflict or git
- -- cherry-pick or stash, pointer
- -- files in the worktree won't
- -- be populated, so populate them
- -- here
- ( Command.Smudge.updateSmudged
- -- When there's a false index,
- -- restaging the files won't work.
- . Restage =<< liftIO Git.haveFalseIndex
- -- inject unlocked files into the annex
- -- (not needed when repo version uses
- -- unlocked pointer files)
- , withFilesOldUnlockedToBeCommitted (commandAction . startInjectUnlocked) l
- )
- )
- runAnnexHook preCommitAnnexHook
- -- committing changes to a view updates metadata
- mv <- currentView
- case mv of
- Nothing -> noop
- Just v -> withViewChanges
- (addViewMetaData v)
- (removeViewMetaData v)
- )
+seek ps = lockPreCommitHook $ do
+ l <- workTreeItems ps
+ -- fix symlinks to files being committed
+ flip withFilesToBeCommitted l $ \f -> commandAction $
+ maybe stop (Command.Fix.start Command.Fix.FixSymlinks f)
+ =<< isAnnexLink f
+ -- after a merge conflict or git cherry-pick or stash, pointer
+ -- files in the worktree won't be populated, so populate them here
+ Command.Smudge.updateSmudged (Restage False)
+ runAnnexHook preCommitAnnexHook
-startInjectUnlocked :: FilePath -> CommandStart
-startInjectUnlocked f = startingCustomOutput (ActionItemOther Nothing) $ do
- unlessM (callCommandAction $ Command.Add.start f) $
- error $ "failed to add " ++ f ++ "; canceling commit"
- next $ return True
-
-startDirect :: [String] -> CommandStart
-startDirect _ = startingCustomOutput (ActionItemOther Nothing) $
- next preCommitDirect
+ -- committing changes to a view updates metadata
+ mv <- currentView
+ case mv of
+ Nothing -> noop
+ Just v -> withViewChanges
+ (addViewMetaData v)
+ (removeViewMetaData v)
addViewMetaData :: View -> ViewedFile -> Key -> CommandStart
addViewMetaData v f k = starting "metadata" (mkActionItem (k, f)) $
diff --git a/Command/Proxy.hs b/Command/Proxy.hs
index 7c042c2..4ccab2f 100644
--- a/Command/Proxy.hs
+++ b/Command/Proxy.hs
@@ -8,23 +8,11 @@
module Command.Proxy where
import Command
-import Config
-import Utility.Tmp.Dir
-import Utility.Env
-import Annex.Direct
-import Annex.Tmp
-import qualified Git
-import qualified Git.Sha
-import qualified Git.Ref
-import qualified Git.Branch
-import qualified Git.LsFiles
-import Git.FilePath
-import Utility.CopyFile
cmd :: Command
cmd = notBareRepo $
command "proxy" SectionPlumbing
- "safely bypass direct mode guard"
+ "safely bypass direct mode guard (deprecated)"
("-- git command") (withParams seek)
seek :: CmdParams -> CommandSeek
@@ -32,48 +20,4 @@ seek = withWords (commandAction . start)
start :: [String] -> CommandStart
start [] = giveup "Did not specify command to run."
-start (c:ps) = liftIO . exitWith =<< ifM isDirect
- ( withOtherTmp $ \tmp -> withTmpDirIn tmp "proxy" go
- , liftIO $ safeSystem c (map Param ps)
- )
- where
- go tmp = do
- oldref <- fromMaybe Git.Sha.emptyTree
- <$> (inRepo . maybe Git.Ref.headSha Git.Ref.sha
- =<< inRepo Git.Branch.currentUnsafe)
-
- exitcode <- proxy tmp
-
- cleanupproxy tmp oldref
-
- return exitcode
-
- proxy tmp = do
- usetmp <- liftIO $ Just . addEntry "GIT_WORK_TREE" tmp <$> getEnvironment
-
- -- Set up the tmp work tree, to contain both a checkout of all
- -- staged files as well as hard links (or copies) of any
- -- unstaged files.
- unlessM (isNothing <$> inRepo Git.Branch.current) $
- unlessM (liftIO $ boolSystemEnv "git" [Param "checkout", Param "--", Param "."] usetmp) $
- error "Failed to set up proxy work tree."
- top <- fromRepo Git.repoPath
- (fs, cleanup) <- inRepo $ Git.LsFiles.notInRepo True [top]
- forM_ fs $ \f -> do
- tf <- inRepo $ toTopFilePath f
- let tmpf = tmp </> getTopFilePath tf
- liftIO $ do
- createDirectoryIfMissing True (takeDirectory tmpf)
- createLinkOrCopy f tmpf
- liftIO $ void cleanup
-
- liftIO $ safeSystemEnv c (map Param ps) usetmp
-
- -- To merge the changes made by the proxied command into
- -- the work tree is similar to cleaning up after a
- -- direct mode merge. But, here we force updates of any
- -- non-annxed files that were changed by the proxied
- -- command.
- cleanupproxy tmp oldref = do
- updateWorkTree tmp oldref True
- liftIO $ removeDirectoryRecursive tmp
+start (c:ps) = liftIO $ exitWith =<< safeSystem c (map Param ps)
diff --git a/Command/ReKey.hs b/Command/ReKey.hs
index fd543fd..6670298 100644
--- a/Command/ReKey.hs
+++ b/Command/ReKey.hs
@@ -21,11 +21,10 @@ import Annex.InodeSentinal
import Utility.InodeCache
cmd :: Command
-cmd = notDirect $
- command "rekey" SectionPlumbing
- "change keys used for files"
- (paramRepeating $ paramPair paramPath paramKey)
- (seek <$$> optParser)
+cmd = command "rekey" SectionPlumbing
+ "change keys used for files"
+ (paramRepeating $ paramPair paramPath paramKey)
+ (seek <$$> optParser)
data ReKeyOptions = ReKeyOptions
{ reKeyThese :: CmdParams
diff --git a/Command/RegisterUrl.hs b/Command/RegisterUrl.hs
index c9d72ee..d13889a 100644
--- a/Command/RegisterUrl.hs
+++ b/Command/RegisterUrl.hs
@@ -15,7 +15,7 @@ import Command.FromKey (mkKey)
import qualified Remote
cmd :: Command
-cmd = notDirect $ notBareRepo $
+cmd = notBareRepo $
command "registerurl"
SectionPlumbing "registers an url for a key"
(paramPair paramKey paramUrl)
diff --git a/Command/Status.hs b/Command/Status.hs
index d667342..e9c2b35 100644
--- a/Command/Status.hs
+++ b/Command/Status.hs
@@ -8,11 +8,7 @@
module Command.Status where
import Command
-import Annex.CatFile
-import Annex.Content.Direct
-import Config
import Git.Status
-import qualified Git.Ref
import Git.FilePath
cmd :: Command
@@ -42,10 +38,7 @@ seek o = withWords (commandAction . start o) (statusFiles o)
start :: StatusOptions -> [FilePath] -> CommandStart
start o locs = do
(l, cleanup) <- inRepo $ getStatus ps locs
- getstatus <- ifM isDirect
- ( return (maybe (pure Nothing) statusDirect . simplifiedStatus)
- , return (pure . simplifiedStatus)
- )
+ let getstatus = pure . simplifiedStatus
forM_ l $ \s -> maybe noop displayStatus =<< getstatus s
ifM (liftIO cleanup)
( stop
@@ -71,38 +64,3 @@ displayStatus s = do
f <- liftIO $ relPathCwdToFile absf
unlessM (showFullJSON $ JSONChunk [("status", [c]), ("file", f)]) $
liftIO $ putStrLn $ [c] ++ " " ++ f
-
--- Git thinks that present direct mode files are typechanged.
--- (On crippled filesystems, git instead thinks they're modified.)
--- Check their content to see if they are modified or not.
-statusDirect :: Status -> Annex (Maybe Status)
-statusDirect (TypeChanged t) = statusDirect' t
-statusDirect s@(Modified t) = ifM crippledFileSystem
- ( statusDirect' t
- , pure (Just s)
- )
-statusDirect s = pure (Just s)
-
-statusDirect' :: TopFilePath -> Annex (Maybe Status)
-statusDirect' t = do
- absf <- fromRepo $ fromTopFilePath t
- f <- liftIO $ relPathCwdToFile absf
- v <- liftIO (catchMaybeIO $ getFileStatus f)
- case v of
- Nothing -> return $ Just $ Deleted t
- Just s
- | not (isSymbolicLink s) ->
- checkkey f s =<< catKeyFile f
- | otherwise -> Just <$> checkNew f t
- where
- checkkey f s (Just k) = ifM (sameFileStatus k f s)
- ( return Nothing
- , return $ Just $ Modified t
- )
- checkkey f _ Nothing = Just <$> checkNew f t
-
-checkNew :: FilePath -> TopFilePath -> Annex Status
-checkNew f t = ifM (isJust <$> catObjectDetails (Git.Ref.fileRef f))
- ( return (Modified t)
- , return (Untracked t)
- )
diff --git a/Command/Sync.hs b/Command/Sync.hs
index 94d34fe..d35986c 100644
--- a/Command/Sync.hs
+++ b/Command/Sync.hs
@@ -30,7 +30,6 @@ import qualified Annex
import qualified Annex.Branch
import qualified Remote
import qualified Types.Remote as Remote
-import Annex.Direct
import Annex.Hook
import qualified Git.Command
import qualified Git.LsFiles as LsFiles
@@ -250,7 +249,7 @@ merge currbranch mergeconfig resolvemergeoverride commitmode tomerge = case curr
ResolveMergeOverride False -> return False
syncBranch :: Git.Branch -> Git.Branch
-syncBranch = Git.Ref.underBase "refs/heads/synced" . fromDirectBranch . fromAdjustedBranch
+syncBranch = Git.Ref.underBase "refs/heads/synced" . fromAdjustedBranch
remoteBranch :: Remote -> Git.Ref -> Git.Ref
remoteBranch remote = Git.Ref.underBase $ "refs/remotes/" ++ Remote.name remote
@@ -286,20 +285,14 @@ commit :: SyncOptions -> CommandStart
commit o = stopUnless shouldcommit $ starting "commit" (ActionItemOther Nothing) $ do
commitmessage <- maybe commitMsg return (messageOption o)
Annex.Branch.commit =<< Annex.Branch.commitMessage
- next $ ifM isDirect
- ( do
- void stageDirect
- void preCommitDirect
- commitStaged Git.Branch.ManualCommit commitmessage
- , do
- showOutput
- void $ inRepo $ Git.Branch.commitCommand Git.Branch.ManualCommit
- [ Param "-a"
- , Param "-m"
- , Param commitmessage
- ]
- return True
- )
+ next $ do
+ showOutput
+ void $ inRepo $ Git.Branch.commitCommand Git.Branch.ManualCommit
+ [ Param "-a"
+ , Param "-m"
+ , Param commitmessage
+ ]
+ return True
where
shouldcommit = pure (commitOption o)
<||> (pure (not (noCommitOption o)) <&&> getGitConfigVal annexAutoCommit)
@@ -378,12 +371,6 @@ updateBranches (Just branch, madj) = do
-- Update the sync branch to match the new state of the branch
inRepo $ updateBranch (syncBranch branch) branch
- -- In direct mode, we're operating on some special direct mode
- -- branch, rather than the intended branch, so update the intended
- -- branch.
- whenM isDirect $
- inRepo $ updateBranch (fromDirectBranch branch) branch
-
updateBranch :: Git.Branch -> Git.Branch -> Git.Repo -> IO ()
updateBranch syncbranch updateto g =
unlessM go $ giveup $ "failed to update " ++ Git.fromRef syncbranch
@@ -449,7 +436,7 @@ mergeRemote remote currbranch mergeconfig resolvemergeoverride = ifM isBareRepo
(mapM (merge currbranch mergeconfig resolvemergeoverride Git.Branch.ManualCommit . remoteBranch remote) =<< getlist)
tomerge = filterM (changed remote)
branchlist Nothing = []
- branchlist (Just branch) = [fromDirectBranch (fromAdjustedBranch branch), syncBranch branch]
+ branchlist (Just branch) = [fromAdjustedBranch branch, syncBranch branch]
pushRemote :: SyncOptions -> Remote -> CurrBranch -> CommandStart
pushRemote _o _remote (Nothing, _) = stop
@@ -471,8 +458,9 @@ pushRemote o remote (Just branch, _) = stopUnless (pure (pushOption o) <&&> need
| remoteAnnexReadOnly gc = return False
| not (remoteAnnexPush gc) = return False
| otherwise = anyM (newer remote) [syncBranch branch, Annex.Branch.name]
- -- Do updateInstead emulation for remotes on eg removable drives
- -- formatted FAT, where the post-receive hook won't run.
+ -- Older remotes on crippled filesystems may not have a
+ -- post-receive hook set up, so when updateInstead emulation
+ -- is needed, run post-receive manually.
postpushupdate repo = case Git.repoWorkTree repo of
Nothing -> return True
Just wt -> ifM needemulation
@@ -540,7 +528,7 @@ pushBranch remote branch g = directpush `after` annexpush `after` syncpush
-- receive.denyCurrentBranch=updateInstead -- the user
-- will want to see that one.
let p = flip Git.Command.gitCreateProcess g $ pushparams
- [ Git.fromRef $ Git.Ref.base $ fromDirectBranch $ fromAdjustedBranch branch ]
+ [ Git.fromRef $ Git.Ref.base $ fromAdjustedBranch branch ]
(transcript, ok) <- processTranscript' p Nothing
when (not ok && not ("denyCurrentBranch" `isInfixOf` transcript)) $
hPutStr stderr transcript
diff --git a/Command/Unannex.hs b/Command/Unannex.hs
index 362a92e..cbb8cb5 100644
--- a/Command/Unannex.hs
+++ b/Command/Unannex.hs
@@ -8,18 +8,11 @@
module Command.Unannex where
import Command
-import Config
import qualified Annex
import Annex.Content
import Annex.Perms
-import Annex.Content.Direct
-import Annex.Version
import qualified Git.Command
-import qualified Git.Branch
-import qualified Git.Ref
-import qualified Git.DiffTree as DiffTree
import Utility.CopyFile
-import Command.PreCommit (lockPreCommitHook)
import qualified Database.Keys
import Git.FilePath
@@ -30,51 +23,15 @@ cmd = withGlobalOptions [annexedMatchingOptions] $
paramPaths (withParams seek)
seek :: CmdParams -> CommandSeek
-seek ps = wrapUnannex $
- (withFilesInGit $ commandAction . whenAnnexed start) =<< workTreeItems ps
-
-wrapUnannex :: Annex a -> Annex a
-wrapUnannex a = ifM (versionSupportsUnlockedPointers <||> isDirect)
- ( a
- {- Run with the pre-commit hook disabled, to avoid confusing
- - behavior if an unannexed file is added back to git as
- - a normal, non-annexed file and then committed.
- - Otherwise, the pre-commit hook would think that the file
- - has been unlocked and needs to be re-annexed.
- -
- - At the end, make a commit removing the unannexed files.
- -}
- , ifM cleanindex
- ( lockPreCommitHook $ commit `after` a
- , giveup "Cannot proceed with uncommitted changes staged in the index. Recommend you: git commit"
- )
- )
- where
- commit = inRepo $ Git.Branch.commitCommand Git.Branch.ManualCommit
- [ Param "-q"
- , Param "--allow-empty"
- , Param "--no-verify"
- , Param "-m", Param "content removed from git annex"
- ]
- cleanindex = ifM (inRepo Git.Ref.headExists)
- ( do
- (diff, cleanup) <- inRepo $ DiffTree.diffIndex Git.Ref.headRef
- if null diff
- then void (liftIO cleanup) >> return True
- else void (liftIO cleanup) >> return False
- , return False
- )
+seek ps = (withFilesInGit $ commandAction . whenAnnexed start) =<< workTreeItems ps
start :: FilePath -> Key -> CommandStart
start file key = stopUnless (inAnnex key) $
starting "unannex" (mkActionItem (key, file)) $
- ifM isDirect
- ( performDirect file key
- , performIndirect file key
- )
+ perform file key
-performIndirect :: FilePath -> Key -> CommandPerform
-performIndirect file key = do
+perform :: FilePath -> Key -> CommandPerform
+perform file key = do
liftIO $ removeFile file
inRepo $ Git.Command.run
[ Param "rm"
@@ -84,10 +41,10 @@ performIndirect file key = do
, Param "--"
, File file
]
- next $ cleanupIndirect file key
+ next $ cleanup file key
-cleanupIndirect :: FilePath -> Key -> CommandCleanup
-cleanupIndirect file key = do
+cleanup :: FilePath -> Key -> CommandCleanup
+cleanup file key = do
Database.Keys.removeAssociatedFile key =<< inRepo (toTopFilePath file)
src <- calcRepo $ gitAnnexLocation key
ifM (Annex.getState Annex.fast)
@@ -112,28 +69,3 @@ cleanupIndirect file key = do
( return True
, copyfrom src
)
-
-performDirect :: FilePath -> Key -> CommandPerform
-performDirect file key = do
- -- --force is needed when the file is not committed
- inRepo $ Git.Command.run
- [ Param "rm"
- , Param "--cached"
- , Param "--force"
- , Param "--quiet"
- , Param "--"
- , File file
- ]
- next $ cleanupDirect file key
-
-{- The direct mode file is not touched during unannex, so the content
- - is already where it needs to be, so this does not need to do anything
- - except remove it from the associated file map (which also updates
- - the location log if this was the last copy), and, if this was the last
- - associated file, remove the inode cache. -}
-cleanupDirect :: FilePath -> Key -> CommandCleanup
-cleanupDirect file key = do
- fs <- removeAssociatedFile key file
- when (null fs) $
- removeInodeCache key
- return True
diff --git a/Command/Undo.hs b/Command/Undo.hs
index 0daa37e..8a19393 100644
--- a/Command/Undo.hs
+++ b/Command/Undo.hs
@@ -8,9 +8,6 @@
module Command.Undo where
import Command
-import Config
-import Annex.Direct
-import Annex.CatFile
import Git.DiffTree
import Git.FilePath
import Git.UpdateIndex
@@ -37,9 +34,7 @@ seek ps = do
-- Committing staged changes before undo allows later
-- undoing the undo. It would be nicer to only commit staged
- -- changes to the specified files, rather than all staged changes,
- -- but that is difficult to do; a partial git-commit can't be done
- -- in direct mode.
+ -- changes to the specified files, rather than all staged changes.
void $ Command.Sync.commitStaged Git.Branch.ManualCommit
"commit before undo"
@@ -68,16 +63,10 @@ perform p = do
forM_ removals $ \di -> do
f <- mkrel di
- whenM isDirect $
- maybe noop (`removeDirect` f)
- =<< catKey (srcsha di)
liftIO $ nukeFile f
forM_ adds $ \di -> do
f <- mkrel di
inRepo $ Git.run [Param "checkout", Param "--", File f]
- whenM isDirect $
- maybe noop (`toDirect` f)
- =<< catKey (dstsha di)
next $ liftIO cleanup
diff --git a/Command/Uninit.hs b/Command/Uninit.hs
index 0f61e08..3f2a45c 100644
--- a/Command/Uninit.hs
+++ b/Command/Uninit.hs
@@ -59,7 +59,7 @@ finish :: Annex ()
finish = do
annexdir <- fromRepo gitAnnexDir
annexobjectdir <- fromRepo gitAnnexObjectDir
- leftovers <- removeUnannexed =<< getKeysPresent InAnnex
+ leftovers <- removeUnannexed =<< listKeys InAnnex
prepareRemoveAnnexDir annexdir
if null leftovers
then liftIO $ removeDirectoryRecursive annexdir
diff --git a/Command/Unlock.hs b/Command/Unlock.hs
index 579e71c..2fc605c 100644
--- a/Command/Unlock.hs
+++ b/Command/Unlock.hs
@@ -10,11 +10,8 @@ module Command.Unlock where
import Command
import Annex.Content
import Annex.Perms
-import Annex.CatFile
-import Annex.Version
import Annex.Link
import Annex.ReplaceFile
-import Utility.CopyFile
import Git.FilePath
import qualified Database.Keys
@@ -25,9 +22,8 @@ editcmd :: Command
editcmd = mkcmd "edit" "same as unlock"
mkcmd :: String -> String -> Command
-mkcmd n d = notDirect $
- withGlobalOptions [jsonOptions, annexedMatchingOptions] $
- command n SectionCommon d paramPaths (withParams seek)
+mkcmd n d = withGlobalOptions [jsonOptions, annexedMatchingOptions] $
+ command n SectionCommon d paramPaths (withParams seek)
seek :: CmdParams -> CommandSeek
seek ps = withFilesInGit (commandAction . whenAnnexed start) =<< workTreeItems ps
@@ -38,15 +34,12 @@ seek ps = withFilesInGit (commandAction . whenAnnexed start) =<< workTreeItems p
start :: FilePath -> Key -> CommandStart
start file key = ifM (isJust <$> isAnnexLink file)
( starting "unlock" (mkActionItem (key, AssociatedFile (Just file))) $
- ifM versionSupportsUnlockedPointers
- ( performNew file key
- , performOld file key
- )
+ perform file key
, stop
)
-performNew :: FilePath -> Key -> CommandPerform
-performNew dest key = do
+perform :: FilePath -> Key -> CommandPerform
+perform dest key = do
destmode <- liftIO $ catchMaybeIO $ fileMode <$> getFileStatus dest
replaceFile dest $ \tmp ->
ifM (inAnnex key)
@@ -58,47 +51,10 @@ performNew dest key = do
LinkAnnexFailed -> error "unlock failed"
, liftIO $ writePointerFile tmp key destmode
)
- next $ cleanupNew dest key destmode
+ next $ cleanup dest key destmode
-cleanupNew :: FilePath -> Key -> Maybe FileMode -> CommandCleanup
-cleanupNew dest key destmode = do
+cleanup :: FilePath -> Key -> Maybe FileMode -> CommandCleanup
+cleanup dest key destmode = do
stagePointerFile dest destmode =<< hashPointerFile key
Database.Keys.addAssociatedFile key =<< inRepo (toTopFilePath dest)
return True
-
-performOld :: FilePath -> Key -> CommandPerform
-performOld file key =
- ifM (inAnnex key)
- ( ifM (isJust <$> catKeyFileHEAD file)
- ( performOld' file key
- , do
- warning "this has not yet been committed to git; cannot unlock it"
- next $ return False
- )
- , do
- warning "content not present; cannot unlock"
- next $ return False
- )
-
-performOld' :: FilePath -> Key -> CommandPerform
-performOld' dest key = ifM (checkDiskSpace Nothing key 0 True)
- ( do
- src <- calcRepo $ gitAnnexLocation key
- tmpdest <- fromRepo $ gitAnnexTmpObjectLocation key
- liftIO $ createDirectoryIfMissing True (parentDir tmpdest)
- showAction "copying"
- ifM (liftIO $ copyFileExternal CopyAllMetaData src tmpdest)
- ( do
- liftIO $ do
- removeFile dest
- moveFile tmpdest dest
- thawContent dest
- next $ return True
- , do
- warning "copy failed!"
- next $ return False
- )
- , do
- warning "not enough disk space to copy file"
- next $ return False
- )
diff --git a/Command/Unused.hs b/Command/Unused.hs
index ca6fb01..95f9533 100644
--- a/Command/Unused.hs
+++ b/Command/Unused.hs
@@ -84,9 +84,7 @@ checkUnused refspec = chain 0
return []
findunused False = do
showAction "checking for unused data"
- -- InAnnex, not InRepository because if a direct mode
- -- file exists, it is obviously not unused.
- excludeReferenced refspec =<< getKeysPresent InAnnex
+ excludeReferenced refspec =<< listKeys InAnnex
chain _ [] = next $ return True
chain v (a:as) = do
v' <- a v
diff --git a/Command/Upgrade.hs b/Command/Upgrade.hs
index 00e972a..ead0c4b 100644
--- a/Command/Upgrade.hs
+++ b/Command/Upgrade.hs
@@ -13,9 +13,13 @@ import Annex.Version
import Annex.Init
cmd :: Command
-cmd = dontCheck repoExists $ -- because an old version may not seem to exist
- noDaemonRunning $ -- avoid upgrading repo out from under daemon
- command "upgrade" SectionMaintenance "upgrade repository layout"
+cmd = dontCheck repoExists $
+ -- ^ because an old version may not seem to exist
+ -- and also, this avoids automatic silent upgrades before
+ -- this command can start up.
+ noDaemonRunning $
+ -- ^ avoid upgrading repo out from under daemon
+ command "upgrade" SectionMaintenance "upgrade repository"
paramNothing (withParams seek)
seek :: CmdParams -> CommandSeek
diff --git a/Command/VAdd.hs b/Command/VAdd.hs
index c18e542..d758374 100644
--- a/Command/VAdd.hs
+++ b/Command/VAdd.hs
@@ -12,7 +12,7 @@ import Annex.View
import Command.View (checkoutViewBranch)
cmd :: Command
-cmd = notBareRepo $ notDirect $
+cmd = notBareRepo $
command "vadd" SectionMetaData
"add subdirs to current view"
(paramRepeating "FIELD=GLOB")
diff --git a/Command/VCycle.hs b/Command/VCycle.hs
index 93627f2..b34c436 100644
--- a/Command/VCycle.hs
+++ b/Command/VCycle.hs
@@ -14,7 +14,7 @@ import Logs.View
import Command.View (checkoutViewBranch)
cmd :: Command
-cmd = notBareRepo $ notDirect $
+cmd = notBareRepo $
command "vcycle" SectionMetaData
"switch view to next layout"
paramNothing (withParams seek)
diff --git a/Command/VFilter.hs b/Command/VFilter.hs
index 74eb55e..62c44e0 100644
--- a/Command/VFilter.hs
+++ b/Command/VFilter.hs
@@ -12,7 +12,7 @@ import Annex.View
import Command.View (paramView, checkoutViewBranch)
cmd :: Command
-cmd = notBareRepo $ notDirect $
+cmd = notBareRepo $
command "vfilter" SectionMetaData "filter current view"
paramView (withParams seek)
diff --git a/Command/VPop.hs b/Command/VPop.hs
index 05ddfa3..2bf1706 100644
--- a/Command/VPop.hs
+++ b/Command/VPop.hs
@@ -16,7 +16,7 @@ import Logs.View
import Command.View (checkoutViewBranch)
cmd :: Command
-cmd = notBareRepo $ notDirect $
+cmd = notBareRepo $
command "vpop" SectionMetaData "switch back to previous view"
paramNumber (withParams seek)
diff --git a/Command/View.hs b/Command/View.hs
index 7c10ab1..88b9a48 100644
--- a/Command/View.hs
+++ b/Command/View.hs
@@ -20,7 +20,7 @@ import Annex.View
import Logs.View
cmd :: Command
-cmd = notBareRepo $ notDirect $
+cmd = notBareRepo $
command "view" SectionMetaData "enter a view branch"
paramView (withParams seek)
diff --git a/Database/Keys.hs b/Database/Keys.hs
index 7793136..e60724c 100644
--- a/Database/Keys.hs
+++ b/Database/Keys.hs
@@ -29,7 +29,6 @@ import qualified Database.Queue as H
import Database.Init
import Annex.Locations
import Annex.Common hiding (delete)
-import Annex.Version (versionUsesKeysDatabase)
import qualified Annex
import Annex.LockFile
import Annex.CatFile
@@ -103,10 +102,7 @@ getDbHandle = go =<< Annex.getState Annex.keysdbhandle
where
go (Just h) = pure h
go Nothing = do
- h <- ifM versionUsesKeysDatabase
- ( liftIO newDbHandle
- , liftIO unavailableDbHandle
- )
+ h <- liftIO newDbHandle
Annex.changeState $ \s -> s { Annex.keysdbhandle = Just h }
return h
@@ -220,7 +216,7 @@ removeInodeCaches = runWriterIO . SQL.removeInodeCaches . toIKey
- file.
-}
reconcileStaged :: H.DbQueue -> Annex ()
-reconcileStaged qh = whenM versionUsesKeysDatabase $ do
+reconcileStaged qh = do
gitindex <- inRepo currentIndexFile
indexcache <- fromRepo gitAnnexKeysDbIndexCache
withTSDelta (liftIO . genInodeCache gitindex) >>= \case
diff --git a/Git/Branch.hs b/Git/Branch.hs
index 9fc4f09..2de6f9e 100644
--- a/Git/Branch.hs
+++ b/Git/Branch.hs
@@ -15,7 +15,6 @@ import Git.Sha
import Git.Command
import qualified Git.Config
import qualified Git.Ref
-import qualified Git.BuildVersion
{- The currently checked out branch.
-
@@ -125,8 +124,7 @@ data CommitMode = ManualCommit | AutomaticCommit
{- Prevent signing automatic commits. -}
applyCommitMode :: CommitMode -> [CommandParam] -> [CommandParam]
applyCommitMode commitmode ps
- | commitmode == AutomaticCommit && not (Git.BuildVersion.older "2.0.0") =
- Param "--no-gpg-sign" : ps
+ | commitmode == AutomaticCommit = Param "--no-gpg-sign" : ps
| otherwise = ps
{- Some versions of git commit-tree honor commit.gpgsign themselves,
diff --git a/Git/CheckAttr.hs b/Git/CheckAttr.hs
index cfac5b1..defa675 100644
--- a/Git/CheckAttr.hs
+++ b/Git/CheckAttr.hs
@@ -10,12 +10,11 @@ module Git.CheckAttr where
import Common
import Git
import Git.Command
-import qualified Git.Version
import qualified Utility.CoProcess as CoProcess
import System.IO.Error
-type CheckAttrHandle = (CoProcess.CoProcessHandle, [Attr], Bool, String)
+type CheckAttrHandle = (CoProcess.CoProcessHandle, [Attr], String)
type Attr = String
@@ -25,8 +24,7 @@ checkAttrStart :: [Attr] -> Repo -> IO CheckAttrHandle
checkAttrStart attrs repo = do
currdir <- getCurrentDirectory
h <- gitCoProcessStart True params repo
- oldgit <- Git.Version.older "1.7.7"
- return (h, attrs, oldgit, currdir)
+ return (h, attrs, currdir)
where
params =
[ Param "check-attr"
@@ -36,12 +34,12 @@ checkAttrStart attrs repo = do
[ Param "--" ]
checkAttrStop :: CheckAttrHandle -> IO ()
-checkAttrStop (h, _, _, _) = CoProcess.stop h
+checkAttrStop (h, _, _) = CoProcess.stop h
{- Gets an attribute of a file. When the attribute is not specified,
- returns "" -}
checkAttr :: CheckAttrHandle -> Attr -> FilePath -> IO String
-checkAttr (h, attrs, oldgit, currdir) want file = do
+checkAttr (h, attrs, currdir) want file = do
pairs <- CoProcess.query h send (receive "")
let vals = map snd $ filter (\(attr, _) -> attr == want) pairs
case vals of
@@ -78,16 +76,9 @@ checkAttr (h, attrs, oldgit, currdir) want file = do
else Nothing -- line incomplete
numattrs = length attrs
- {- Before git 1.7.7, git check-attr worked best with
- - absolute filenames; using them worked around some bugs
- - with relative filenames.
- -
- - With newer git, git check-attr chokes on some absolute
- - filenames, and the bugs that necessitated them were fixed,
- - so use relative filenames. -}
- file'
- | oldgit = absPathFrom currdir file
- | otherwise = relPathDirToFileAbs currdir $ absPathFrom currdir file
+ {- git check-attr chokes on some absolute filenames,
+ - so make sure the filename is relative. -}
+ file' = relPathDirToFileAbs currdir $ absPathFrom currdir file
oldattrvalue attr l = end bits !! 0
where
bits = split sep l
diff --git a/Git/CheckIgnore.hs b/Git/CheckIgnore.hs
index 3ecbd93..67eef7a 100644
--- a/Git/CheckIgnore.hs
+++ b/Git/CheckIgnore.hs
@@ -15,7 +15,6 @@ module Git.CheckIgnore (
import Common
import Git
import Git.Command
-import qualified Git.Version
import qualified Utility.CoProcess as CoProcess
import System.IO.Error
@@ -29,17 +28,11 @@ type CheckIgnoreHandle = CoProcess.CoProcessHandle
- GIT_FLUSH behavior flushing the output buffer when git check-ignore
- is piping to us.
-
- - The first version of git to support what we need is 1.8.4.
- - Nothing is returned if an older git is installed.
- -
- check-ignore does not support --literal-pathspecs, so remove that
- from the gitGlobalOpts if set.
-}
-checkIgnoreStart :: Repo -> IO (Maybe CheckIgnoreHandle)
-checkIgnoreStart repo = ifM supportedGitVersion
- ( Just <$> gitCoProcessStart True params repo'
- , return Nothing
- )
+checkIgnoreStart :: Repo -> IO CheckIgnoreHandle
+checkIgnoreStart repo = gitCoProcessStart True params repo'
where
params =
[ Param "check-ignore"
@@ -52,11 +45,6 @@ checkIgnoreStart repo = ifM supportedGitVersion
pathspecs (Param "--literal-pathspecs") = True
pathspecs _ = False
-supportedGitVersion :: IO Bool
-supportedGitVersion = do
- v <- Git.Version.installed
- return $ v >= Git.Version.normalize "1.8.4"
-
{- For some reason, check-ignore --batch always exits nonzero,
- so ignore any error. -}
checkIgnoreStop :: CheckIgnoreHandle -> IO ()
diff --git a/Git/Fsck.hs b/Git/Fsck.hs
index 9897c54..6f33e11 100644
--- a/Git/Fsck.hs
+++ b/Git/Fsck.hs
@@ -22,7 +22,6 @@ import Git
import Git.Command
import Git.Sha
import Utility.Batch
-import qualified Git.Version
import qualified Data.Set as S
import Control.Concurrent.Async
@@ -73,9 +72,7 @@ instance Monoid FsckOutput where
-}
findBroken :: Bool -> Repo -> IO FsckResults
findBroken batchmode r = do
- supportsNoDangling <- (>= Git.Version.normalize "1.7.10")
- <$> Git.Version.installed
- let (command, params) = ("git", fsckParams supportsNoDangling r)
+ let (command, params) = ("git", fsckParams r)
(command', params') <- if batchmode
then toBatchCommand (command, params)
else return (command, params)
@@ -86,8 +83,8 @@ findBroken batchmode r = do
, std_err = CreatePipe
}
(o1, o2) <- concurrently
- (parseFsckOutput maxobjs r supportsNoDangling (stdoutHandle p))
- (parseFsckOutput maxobjs r supportsNoDangling (stderrHandle p))
+ (parseFsckOutput maxobjs r (stdoutHandle p))
+ (parseFsckOutput maxobjs r (stderrHandle p))
fsckok <- checkSuccessProcess pid
case mappend o1 o2 of
FsckOutput badobjs truncated
@@ -120,15 +117,15 @@ knownMissing (FsckFoundMissing s _) = s
findMissing :: [Sha] -> Repo -> IO MissingObjects
findMissing objs r = S.fromList <$> filterM (`isMissing` r) objs
-parseFsckOutput :: Int -> Repo -> Bool -> Handle -> IO FsckOutput
-parseFsckOutput maxobjs r supportsNoDangling h = do
+parseFsckOutput :: Int -> Repo -> Handle -> IO FsckOutput
+parseFsckOutput maxobjs r h = do
ls <- lines <$> hGetContents h
if null ls
then return NoFsckOutput
else if all ("duplicateEntries" `isInfixOf`) ls
then return AllDuplicateEntriesWarning
else do
- let shas = findShas supportsNoDangling ls
+ let shas = findShas ls
let !truncated = length shas > maxobjs
missingobjs <- findMissing (take maxobjs shas) r
return $ FsckOutput missingobjs truncated
@@ -141,18 +138,14 @@ isMissing s r = either (const True) (const False) <$> tryIO dump
, Param (fromRef s)
] r
-findShas :: Bool -> [String] -> [Sha]
-findShas supportsNoDangling = catMaybes . map extractSha . concat . map words . filter wanted
+findShas :: [String] -> [Sha]
+findShas = catMaybes . map extractSha . concat . map words . filter wanted
where
- wanted l
- | supportsNoDangling = True
- | otherwise = not ("dangling " `isPrefixOf` l)
-
-fsckParams :: Bool -> Repo -> [CommandParam]
-fsckParams supportsNoDangling = gitCommandLine $ map Param $ catMaybes
- [ Just "fsck"
- , if supportsNoDangling
- then Just "--no-dangling"
- else Nothing
- , Just "--no-reflogs"
+ wanted l = not ("dangling " `isPrefixOf` l)
+
+fsckParams :: Repo -> [CommandParam]
+fsckParams = gitCommandLine $ map Param
+ [ "fsck"
+ , "--no-dangling"
+ , "--no-reflogs"
]
diff --git a/Git/Index.hs b/Git/Index.hs
index 2fdae25..a5bd7b9 100644
--- a/Git/Index.hs
+++ b/Git/Index.hs
@@ -58,19 +58,3 @@ currentIndexFile r = fromMaybe (indexFile r) <$> getEnv indexEnv
{- Git locks the index by creating this file. -}
indexFileLock :: FilePath -> FilePath
indexFileLock f = f ++ ".lock"
-
-{- When the pre-commit hook is run, and git commit has been run with
- - a file or files specified to commit, rather than committing the staged
- - index, git provides the pre-commit hook with a "false index file".
- -
- - Changes made to this index will influence the commit, but won't
- - affect the real index file.
- -
- - This detects when we're in this situation, using a heuristic, which
- - might be broken by changes to git. Any use of this should have a test
- - case to make sure it works.
- -}
-haveFalseIndex :: IO Bool
-haveFalseIndex = maybe (False) check <$> getEnv indexEnv
- where
- check f = "next-index" `isPrefixOf` takeFileName f
diff --git a/Git/Merge.hs b/Git/Merge.hs
index a2c04d7..510f53b 100644
--- a/Git/Merge.hs
+++ b/Git/Merge.hs
@@ -17,7 +17,6 @@ module Git.Merge (
import Common
import Git
import Git.Command
-import qualified Git.BuildVersion
import qualified Git.Version
import Git.Branch (CommitMode(..))
@@ -33,7 +32,7 @@ merge = merge' []
merge' :: [CommandParam] -> Ref -> [MergeConfig] -> CommitMode -> Repo -> IO Bool
merge' extraparams branch mergeconfig commitmode r
- | MergeNonInteractive `notElem` mergeconfig || Git.BuildVersion.older "1.7.7.6" =
+ | MergeNonInteractive `notElem` mergeconfig =
go [Param $ fromRef branch]
| otherwise = go [Param "--no-edit", Param $ fromRef branch]
where
diff --git a/Git/Remote/Remove.hs b/Git/Remote/Remove.hs
index ae09d8b..147e599 100644
--- a/Git/Remote/Remove.hs
+++ b/Git/Remote/Remove.hs
@@ -13,17 +13,10 @@ import Common
import Git
import Git.Types
import qualified Git.Command
-import qualified Git.Version
remove :: RemoteName -> Repo -> IO ()
-remove remotename r = do
- old <- Git.Version.older "1.8.0"
- Git.Command.run
- [ Param "remote"
- -- name of this subcommand changed
- , Param $
- if old
- then "rm"
- else "remove"
- , Param remotename
- ] r
+remove remotename = Git.Command.run
+ [ Param "remote"
+ , Param "remove"
+ , Param remotename
+ ]
diff --git a/NEWS b/NEWS
index a936360..1d04a1e 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,31 @@
+git-annex (7.20190912) upstream; urgency=medium
+
+ This version of git-annex uses repository version 7 for all repositories.
+
+ Existing v5 repositories will be automatically upgraded by default.
+ You can prevent this, by runing: git config annex.autoupgraderepository false
+
+ A v7 repository can can have some files locked while other files are
+ unlocked, and all git and git-annex commands can be used on both locked and
+ unlocked files. It's a good idea to make sure that all users of the
+ repository have upgraded git-annex and upgraded their repositories
+ to the new version before starting to use that feature, since old
+ versions of git-annex will ignore the new unlocked files.
+
+ The behavior of some commands changes in an upgraded repository:
+
+ * `git add` will add files to the annex, rather than adding them directly
+ to the git repository. To cause some files to be added directly
+ to git, you can configure `annex.largefiles`. For example:
+
+ git config annex.largefiles "largerthan=100kb and not (include=*.c or include=*.h)"
+
+ * `git annex unlock` and `git annex lock` change how the pointer to
+ the annexed content is stored in git. If you commit the change,
+ that will impact all clones of the repository.
+
+ -- Joey Hess <id@joeyh.name> Fri, 13 Sep 2019 12:19:55 -0400
+
git-annex (7.20181031) upstream; urgency=medium
Repository version 7 is now available. v6 repositories will automatically
diff --git a/Remote/Git.hs b/Remote/Git.hs
index 0aae29d..e184aeb 100644
--- a/Remote/Git.hs
+++ b/Remote/Git.hs
@@ -37,13 +37,11 @@ import Config
import Config.Cost
import Config.DynamicConfig
import Annex.Init
-import Annex.Version
import Types.CleanupActions
import qualified CmdLine.GitAnnexShell.Fields as Fields
import Logs.Location
import Utility.Metered
import Utility.CopyFile
-import Utility.FileMode
import Utility.Env
import Utility.Batch
import Utility.SimpleProtocol
@@ -62,6 +60,10 @@ import Types.NumCopies
import Annex.Action
import Messages.Progress
+#ifndef mingw32_HOST_OS
+import Utility.FileMode
+#endif
+
import Control.Concurrent
import Control.Concurrent.MSampleVar
import qualified Data.Map as M
@@ -324,7 +326,7 @@ tryGitConfigRead autoinit r
readlocalannexconfig = do
let check = do
Annex.BranchState.disableUpdate
- void $ tryNonAsync $ ensureInitialized
+ catchNonAsync ensureInitialized (warning . show)
Annex.getState Annex.repo
s <- Annex.new r
Annex.eval s $ check `finally` stopCoProcesses
@@ -391,7 +393,6 @@ dropKey' repo r (State connpool duc _ _) key
| not $ Git.repoIsUrl repo = ifM duc
( guardUsable repo (return False) $
commitOnCleanup repo r $ onLocalFast repo r $ do
- ensureInitialized
whenM (Annex.Content.inAnnex key) $ do
Annex.Content.lockContentForRemoval key $ \lock -> do
Annex.Content.removeAnnex lock
@@ -489,7 +490,6 @@ copyFromRemote'' repo forcersync r st@(State connpool _ _ _) key file dest meter
hardlink <- wantHardLink
-- run copy from perspective of remote
onLocalFast repo r $ do
- ensureInitialized
v <- Annex.Content.prepSendAnnex key
case v of
Nothing -> return (False, UnVerified)
@@ -631,7 +631,6 @@ copyToRemote' repo r st@(State connpool duc _ _) key file meterupdate
onLocalFast repo r $ ifM (Annex.Content.inAnnex key)
( return True
, do
- ensureInitialized
copier <- mkCopier hardlink st params
let verify = Annex.Content.RemoteVerify r
let rsp = RetrievalAllKeysSecure
@@ -645,7 +644,7 @@ copyToRemote' repo r st@(State connpool duc _ _) key file meterupdate
-- This is too broad really, but recvkey normally
-- verifies content anyway, so avoid complicating
-- it with a local sendAnnex check and rollback.
- unlocked <- isDirect <||> versionSupportsUnlockedPointers
+ let unlocked = True
oh <- mkOutputHandlerQuiet
Ssh.rsyncHelper oh (Just p)
=<< Ssh.rsyncParamsRemote unlocked r Upload key object file
@@ -681,21 +680,25 @@ repairRemote r a = return $ do
- The AnnexState is cached for speed and to avoid resource leaks.
- However, coprocesses are stopped after each call to avoid git
- processes hanging around on removable media.
+ -
+ - The remote will be automatically initialized/upgraded first,
+ - when possible.
-}
onLocal :: Git.Repo -> Remote -> Annex a -> Annex a
onLocal repo r a = do
m <- Annex.getState Annex.remoteannexstate
- go =<< maybe
- (liftIO $ Annex.new repo)
- return
- (M.lookup (uuid r) m)
+ case M.lookup (uuid r) m of
+ Nothing -> do
+ st <- liftIO $ Annex.new repo
+ go (st, ensureInitialized >> a)
+ Just st -> go (st, a)
where
cache st = Annex.changeState $ \s -> s
{ Annex.remoteannexstate = M.insert (uuid r) st (Annex.remoteannexstate s) }
- go st = do
+ go (st, a') = do
curro <- Annex.getState Annex.output
(ret, st') <- liftIO $ Annex.run (st { Annex.output = curro }) $
- a `finally` stopCoProcesses
+ a' `finally` stopCoProcesses
cache st'
return ret
@@ -719,13 +722,14 @@ newCopyCoWTried = CopyCoWTried <$> newEmptyMVar
{- Copys a file. Uses copy-on-write if it is supported. Otherwise,
- uses rsync, so that interrupted copies can be resumed. -}
rsyncOrCopyFile :: State -> [CommandParam] -> FilePath -> FilePath -> MeterUpdate -> Annex Bool
-rsyncOrCopyFile st rsyncparams src dest p =
#ifdef mingw32_HOST_OS
+rsyncOrCopyFile _st _rsyncparams src dest p =
-- rsync is only available on Windows in some installation methods,
-- and is not strictly needed here, so don't use it.
docopywith copyFileExternal
where
#else
+rsyncOrCopyFile st rsyncparams src dest p =
-- If multiple threads reach this at the same time, they
-- will both try CoW, which is acceptable.
ifM (liftIO $ isEmptyMVar copycowtried)
@@ -775,8 +779,6 @@ commitOnCleanup repo r a = go `after` a
wantHardLink :: Annex Bool
wantHardLink = (annexHardLink <$> Annex.getGitConfig)
- -- Not direct mode files because they can be modified at any time.
- <&&> (not <$> isDirect)
-- Not unlocked files that are hard linked in the work tree,
-- because they can be modified at any time.
<&&> (not <$> annexThin <$> Annex.getGitConfig)
@@ -800,14 +802,13 @@ mkCopier remotewanthardlink st rsyncparams = do
rsyncOrCopyFile st rsyncparams src dest p <&&> check
localwanthardlink <- wantHardLink
let linker = \src dest -> createLink src dest >> return True
- ifM (pure (remotewanthardlink || localwanthardlink) <&&> not <$> isDirect)
- ( return $ \src dest p check ->
+ if remotewanthardlink || localwanthardlink
+ then return $ \src dest p check ->
ifM (liftIO (catchBoolIO (linker src dest)))
( return (True, Verified)
, copier src dest p check
)
- , return copier
- )
+ else return copier
{- Normally the UUID of a local repository is checked at startup,
- but annex-checkuuid config can prevent that. To avoid getting
diff --git a/Test.hs b/Test.hs
index 0b5f3f8..be15365 100644
--- a/Test.hs
+++ b/Test.hs
@@ -30,7 +30,6 @@ import CmdLine.GitAnnex.Options
import qualified Utility.SafeCommand
import qualified Annex
-import qualified Annex.Version
import qualified Git.Filename
import qualified Git.Types
import qualified Git.Ref
@@ -151,9 +150,7 @@ tests crippledfilesystem adjustedbranchok opts =
testmodes = catMaybes
[ canadjust ("v7 adjusted unlocked branch", (testMode opts (RepoVersion 7)) { adjustedUnlockedBranch = True })
, unlesscrippled ("v7 unlocked", (testMode opts (RepoVersion 7)) { unlockedFiles = True })
- , unlesscrippled ("v5", testMode opts (RepoVersion 5))
, unlesscrippled ("v7 locked", testMode opts (RepoVersion 7))
- , Just ("v5 direct", (testMode opts (RepoVersion 5)) { forceDirect = True })
]
unlesscrippled v
| crippledfilesystem = Nothing
@@ -231,12 +228,11 @@ unitTests note = testGroup ("Unit Tests " ++ note)
, testCase "move (ssh remote)" test_move_ssh_remote
, testCase "copy" test_copy
, testCase "lock" test_lock
- , testCase "lock (v7 --force)" test_lock_v7_force
+ , testCase "lock --force" test_lock_force
, testCase "edit (no pre-commit)" test_edit
, testCase "edit (pre-commit)" test_edit_precommit
, testCase "partial commit" test_partial_commit
, testCase "fix" test_fix
- , testCase "direct" test_direct
, testCase "trust" test_trust
, testCase "fsck (basics)" test_fsck_basic
, testCase "fsck (bare)" test_fsck_bare
@@ -302,19 +298,11 @@ test_add = inmainrepo $ do
git_annex "unlock" [sha1annexedfile] @? "unlock failed"
annexed_present sha1annexedfile
checkbackend sha1annexedfile backendSHA1
- ifM (annexeval Config.isDirect)
- ( do
- writecontent ingitfile $ content ingitfile
- not <$> boolSystem "git" [Param "add", File ingitfile] @? "git add failed to fail in direct mode"
- nukeFile ingitfile
- git_annex "sync" [] @? "sync failed"
- , do
- writecontent ingitfile $ content ingitfile
- boolSystem "git" [Param "add", File ingitfile] @? "git add failed"
- boolSystem "git" [Param "commit", Param "-q", Param "-m", Param "commit"] @? "git commit failed"
- git_annex "add" [ingitfile] @? "add ingitfile should be no-op"
- unannexed ingitfile
- )
+ writecontent ingitfile $ content ingitfile
+ boolSystem "git" [Param "add", File ingitfile] @? "git add failed"
+ boolSystem "git" [Param "commit", Param "-q", Param "-m", Param "commit"] @? "git commit failed"
+ git_annex "add" [ingitfile] @? "add ingitfile should be no-op"
+ unannexed ingitfile
test_add_dup :: Assertion
test_add_dup = intmpclonerepo $ do
@@ -394,7 +382,7 @@ test_import = intmpclonerepo $ Utility.Tmp.Dir.withTmpDir "importtest" $ \import
return (importdir </> subdir, importdir </> importf, importf)
test_reinject :: Assertion
-test_reinject = intmpclonerepoInDirect $ do
+test_reinject = intmpclonerepo $ do
git_annex "drop" ["--force", sha1annexedfile] @? "drop failed"
annexed_notpresent sha1annexedfile
writecontent tmp $ content sha1annexedfile
@@ -423,9 +411,8 @@ test_unannex_withcopy = intmpclonerepo $ do
unannexed annexedfile
git_annex "unannex" [annexedfile] @? "unannex failed on non-annexed file"
unannexed annexedfile
- unlessM (annexeval Config.isDirect) $ do
- git_annex "unannex" [ingitfile] @? "unannex ingitfile should be no-op"
- unannexed ingitfile
+ git_annex "unannex" [ingitfile] @? "unannex ingitfile should be no-op"
+ unannexed ingitfile
test_drop_noremote :: Assertion
test_drop_noremote = intmpclonerepo $ do
@@ -437,9 +424,8 @@ test_drop_noremote = intmpclonerepo $ do
git_annex "drop" ["--force", annexedfile] @? "drop --force failed"
annexed_notpresent annexedfile
git_annex "drop" [annexedfile] @? "drop of dropped file failed"
- unlessM (annexeval Config.isDirect) $ do
- git_annex "drop" [ingitfile] @? "drop ingitfile should be no-op"
- unannexed ingitfile
+ git_annex "drop" [ingitfile] @? "drop ingitfile should be no-op"
+ unannexed ingitfile
test_drop_withremote :: Assertion
test_drop_withremote = intmpclonerepo $ do
@@ -485,12 +471,11 @@ test_get' setup = setup $ do
git_annex "get" [annexedfile] @? "get of file already here failed"
inmainrepo $ annexed_present annexedfile
annexed_present annexedfile
- unlessM (annexeval Config.isDirect) $ do
- inmainrepo $ unannexed ingitfile
- unannexed ingitfile
- git_annex "get" [ingitfile] @? "get ingitfile should be no-op"
- inmainrepo $ unannexed ingitfile
- unannexed ingitfile
+ inmainrepo $ unannexed ingitfile
+ unannexed ingitfile
+ git_annex "get" [ingitfile] @? "get ingitfile should be no-op"
+ inmainrepo $ unannexed ingitfile
+ unannexed ingitfile
test_move :: Assertion
test_move = test_move' intmpclonerepo
@@ -519,15 +504,14 @@ test_move' setup = setup $ do
git_annex "move" ["--to", "origin", annexedfile] @? "move --to of file already there failed"
inmainrepo $ annexed_present annexedfile
annexed_notpresent annexedfile
- unlessM (annexeval Config.isDirect) $ do
- unannexed ingitfile
- inmainrepo $ unannexed ingitfile
- git_annex "move" ["--to", "origin", ingitfile] @? "move of ingitfile should be no-op"
- unannexed ingitfile
- inmainrepo $ unannexed ingitfile
- git_annex "move" ["--from", "origin", ingitfile] @? "move of ingitfile should be no-op"
- unannexed ingitfile
- inmainrepo $ unannexed ingitfile
+ unannexed ingitfile
+ inmainrepo $ unannexed ingitfile
+ git_annex "move" ["--to", "origin", ingitfile] @? "move of ingitfile should be no-op"
+ unannexed ingitfile
+ inmainrepo $ unannexed ingitfile
+ git_annex "move" ["--from", "origin", ingitfile] @? "move of ingitfile should be no-op"
+ unannexed ingitfile
+ inmainrepo $ unannexed ingitfile
test_copy :: Assertion
test_copy = intmpclonerepo $ do
@@ -545,15 +529,14 @@ test_copy = intmpclonerepo $ do
git_annex "move" ["--to", "origin", annexedfile] @? "move --to of file already there failed"
annexed_notpresent annexedfile
inmainrepo $ annexed_present annexedfile
- unlessM (annexeval Config.isDirect) $ do
- unannexed ingitfile
- inmainrepo $ unannexed ingitfile
- git_annex "copy" ["--to", "origin", ingitfile] @? "copy of ingitfile should be no-op"
- unannexed ingitfile
- inmainrepo $ unannexed ingitfile
- git_annex "copy" ["--from", "origin", ingitfile] @? "copy of ingitfile should be no-op"
- checkregularfile ingitfile
- checkcontent ingitfile
+ unannexed ingitfile
+ inmainrepo $ unannexed ingitfile
+ git_annex "copy" ["--to", "origin", ingitfile] @? "copy of ingitfile should be no-op"
+ unannexed ingitfile
+ inmainrepo $ unannexed ingitfile
+ git_annex "copy" ["--from", "origin", ingitfile] @? "copy of ingitfile should be no-op"
+ checkregularfile ingitfile
+ checkcontent ingitfile
test_preferred_content :: Assertion
test_preferred_content = intmpclonerepo $ do
@@ -597,23 +580,14 @@ test_preferred_content = intmpclonerepo $ do
annexed_notpresent annexedfile
test_lock :: Assertion
-test_lock = intmpclonerepoInDirect $ do
- annexed_notpresent annexedfile
- unlessM (annexeval Annex.Version.versionSupportsUnlockedPointers) $
- ifM (hasUnlockedFiles <$> getTestMode)
- ( git_annex_shouldfail "lock" [annexedfile] @? "lock failed to fail with not present file"
- , git_annex_shouldfail "unlock" [annexedfile] @? "unlock failed to fail with not present file"
- )
+test_lock = intmpclonerepo $ do
annexed_notpresent annexedfile
-- regression test: unlock of newly added, not committed file
- -- should fail in v5 mode. In v7 mode, this is allowed.
+ -- should not fail.
writecontent "newfile" "foo"
git_annex "add" ["newfile"] @? "add new file failed"
- ifM (annexeval Annex.Version.versionSupportsUnlockedPointers)
- ( git_annex "unlock" ["newfile"] @? "unlock failed on newly added, never committed file in v7 repository"
- , git_annex_shouldfail "unlock" ["newfile"] @? "unlock failed to fail on newly added, never committed file in v5 repository"
- )
+ git_annex "unlock" ["newfile"] @? "unlock failed on newly added, never committed file"
git_annex "get" [annexedfile] @? "get of file failed"
annexed_present annexedfile
@@ -625,21 +599,15 @@ test_lock = intmpclonerepoInDirect $ do
writecontent annexedfile $ content annexedfile ++ "foo"
git_annex_shouldfail "lock" [annexedfile] @? "lock failed to fail without --force"
git_annex "lock" ["--force", annexedfile] @? "lock --force failed"
- -- In v7 mode, the original content of the file is not always
+ -- The original content of an unlocked file is not always
-- preserved after modification, so re-get it.
git_annex "get" [annexedfile] @? "get of file failed after lock --force"
annexed_present_locked annexedfile
git_annex "unlock" [annexedfile] @? "unlock failed"
unannexed annexedfile
changecontent annexedfile
- ifM (annexeval Annex.Version.versionSupportsUnlockedPointers)
- ( do
- boolSystem "git" [Param "add", Param annexedfile] @? "add of modified file failed"
- runchecks [checkregularfile, checkwritable] annexedfile
- , do
- git_annex "add" [annexedfile] @? "add of modified file failed"
- runchecks [checklink, checkunwritable] annexedfile
- )
+ boolSystem "git" [Param "add", Param annexedfile] @? "add of modified file failed"
+ runchecks [checkregularfile, checkwritable] annexedfile
c <- readFile annexedfile
assertEqual "content of modified file" c (changedcontent annexedfile)
r' <- git_annex "drop" [annexedfile]
@@ -648,21 +616,20 @@ test_lock = intmpclonerepoInDirect $ do
-- Regression test: lock --force when work tree file
-- was modified lost the (unmodified) annex object.
-- (Only occurred when the keys database was out of sync.)
-test_lock_v7_force :: Assertion
-test_lock_v7_force = intmpclonerepoInDirect $ do
+test_lock_force :: Assertion
+test_lock_force = intmpclonerepo $ do
git_annex "upgrade" [] @? "upgrade failed"
- whenM (annexeval Annex.Version.versionSupportsUnlockedPointers) $ do
- git_annex "get" [annexedfile] @? "get of file failed"
- git_annex "unlock" [annexedfile] @? "unlock failed in v7 mode"
- annexeval $ do
- Just k <- Annex.WorkTree.lookupFile annexedfile
- Database.Keys.removeInodeCaches k
- Database.Keys.closeDb
- liftIO . nukeFile =<< Annex.fromRepo Annex.Locations.gitAnnexKeysDbIndexCache
- writecontent annexedfile "test_lock_v7_force content"
- git_annex_shouldfail "lock" [annexedfile] @? "lock of modified file failed to fail in v7 mode"
- git_annex "lock" ["--force", annexedfile] @? "lock --force of modified file failed in v7 mode"
- annexed_present_locked annexedfile
+ git_annex "get" [annexedfile] @? "get of file failed"
+ git_annex "unlock" [annexedfile] @? "unlock failed"
+ annexeval $ do
+ Just k <- Annex.WorkTree.lookupFile annexedfile
+ Database.Keys.removeInodeCaches k
+ Database.Keys.closeDb
+ liftIO . nukeFile =<< Annex.fromRepo Annex.Locations.gitAnnexKeysDbIndexCache
+ writecontent annexedfile "test_lock_force content"
+ git_annex_shouldfail "lock" [annexedfile] @? "lock of modified file failed to fail"
+ git_annex "lock" ["--force", annexedfile] @? "lock --force of modified file failed"
+ annexed_present_locked annexedfile
test_edit :: Assertion
test_edit = test_edit' False
@@ -671,7 +638,7 @@ test_edit_precommit :: Assertion
test_edit_precommit = test_edit' True
test_edit' :: Bool -> Assertion
-test_edit' precommit = intmpclonerepoInDirect $ do
+test_edit' precommit = intmpclonerepo $ do
git_annex "get" [annexedfile] @? "get of file failed"
annexed_present annexedfile
git_annex "edit" [annexedfile] @? "edit failed"
@@ -684,29 +651,22 @@ test_edit' precommit = intmpclonerepoInDirect $ do
@? "pre-commit failed"
else boolSystem "git" [Param "commit", Param "-q", Param "-m", Param "contentchanged"]
@? "git commit of edited file failed"
- ifM (annexeval Annex.Version.versionSupportsUnlockedPointers)
- ( runchecks [checkregularfile, checkwritable] annexedfile
- , runchecks [checklink, checkunwritable] annexedfile
- )
+ runchecks [checkregularfile, checkwritable] annexedfile
c <- readFile annexedfile
assertEqual "content of modified file" c (changedcontent annexedfile)
git_annex_shouldfail "drop" [annexedfile] @? "drop wrongly succeeded with no known copy of modified file"
test_partial_commit :: Assertion
-test_partial_commit = intmpclonerepoInDirect $ do
+test_partial_commit = intmpclonerepo $ do
git_annex "get" [annexedfile] @? "get of file failed"
annexed_present annexedfile
git_annex "unlock" [annexedfile] @? "unlock failed"
changecontent annexedfile
- ifM (annexeval Annex.Version.versionSupportsUnlockedPointers)
- ( boolSystem "git" [Param "commit", Param "-q", Param "-m", Param "test", File annexedfile]
- @? "partial commit of unlocked file should be allowed in v7 repository"
- , not <$> boolSystem "git" [Param "commit", Param "-q", Param "-m", Param "test", File annexedfile]
- @? "partial commit of unlocked file not blocked by pre-commit hook"
- )
+ boolSystem "git" [Param "commit", Param "-q", Param "-m", Param "test", File annexedfile]
+ @? "partial commit of unlocked file should be allowed"
test_fix :: Assertion
-test_fix = intmpclonerepoInDirect $ unlessM (hasUnlockedFiles <$> getTestMode) $ do
+test_fix = intmpclonerepo $ unlessM (hasUnlockedFiles <$> getTestMode) $ do
annexed_notpresent annexedfile
git_annex "fix" [annexedfile] @? "fix of not present failed"
annexed_notpresent annexedfile
@@ -725,18 +685,6 @@ test_fix = intmpclonerepoInDirect $ unlessM (hasUnlockedFiles <$> getTestMode) $
subdir = "s"
newfile = subdir ++ "/" ++ annexedfile
-test_direct :: Assertion
-test_direct = intmpclonerepoInDirect $ do
- git_annex "get" [annexedfile] @? "get of file failed"
- annexed_present annexedfile
- ifM (annexeval Annex.Version.versionSupportsUnlockedPointers)
- ( git_annex_shouldfail "direct" [] @? "switch to direct mode failed to fail in v7 repository"
- , do
- git_annex "direct" [] @? "switch to direct mode failed"
- annexed_present annexedfile
- git_annex "indirect" [] @? "switch to indirect mode failed"
- )
-
test_trust :: Assertion
test_trust = intmpclonerepo $ do
git_annex "trust" [repo] @? "trust failed"
@@ -777,7 +725,7 @@ test_fsck_basic = intmpclonerepo $ do
git_annex "get" [f] @? "get of file failed"
Utility.FileMode.allowWrite f
writecontent f (changedcontent f)
- ifM (annexeval Config.isDirect <||> hasUnlockedFiles <$> getTestMode)
+ ifM (hasUnlockedFiles <$> getTestMode)
( git_annex "fsck" [] @? "fsck failed on unlocked file with changed file content"
, git_annex_shouldfail "fsck" [] @? "fsck failed to fail with corrupted file content"
)
@@ -820,7 +768,7 @@ test_migrate_via_gitattributes :: Assertion
test_migrate_via_gitattributes = test_migrate' True
test_migrate' :: Bool -> Assertion
-test_migrate' usegitattributes = intmpclonerepoInDirect $ do
+test_migrate' usegitattributes = intmpclonerepo $ do
annexed_notpresent annexedfile
annexed_notpresent sha1annexedfile
git_annex "migrate" [annexedfile] @? "migrate of not present failed"
@@ -858,8 +806,7 @@ test_migrate' usegitattributes = intmpclonerepoInDirect $ do
checkbackend sha1annexedfile backendSHA256
test_unused :: Assertion
--- This test is broken in direct mode.
-test_unused = intmpclonerepoInDirect $ do
+test_unused = intmpclonerepo $ do
checkunused [] "in new clone"
git_annex "get" [annexedfile] @? "get of file failed"
git_annex "get" [sha1annexedfile] @? "get of file failed"
@@ -991,10 +938,6 @@ test_version = intmpclonerepo $
test_sync :: Assertion
test_sync = intmpclonerepo $ do
git_annex "sync" [] @? "sync failed"
- {- Regression test for bug fixed in
- - 7b0970b340d7faeb745c666146c7f701ec71808f, where in direct mode
- - sync committed the symlink standin file to the annex. -}
- git_annex_expectoutput "find" ["--in", "."] []
{- Regression test for bug fixed in
- 039e83ed5d1a11fd562cce55b8429c840d72443e, where a present
- wanted file was dropped. -}
@@ -1051,12 +994,8 @@ test_conflict_resolution_movein_regression = withtmpclonerepo $ \r1 ->
forM_ [r1, r2] $ \r -> indir r $ do
{- Set up a conflict. -}
let newcontent = content annexedfile ++ rname r
- ifM (annexeval Config.isDirect)
- ( writecontent annexedfile newcontent
- , do
- git_annex "unlock" [annexedfile] @? "unlock failed"
- writecontent annexedfile newcontent
- )
+ git_annex "unlock" [annexedfile] @? "unlock failed"
+ writecontent annexedfile newcontent
{- Sync twice in r1 so it gets the conflict resolution
- update from r2 -}
forM_ [r1, r2, r1] $ \r -> indir r $
@@ -1065,9 +1004,8 @@ test_conflict_resolution_movein_regression = withtmpclonerepo $ \r1 ->
- files. This includes both sides of the conflict,
- although the filenames are not easily predictable.
-
- - The bug caused, in direct mode, one repo to
- - be missing the content of the file that had
- - been put in it. -}
+ - The bug caused one repo to be missing the content
+ - of the file that had been put in it. -}
forM_ [r1, r2] $ \r -> indir r $ do
git_annex "get" [] @? "unable to get all files after merge conflict resolution in " ++ rname r
@@ -1120,8 +1058,6 @@ test_conflict_resolution_adjusted_branch =
writecontent conflictor "conflictor2"
add_annex conflictor @? "add conflicter failed"
git_annex "sync" [] @? "sync failed in r2"
- -- need v7 to use adjust
- git_annex "upgrade" [] @? "upgrade failed"
-- We might be in an adjusted branch
-- already, when eg on a crippled
-- filesystem. So, --force it.
@@ -1207,9 +1143,8 @@ test_remove_conflict_resolution = do
git_annex "sync" [] @? "sync failed in r2"
git_annex "get" [conflictor]
@? "get conflictor failed"
- unlessM (annexeval Config.isDirect) $ do
- git_annex "unlock" [conflictor]
- @? "unlock conflictor failed"
+ git_annex "unlock" [conflictor]
+ @? "unlock conflictor failed"
writecontent conflictor "newconflictor"
indir r1 $
nukeFile conflictor
@@ -1230,44 +1165,35 @@ test_remove_conflict_resolution = do
{- Check merge confalict resolution when a file is annexed in one repo,
- and checked directly into git in the other repo.
- -
- - This test requires indirect mode to set it up, but tests both direct and
- - indirect mode.
-}
test_nonannexed_file_conflict_resolution :: Assertion
test_nonannexed_file_conflict_resolution = do
- check True False
- check False False
- check True True
- check False True
+ check True
+ check False
where
- check inr1 switchdirect = withtmpclonerepo $ \r1 ->
- withtmpclonerepo $ \r2 ->
- whenM (isInDirect r1 <&&> isInDirect r2) $ do
- indir r1 $ do
- disconnectOrigin
- writecontent conflictor "conflictor"
- add_annex conflictor @? "add conflicter failed"
- git_annex "sync" [] @? "sync failed in r1"
- indir r2 $ do
- disconnectOrigin
- writecontent conflictor nonannexed_content
- boolSystem "git"
- [ Param "config"
- , Param "annex.largefiles"
- , Param ("exclude=" ++ ingitfile ++ " and exclude=" ++ conflictor)
- ] @? "git config annex.largefiles failed"
- boolSystem "git" [Param "add", File conflictor] @? "git add conflictor failed"
- git_annex "sync" [] @? "sync failed in r2"
- pair r1 r2
- let l = if inr1 then [r1, r2] else [r2, r1]
- forM_ l $ \r -> indir r $ do
- when switchdirect $
- whenM (annexeval Annex.Version.versionSupportsDirectMode) $
- git_annex "direct" [] @? "failed switching to direct mode"
- git_annex "sync" [] @? "sync failed"
- checkmerge ("r1" ++ show switchdirect) r1
- checkmerge ("r2" ++ show switchdirect) r2
+ check inr1 = withtmpclonerepo $ \r1 ->
+ withtmpclonerepo $ \r2 -> do
+ indir r1 $ do
+ disconnectOrigin
+ writecontent conflictor "conflictor"
+ add_annex conflictor @? "add conflicter failed"
+ git_annex "sync" [] @? "sync failed in r1"
+ indir r2 $ do
+ disconnectOrigin
+ writecontent conflictor nonannexed_content
+ boolSystem "git"
+ [ Param "config"
+ , Param "annex.largefiles"
+ , Param ("exclude=" ++ ingitfile ++ " and exclude=" ++ conflictor)
+ ] @? "git config annex.largefiles failed"
+ boolSystem "git" [Param "add", File conflictor] @? "git add conflictor failed"
+ git_annex "sync" [] @? "sync failed in r2"
+ pair r1 r2
+ let l = if inr1 then [r1, r2] else [r2, r1]
+ forM_ l $ \r -> indir r $
+ git_annex "sync" [] @? "sync failed"
+ checkmerge "r1" r1
+ checkmerge "r2" r2
conflictor = "conflictor"
nonannexed_content = "nonannexed"
variantprefix = conflictor ++ ".variant"
@@ -1284,7 +1210,7 @@ test_nonannexed_file_conflict_resolution = do
@? (what ++ " wrong content for nonannexed file: " ++ show s)
-{- Check merge confalict resolution when a file is annexed in one repo,
+{- Check merge conflict resolution when a file is annexed in one repo,
- and is a non-git-annex symlink in the other repo.
-
- Test can only run when coreSymlinks is supported, because git needs to
@@ -1292,15 +1218,12 @@ test_nonannexed_file_conflict_resolution = do
-}
test_nonannexed_symlink_conflict_resolution :: Assertion
test_nonannexed_symlink_conflict_resolution = do
- check True False
- check False False
- check True True
- check False True
+ check True
+ check False
where
- check inr1 switchdirect = withtmpclonerepo $ \r1 ->
+ check inr1 = withtmpclonerepo $ \r1 ->
withtmpclonerepo $ \r2 ->
- whenM (checkRepo (Types.coreSymlinks <$> Annex.getGitConfig) r1
- <&&> isInDirect r1 <&&> isInDirect r2) $ do
+ whenM (checkRepo (Types.coreSymlinks <$> Annex.getGitConfig) r1) $ do
indir r1 $ do
disconnectOrigin
writecontent conflictor "conflictor"
@@ -1313,13 +1236,10 @@ test_nonannexed_symlink_conflict_resolution = do
git_annex "sync" [] @? "sync failed in r2"
pair r1 r2
let l = if inr1 then [r1, r2] else [r2, r1]
- forM_ l $ \r -> indir r $ do
- when switchdirect $
- whenM (annexeval Annex.Version.versionSupportsDirectMode) $ do
- git_annex "direct" [] @? "failed switching to direct mode"
+ forM_ l $ \r -> indir r $
git_annex "sync" [] @? "sync failed"
- checkmerge ("r1" ++ show switchdirect) r1
- checkmerge ("r2" ++ show switchdirect) r2
+ checkmerge "r1" r1
+ checkmerge "r2" r2
conflictor = "conflictor"
symlinktarget = "dummy-target"
variantprefix = conflictor ++ ".variant"
@@ -1361,24 +1281,11 @@ test_uncommitted_conflict_resolution = do
disconnectOrigin
writecontent conflictor localcontent
pair r1 r2
- indir r2 $ ifM (annexeval Config.isDirect)
- ( do
- git_annex "sync" [] @? "sync failed"
- let local = conflictor ++ localprefix
- doesFileExist local @? (local ++ " missing after merge")
- s <- readFile local
- s == localcontent @? (local ++ " has wrong content: " ++ s)
- git_annex "get" [conflictor] @? "get failed"
- doesFileExist remoteconflictor @? (remoteconflictor ++ " missing after merge")
- s' <- readFile remoteconflictor
- s' == annexedcontent @? (remoteconflictor ++ " has wrong content: " ++ s)
- -- this case is intentionally not handled
- -- in indirect mode, since the user
- -- can recover on their own easily
- , git_annex_shouldfail "sync" [] @? "sync failed to fail"
- )
+ -- this case is intentionally not handled
+ -- since the user can recover on their own easily
+ indir r2 $ git_annex_shouldfail "sync" []
+ @? "sync failed to fail"
conflictor = "conflictor"
- localprefix = ".variant-local"
localcontent = "local"
annexedcontent = "annexed"
@@ -1414,19 +1321,19 @@ test_conflict_resolution_symlink_bit = unlessM (hasUnlockedFiles <$> getTestMode
all (\i -> Git.Types.toTreeItemType (Git.LsTree.mode i) == Just Git.Types.TreeSymlink) l
@? (what ++ " " ++ f ++ " lost symlink bit after merge: " ++ show l)
-{- A v7 unlocked file that conflicts with a locked file should be resolved
+{- An unlocked file that conflicts with a locked file should be resolved
- in favor of the unlocked file, with no variant files, as long as they
- both point to the same key. -}
test_mixed_lock_conflict_resolution :: Assertion
test_mixed_lock_conflict_resolution =
withtmpclonerepo $ \r1 ->
withtmpclonerepo $ \r2 -> do
- indir r1 $ whenM shouldtest $ do
+ indir r1 $ do
disconnectOrigin
writecontent conflictor "conflictor"
git_annex "add" [conflictor] @? "add conflicter failed"
git_annex "sync" [] @? "sync failed in r1"
- indir r2 $ whenM shouldtest $ do
+ indir r2 $ do
disconnectOrigin
writecontent conflictor "conflictor"
git_annex "add" [conflictor] @? "add conflicter failed"
@@ -1438,10 +1345,9 @@ test_mixed_lock_conflict_resolution =
checkmerge "r1" r1
checkmerge "r2" r2
where
- shouldtest = annexeval Annex.Version.versionSupportsUnlockedPointers
conflictor = "conflictor"
variantprefix = conflictor ++ ".variant"
- checkmerge what d = indir d $ whenM shouldtest $ do
+ checkmerge what d = indir d $ do
l <- getDirectoryContents "."
let v = filter (variantprefix `isPrefixOf`) l
length v == 0
@@ -1527,7 +1433,7 @@ test_uninit = intmpclonerepo $ do
doesDirectoryExist ".git" @? ".git vanished in uninit"
test_uninit_inbranch :: Assertion
-test_uninit_inbranch = intmpclonerepoInDirect $ do
+test_uninit_inbranch = intmpclonerepo $ do
boolSystem "git" [Param "checkout", Param "git-annex"] @? "git checkout git-annex"
git_annex_shouldfail "uninit" [] @? "uninit failed to fail when git-annex branch was checked out"
@@ -1744,7 +1650,7 @@ test_addurl = intmpclonerepo $ do
doesFileExist dest @? (dest ++ " missing after addurl --file")
test_export_import :: Assertion
-test_export_import = intmpclonerepoInDirect $ do
+test_export_import = intmpclonerepo $ do
createDirectory "dir"
git_annex "initremote" (words "foo type=directory encryption=none directory=dir exporttree=yes importtree=yes") @? "initremote failed"
git_annex "get" [] @? "get of files failed"
@@ -1798,7 +1704,7 @@ test_export_import = intmpclonerepoInDirect $ do
commitchanges = git_annex "sync" ["--no-pull", "--no-push"] @? "sync failed"
test_export_import_subdir :: Assertion
-test_export_import_subdir = intmpclonerepoInDirect $ do
+test_export_import_subdir = intmpclonerepo $ do
createDirectory "dir"
git_annex "initremote" (words "foo type=directory encryption=none directory=dir exporttree=yes importtree=yes") @? "initremote failed"
git_annex "get" [] @? "get of files failed"
diff --git a/Test/Framework.hs b/Test/Framework.hs
index bb5ca44..000d80e 100644
--- a/Test/Framework.hs
+++ b/Test/Framework.hs
@@ -31,7 +31,6 @@ import qualified Types.Messages
import qualified Config
import qualified Annex.WorkTree
import qualified Annex.Link
-import qualified Annex.Init
import qualified Annex.Path
import qualified Annex.Action
import qualified Annex.AdjustedBranch
@@ -98,26 +97,12 @@ with_ssh_origin cloner a = cloner $ do
intmpclonerepo :: Assertion -> Assertion
intmpclonerepo a = withtmpclonerepo $ \r -> indir r a
-intmpclonerepoInDirect :: Assertion -> Assertion
-intmpclonerepoInDirect a = intmpclonerepo $
- ifM isdirect
- ( putStrLn "not supported in direct mode; skipping"
- , a
- )
- where
- isdirect = annexeval $ do
- Annex.Init.initialize Nothing Nothing
- Config.isDirect
-
checkRepo :: Types.Annex a -> FilePath -> IO a
checkRepo getval d = do
s <- Annex.new =<< Git.Construct.fromPath d
Annex.eval s $
getval `finally` Annex.Action.stopCoProcesses
-isInDirect :: FilePath -> IO Bool
-isInDirect = checkRepo (not <$> Config.isDirect)
-
intmpbareclonerepo :: Assertion -> Assertion
intmpbareclonerepo a = withtmpclonerepo' (newCloneRepoConfig { bareClone = True } ) $
\r -> indir r a
@@ -165,7 +150,7 @@ indir dir a = do
Left e -> throwM e
adjustedbranchsupported :: FilePath -> IO Bool
-adjustedbranchsupported repo = indir repo $ annexeval Annex.AdjustedBranch.isSupported
+adjustedbranchsupported repo = indir repo $ Annex.AdjustedBranch.isGitVersionSupported
setuprepo :: FilePath -> IO FilePath
setuprepo dir = do
@@ -259,17 +244,13 @@ finalCleanup = whenM (doesDirectoryExist tmpdir) $ do
removeDirectoryRecursive tmpdir
checklink :: FilePath -> Assertion
-checklink f =
- -- in direct mode, it may be a symlink, or not, depending
- -- on whether the content is present.
- unlessM (annexeval Config.isDirect) $
- ifM (annexeval Config.crippledFileSystem)
- ( (isJust <$> annexeval (Annex.Link.getAnnexLinkTarget f))
- @? f ++ " is not a (crippled) symlink"
- , do
- s <- getSymbolicLinkStatus f
- isSymbolicLink s @? f ++ " is not a symlink"
- )
+checklink f = ifM (annexeval Config.crippledFileSystem)
+ ( (isJust <$> annexeval (Annex.Link.getAnnexLinkTarget f))
+ @? f ++ " is not a (crippled) symlink"
+ , do
+ s <- getSymbolicLinkStatus f
+ isSymbolicLink s @? f ++ " is not a symlink"
+ )
checkregularfile :: FilePath -> Assertion
checkregularfile f = do
@@ -293,7 +274,7 @@ checkcontent f = do
assertEqual ("checkcontent " ++ f) (content f) c
checkunwritable :: FilePath -> Assertion
-checkunwritable f = unlessM (annexeval Config.isDirect) $ do
+checkunwritable f = do
-- Look at permissions bits rather than trying to write or
-- using fileAccess because if run as root, any file can be
-- modified despite permissions.
@@ -408,8 +389,7 @@ add_annex f = ifM (unlockedFiles <$> getTestMode)
)
data TestMode = TestMode
- { forceDirect :: Bool
- , unlockedFiles :: Bool
+ { unlockedFiles :: Bool
, adjustedUnlockedBranch :: Bool
, annexVersion :: Types.RepoVersion.RepoVersion
, keepFailures :: Bool
@@ -417,8 +397,7 @@ data TestMode = TestMode
testMode :: TestOptions -> Types.RepoVersion.RepoVersion -> TestMode
testMode opts v = TestMode
- { forceDirect = False
- , unlockedFiles = False
+ { unlockedFiles = False
, adjustedUnlockedBranch = False
, annexVersion = v
, keepFailures = keepFailuresOption opts
@@ -477,8 +456,6 @@ getTestMode = Prelude.read <$> Utility.Env.getEnvDefault "TESTMODE" ""
setupTestMode :: IO ()
setupTestMode = do
testmode <- getTestMode
- when (forceDirect testmode) $
- git_annex "direct" ["-q"] @? "git annex direct failed"
when (adjustedUnlockedBranch testmode) $ do
boolSystem "git" [Param "commit", Param "--allow-empty", Param "-m", Param "empty"] @? "git commit failed"
git_annex "adjust" ["--unlock"] @? "git annex adjust failed"
diff --git a/Types/GitConfig.hs b/Types/GitConfig.hs
index 7976f08..9e37bc1 100644
--- a/Types/GitConfig.hs
+++ b/Types/GitConfig.hs
@@ -103,6 +103,7 @@ data GitConfig = GitConfig
, annexMaxExtensionLength :: Maybe Int
, annexJobs :: Concurrency
, annexCacheCreds :: Bool
+ , annexAutoUpgradeRepository :: Bool
, coreSymlinks :: Bool
, coreSharedRepository :: SharedRepository
, receiveDenyCurrentBranch :: DenyCurrentBranch
@@ -182,6 +183,7 @@ extractGitConfig r = GitConfig
, annexJobs = fromMaybe NonConcurrent $
parseConcurrency =<< getmaybe (annex "jobs")
, annexCacheCreds = getbool (annex "cachecreds") True
+ , annexAutoUpgradeRepository = getbool (annex "autoupgraderepository") True
, coreSymlinks = getbool "core.symlinks" True
, coreSharedRepository = getSharedRepository r
, receiveDenyCurrentBranch = getDenyCurrentBranch r
diff --git a/Upgrade.hs b/Upgrade.hs
index 3535725..1cde059 100644
--- a/Upgrade.hs
+++ b/Upgrade.hs
@@ -1,6 +1,6 @@
{- git-annex upgrade support
-
- - Copyright 2010, 2013 Joey Hess <id@joeyh.name>
+ - Copyright 2010-2019 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
@@ -10,6 +10,8 @@
module Upgrade where
import Annex.Common
+import qualified Annex
+import qualified Git
import Annex.Version
import Types.RepoVersion
#ifndef mingw32_HOST_OS
@@ -36,14 +38,23 @@ needsUpgrade v
err "Upgrade this repository: git-annex upgrade"
| otherwise ->
err "Upgrade git-annex."
- Just newv -> ifM (upgrade True newv)
- ( ok
- , err "Automatic upgrade failed!"
+ Just newv -> ifM (annexAutoUpgradeRepository <$> Annex.getGitConfig)
+ ( tryNonAsync (upgrade True newv) >>= \case
+ Right True -> ok
+ Right False -> err "Automatic upgrade failed!"
+ Left ex -> err $ "Automatic upgrade exception! " ++ show ex
+ , err "Automatic upgrade is disabled by annex.autoupgraderepository configuration. To upgrade this repository: git-annex upgrade"
)
where
- err msg = return $ Just $ "Repository version " ++
- show (fromRepoVersion v) ++
- " is not supported. " ++ msg
+ err msg = do
+ g <- Annex.gitRepo
+ p <- liftIO $ absPath $ Git.repoPath g
+ return $ Just $ unwords
+ [ "Repository", p
+ , "is at unsupported version"
+ , show (fromRepoVersion v) ++ "."
+ , msg
+ ]
ok = return Nothing
upgrade :: Bool -> RepoVersion -> Annex Bool
@@ -74,3 +85,4 @@ upgrade automatic destversion = do
up (RepoVersion 5) = Upgrade.V5.upgrade automatic
up (RepoVersion 6) = Upgrade.V6.upgrade automatic
up _ = return True
+
diff --git a/Upgrade/V4.hs b/Upgrade/V4.hs
index 33f8d08..bb3cca0 100644
--- a/Upgrade/V4.hs
+++ b/Upgrade/V4.hs
@@ -8,16 +8,8 @@
module Upgrade.V4 where
import Annex.Common
-import Config
-import Annex.Direct
-{- Direct mode only upgrade. v4 to v5 indirect update is a no-op -}
+{- Was only used for direct mode upgrade. v4 to v5 indirect update is a no-op,
+ - and direct mode is no longer supported, so nothing needs to be done. -}
upgrade :: Bool -> Annex Bool
-upgrade automatic = ifM isDirect
- ( do
- unless automatic $
- showAction "v4 to v5"
- setDirect True
- return True
- , return True
- )
+upgrade _automatic = return True
diff --git a/Upgrade/V5.hs b/Upgrade/V5.hs
index cbde00a..5c8ed0a 100644
--- a/Upgrade/V5.hs
+++ b/Upgrade/V5.hs
@@ -1,6 +1,6 @@
{- git-annex v5 -> v6 upgrade support
-
- - Copyright 2015-2016 Joey Hess <id@joeyh.name>
+ - Copyright 2015-2019 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
@@ -13,78 +13,99 @@ import Config
import Config.Smudge
import Annex.InodeSentinal
import Annex.Link
-import Annex.Direct
-import Annex.Content
import Annex.CatFile
import Annex.WorkTree
+import Annex.UUID
+import Logs.Location
+import qualified Upgrade.V5.Direct as Direct
+import qualified Annex.Content as Content
import qualified Database.Keys
-import qualified Annex.Content.Direct as Direct
import qualified Git
import qualified Git.LsFiles
import qualified Git.Branch
+import qualified Git.Version
import Git.FilePath
import Git.FileMode
import Git.Config
import Git.Ref
import Utility.InodeCache
+import Utility.DottedVersion
import Annex.AdjustedBranch
import qualified Data.ByteString as S
upgrade :: Bool -> Annex Bool
-upgrade automatic = do
+upgrade automatic = flip catchNonAsync (const $ return False) $ do
unless automatic $
showAction "v5 to v6"
- whenM isDirect $ do
- {- Direct mode makes the same tradeoff of using less disk
- - space, with less preservation of old versions of files
- - as does annex.thin. -}
- setConfig (annexConfig "thin") (boolConfig True)
- Annex.changeGitConfig $ \c -> c { annexThin = True }
- {- Since upgrade from direct mode changes how files
- - are represented in git, by checking out an adjusted
- - branch, commit any changes in the work tree first. -}
- whenM stageDirect $ do
- unless automatic $
- showAction "committing first"
- upgradeDirectCommit automatic
- "commit before upgrade to annex.version 6"
- setDirect False
- cur <- fromMaybe (error "Somehow no branch is checked out")
- <$> inRepo Git.Branch.current
- upgradeDirectWorkTree
- removeDirectCruft
- {- Create adjusted branch where all files are unlocked.
- - This should have the same content for each file as
- - have been staged in upgradeDirectWorkTree. -}
- AdjBranch b <- adjustBranch (LinkAdjustment UnlockAdjustment) cur
- {- Since the work tree was already set up by
- - upgradeDirectWorkTree, and contains unlocked file
- - contents too, don't use git checkout to check out the
- - adjust branch. Instead, update HEAD manually. -}
- inRepo $ setHeadRef b
- scanUnlockedFiles
+ ifM isDirect
+ ( do
+ checkGitVersionForDirectUpgrade
+ convertDirect
+ -- Worktree files are already populated, so don't
+ -- have this try to populate them again.
+ scanUnlockedFiles False
+ , do
+ checkGitVersionForIndirectUpgrade
+ scanUnlockedFiles True
+ )
configureSmudgeFilter
-- Inode sentinal file was only used in direct mode and when
-- locking down files as they were added. In v6, it's used more
-- extensively, so make sure it exists, since old repos that didn't
-- use direct mode may not have created it.
- unlessM (isDirect) $
+ unlessM isDirect $
createInodeSentinalFile True
return True
-upgradeDirectCommit :: Bool -> String -> Annex ()
-upgradeDirectCommit automatic msg =
- void $ inRepo $ Git.Branch.commitCommand commitmode
- [ Param "-m"
- , Param msg
- ]
- where
- commitmode = if automatic then Git.Branch.AutomaticCommit else Git.Branch.ManualCommit
+-- git before 2.22 would OOM running git status on a large file.
+--
+-- Older versions of git that are patched (with
+-- commit 02156ab031e430bc45ce6984dfc712de9962dec8)
+-- can include "oomfix" in their version to indicate it.
+gitWillOOM :: Annex Bool
+gitWillOOM = liftIO $ do
+ v <- Git.Version.installed
+ return $ v < Git.Version.normalize "2.22" &&
+ not ("oomfix" `isInfixOf` fromDottedVersion v)
+
+-- configureSmudgeFilter has to run git status, and direct mode files
+-- are unlocked, so avoid the upgrade failing half way through.
+checkGitVersionForDirectUpgrade :: Annex ()
+checkGitVersionForDirectUpgrade = whenM gitWillOOM $
+ giveup "You must upgrade git to version 2.22 or newer in order to use this version of git-annex in this repository."
+
+checkGitVersionForIndirectUpgrade :: Annex ()
+checkGitVersionForIndirectUpgrade = whenM gitWillOOM $
+ warning "Git is older than version 2.22 and so it has a memory leak that affects using unlocked files. Recommend you upgrade git before unlocking any files in your repository."
+
+convertDirect :: Annex ()
+convertDirect = do
+ {- Direct mode makes the same tradeoff of using less disk
+ - space, with less preservation of old versions of files
+ - as does annex.thin. -}
+ setConfig (annexConfig "thin") (boolConfig True)
+ Annex.changeGitConfig $ \c -> c { annexThin = True }
+ Direct.setIndirect
+ cur <- fromMaybe (error "Somehow no branch is checked out")
+ <$> inRepo Git.Branch.current
+ upgradeDirectWorkTree
+ removeDirectCruft
+ {- Create adjusted branch where all files are unlocked.
+ - This should have the same content for each file as
+ - have been staged in upgradeDirectWorkTree. -}
+ AdjBranch b <- adjustBranch (LinkAdjustment UnlockAdjustment) cur
+ {- Since the work tree was already set up by
+ - upgradeDirectWorkTree, and contains unlocked file
+ - contents too, don't use git checkout to check out the
+ - adjust branch. Instead, update HEAD manually. -}
+ inRepo $ setHeadRef b
{- Walk work tree from top and convert all annex symlinks to pointer files,
- - staging them in the index, and updating the work tree files with
- - either the content of the object, or the pointer file content. -}
+ - staging them in the index, and populating the annex objects with
+ - hard links (or copies) of the work tree files (when not modified or
+ - deleted).
+ -}
upgradeDirectWorkTree :: Annex ()
upgradeDirectWorkTree = do
top <- fromRepo Git.repoPath
@@ -99,31 +120,41 @@ upgradeDirectWorkTree = do
case mk of
Nothing -> noop
Just k -> do
+ stagePointerFile f Nothing =<< hashPointerFile k
ifM (isJust <$> getAnnexLinkTarget f)
( writepointer f k
, fromdirect f k
)
- stagePointerFile f Nothing =<< hashPointerFile k
Database.Keys.addAssociatedFile k
=<< inRepo (toTopFilePath f)
- return ()
go _ = noop
- fromdirect f k = do
- -- If linkToAnnex fails for some reason, the work tree file
- -- still has the content; the annex object file is just
- -- not populated with it. Since the work tree file
- -- is recorded as an associated file, things will still
- -- work that way, it's just not ideal.
- ic <- withTSDelta (liftIO . genInodeCache f)
- void $ linkToAnnex k f ic
+ fromdirect f k = ifM (Direct.goodContent k f)
+ ( do
+ -- If linkToAnnex fails for some reason, the work tree
+ -- file still has the content; the annex object file
+ -- is just not populated with it. Since the work tree
+ -- file is recorded as an associated file, things will
+ -- still work that way, it's just not ideal.
+ ic <- withTSDelta (liftIO . genInodeCache f)
+ void $ Content.linkToAnnex k f ic
+ , unlessM (Content.inAnnex k) $ do
+ -- Worktree file was deleted or modified;
+ -- if there are no other copies of the content
+ -- then it's been lost.
+ locs <- Direct.associatedFiles k
+ unlessM (anyM (Direct.goodContent k) locs) $ do
+ u <- getUUID
+ logChange k u InfoMissing
+ )
+
writepointer f k = liftIO $ do
nukeFile f
S.writeFile f (formatPointer k)
{- Remove all direct mode bookkeeping files. -}
removeDirectCruft :: Annex ()
-removeDirectCruft = mapM_ go =<< getKeysPresent InAnywhere
+removeDirectCruft = mapM_ go =<< Content.listKeys Content.InAnywhere
where
go k = do
Direct.removeInodeCache k
diff --git a/Upgrade/V5/Direct.hs b/Upgrade/V5/Direct.hs
new file mode 100644
index 0000000..8b67bb3
--- /dev/null
+++ b/Upgrade/V5/Direct.hs
@@ -0,0 +1,126 @@
+{- git-annex direct mode
+ -
+ - This only contains some remnants needed to convert away from direct mode.
+ -
+ - Copyright 2012-2014 Joey Hess <id@joeyh.name>
+ -
+ - Licensed under the GNU AGPL version 3 or higher.
+ -}
+
+module Upgrade.V5.Direct (
+ switchHEADBack,
+ setIndirect,
+ goodContent,
+ associatedFiles,
+ removeAssociatedFiles,
+ removeInodeCache,
+) where
+
+import Annex.Common
+import qualified Annex
+import qualified Git
+import qualified Git.Config
+import qualified Git.Ref
+import qualified Git.Branch
+import Git.Types
+import Config
+import Annex.Perms
+import Utility.InodeCache
+import Annex.InodeSentinal
+
+setIndirect :: Annex ()
+setIndirect = do
+ setbare
+ switchHEADBack
+ setConfig (annexConfig "direct") val
+ Annex.changeGitConfig $ \c -> c { annexDirect = False }
+ where
+ val = Git.Config.boolConfig False
+ coreworktree = ConfigKey "core.worktree"
+ indirectworktree = ConfigKey "core.indirect-worktree"
+ setbare = do
+ -- core.worktree is not compatable with
+ -- core.bare; git does not allow both to be set, so
+ -- unset it when enabling direct mode, caching in
+ -- core.indirect-worktree
+ moveconfig indirectworktree coreworktree
+ setConfig (ConfigKey Git.Config.coreBare) val
+ moveconfig src dest = getConfigMaybe src >>= \case
+ Nothing -> noop
+ Just wt -> do
+ unsetConfig src
+ setConfig dest wt
+ reloadConfig
+
+{- Converts a directBranch back to the original branch.
+ -
+ - Any other ref is left unchanged.
+ -}
+fromDirectBranch :: Ref -> Ref
+fromDirectBranch directhead = case splitc '/' $ fromRef directhead of
+ ("refs":"heads":"annex":"direct":rest) ->
+ Ref $ "refs/heads/" ++ intercalate "/" rest
+ _ -> directhead
+
+switchHEADBack :: Annex ()
+switchHEADBack = maybe noop switch =<< inRepo Git.Branch.currentUnsafe
+ where
+ switch currhead = do
+ let orighead = fromDirectBranch currhead
+ inRepo (Git.Ref.sha currhead) >>= \case
+ Just headsha
+ | orighead /= currhead -> do
+ inRepo $ Git.Branch.update "leaving direct mode" orighead headsha
+ inRepo $ Git.Branch.checkout orighead
+ inRepo $ Git.Branch.delete currhead
+ _ -> inRepo $ Git.Branch.checkout orighead
+
+{- Absolute FilePaths of Files in the tree that are associated with a key. -}
+associatedFiles :: Key -> Annex [FilePath]
+associatedFiles key = do
+ files <- associatedFilesRelative key
+ top <- fromRepo Git.repoPath
+ return $ map (top </>) files
+
+{- List of files in the tree that are associated with a key, relative to
+ - the top of the repo. -}
+associatedFilesRelative :: Key -> Annex [FilePath]
+associatedFilesRelative key = do
+ mapping <- calcRepo $ gitAnnexMapping key
+ liftIO $ catchDefaultIO [] $ withFile mapping ReadMode $ \h ->
+ -- Read strictly to ensure the file is closed promptly
+ lines <$> hGetContentsStrict h
+
+{- Removes the list of associated files. -}
+removeAssociatedFiles :: Key -> Annex ()
+removeAssociatedFiles key = do
+ mapping <- calcRepo $ gitAnnexMapping key
+ modifyContent mapping $
+ liftIO $ nukeFile mapping
+
+{- Checks if a file in the tree, associated with a key, has not been modified.
+ -
+ - To avoid needing to fsck the file's content, which can involve an
+ - expensive checksum, this relies on a cache that contains the file's
+ - expected mtime and inode.
+ -}
+goodContent :: Key -> FilePath -> Annex Bool
+goodContent key file = sameInodeCache file =<< recordedInodeCache key
+
+{- Gets the recorded inode cache for a key.
+ -
+ - A key can be associated with multiple files, so may return more than
+ - one. -}
+recordedInodeCache :: Key -> Annex [InodeCache]
+recordedInodeCache key = withInodeCacheFile key $ \f ->
+ liftIO $ catchDefaultIO [] $
+ mapMaybe readInodeCache . lines <$> readFileStrict f
+
+{- Removes an inode cache. -}
+removeInodeCache :: Key -> Annex ()
+removeInodeCache key = withInodeCacheFile key $ \f ->
+ modifyContent f $
+ liftIO $ nukeFile f
+
+withInodeCacheFile :: Key -> (FilePath -> Annex a) -> Annex a
+withInodeCacheFile key a = a =<< calcRepo (gitAnnexInodeCache key)
diff --git a/Utility/CopyFile.hs b/Utility/CopyFile.hs
index 971fb5b..e3cdc46 100644
--- a/Utility/CopyFile.hs
+++ b/Utility/CopyFile.hs
@@ -35,7 +35,8 @@ copyMetaDataParams meta = map snd $ filter fst
allmeta = meta == CopyAllMetaData
{- The cp command is used, because I hate reinventing the wheel,
- - and because this allows easy access to features like cp --reflink. -}
+ - and because this allows easy access to features like cp --reflink
+ - and preserving metadata. -}
copyFileExternal :: CopyMetaData -> FilePath -> FilePath -> IO Bool
copyFileExternal meta src dest = do
-- Delete any existing dest file because an unwritable file
diff --git a/Utility/DottedVersion.hs b/Utility/DottedVersion.hs
index 3198b1c..c2a849b 100644
--- a/Utility/DottedVersion.hs
+++ b/Utility/DottedVersion.hs
@@ -18,7 +18,10 @@ instance Ord DottedVersion where
compare (DottedVersion _ x) (DottedVersion _ y) = compare x y
instance Show DottedVersion where
- show (DottedVersion s _) = s
+ show = fromDottedVersion
+
+fromDottedVersion :: DottedVersion -> String
+fromDottedVersion (DottedVersion s _) = s
{- To compare dotted versions like 1.7.7 and 1.8, they are normalized to
- a somewhat arbitrary integer representation. -}
diff --git a/Utility/InodeCache.hs b/Utility/InodeCache.hs
index af39219..fca478f 100644
--- a/Utility/InodeCache.hs
+++ b/Utility/InodeCache.hs
@@ -170,7 +170,9 @@ genInodeCache f delta = catchDefaultIO Nothing $
toInodeCache :: TSDelta -> FilePath -> FileStatus -> IO (Maybe InodeCache)
toInodeCache (TSDelta getdelta) f s
| isRegularFile s = do
+#ifndef mingw32_HOST_OS
delta <- getdelta
+#endif
sz <- getFileSize' f s
#ifdef mingw32_HOST_OS
mtime <- MTimeHighRes . utcTimeToPOSIXSeconds <$> getModificationTime f
diff --git a/Utility/Path/Max.hs b/Utility/Path/Max.hs
index 8ae35df..49e65d3 100644
--- a/Utility/Path/Max.hs
+++ b/Utility/Path/Max.hs
@@ -10,8 +10,6 @@
module Utility.Path.Max where
-import System.FilePath
-
#ifndef mingw32_HOST_OS
import Utility.Exception
import System.Posix.Files
diff --git a/doc/git-annex-add.mdwn b/doc/git-annex-add.mdwn
index da38600..d3d4c36 100644
--- a/doc/git-annex-add.mdwn
+++ b/doc/git-annex-add.mdwn
@@ -22,9 +22,8 @@ non-large file directly to the git repository, instead of to the annex.
Large files are added to the annex in locked form, which prevents further
modification of their content unless unlocked by [[git-annex-unlock]](1).
(This is not the case however when a repository is in a filesystem not
-supporting symlinks, or is in direct mode.)
-To add a file to the annex in unlocked form, `git add` can be used instead
-(that only works in repository v7 or higher).
+supporting symlinks.)
+To add a file to the annex in unlocked form, `git add` can be used instead.
This command can also be used to add symbolic links, both symlinks to
annexed content, and other symlinks.
diff --git a/doc/git-annex-adjust.mdwn b/doc/git-annex-adjust.mdwn
index c03a6e4..1b6a93f 100644
--- a/doc/git-annex-adjust.mdwn
+++ b/doc/git-annex-adjust.mdwn
@@ -34,8 +34,6 @@ while inside the adjusted branch will update the adjusted branch
as necessary (eg for `--hide-missing`), and will also propagate commits
back to the original branch.
-This command can only be used in a v7 git-annex repository.
-
# OPTIONS
* `--unlock`
diff --git a/doc/git-annex-contentlocation.mdwn b/doc/git-annex-contentlocation.mdwn
index a090e37..baba8d8 100644
--- a/doc/git-annex-contentlocation.mdwn
+++ b/doc/git-annex-contentlocation.mdwn
@@ -12,10 +12,6 @@ This plumbing-level command looks up filename used to store the content
of a key. The filename is output to stdout. If the key's content is not
present in the local repository, nothing is output, and it exits nonzero.
-Note that in direct mode, the file will typically be in the git work
-tree, and while its content should correspond to the key, the file
-could become modified at any time after git-annex checks it.
-
# OPTIONS
* `--batch`
diff --git a/doc/git-annex-direct.mdwn b/doc/git-annex-direct.mdwn
index 5e9a41a..909015a 100644
--- a/doc/git-annex-direct.mdwn
+++ b/doc/git-annex-direct.mdwn
@@ -1,6 +1,6 @@
# NAME
-git-annex direct - switch repository to direct mode
+git-annex direct - switch repository to direct mode (deprecated)
# SYNOPSIS
@@ -8,20 +8,9 @@ git annex direct
# DESCRIPTION
-Switches a repository to use direct mode, where rather than symlinks to
-files, the files are directly present in the repository.
-
-As part of the switch to direct mode, any changed files will be committed.
-
-Note that git commands that operate on the work tree will refuse to
-run in direct mode repositories. Use `git annex proxy` to safely run such
-commands.
-
-Note that the direct mode/indirect mode distinction is removed in v7
-git-annex repositories. In such a repository, you can
-use [[git-annex-unlock]](1) to make a file's content be directly present.
-You can also use [[git-annex-adjust]](1) to enter a branch where all
-annexed files are unlocked, which is similar to the old direct mode.
+This used to switch a repository to use direct mode.
+But direct mode is no longer used; git-annex automatically converts
+direct mode repositories to v7 adjusted unlocked branches.
# SEE ALSO
@@ -29,8 +18,6 @@ annexed files are unlocked, which is similar to the old direct mode.
[[git-annex-indirect]](1)
-[[git-annex-unlock]](1)
-
[[git-annex-adjust]](1)
# AUTHOR
diff --git a/doc/git-annex-examinekey.mdwn b/doc/git-annex-examinekey.mdwn
index 83baa56..c66225a 100644
--- a/doc/git-annex-examinekey.mdwn
+++ b/doc/git-annex-examinekey.mdwn
@@ -45,8 +45,7 @@ that can be determined purely by looking at the key.
# EXAMPLES
-The location a key's value is stored (in indirect mode)
-can be looked up by running:
+The location where the content of a key is stored can be looked up by running:
git annex examinekey $KEY --format='.git/annex/objects/${hashdirmixed}${key}/${key}'
diff --git a/doc/git-annex-indirect.mdwn b/doc/git-annex-indirect.mdwn
index c2bd4c5..4d35afa 100644
--- a/doc/git-annex-indirect.mdwn
+++ b/doc/git-annex-indirect.mdwn
@@ -1,6 +1,6 @@
# NAME
-git-annex indirect - switch repository to indirect mode
+git-annex indirect - switch repository to indirect mode (deprecated)
# SYNOPSIS
@@ -8,11 +8,11 @@ git annex indirect
# DESCRIPTION
-Switches a repository back from direct mode to the default, indirect
-mode.
+This command was used to switch a repository back from direct mode
+indirect mode.
-Note that the direct mode/indirect mode distinction is removed in v7
-git-annex repositories.
+Now git-annex automatically converts direct mode repositories to v7
+with adjusted unlocked branches, so this command does nothing.
# SEE ALSO
diff --git a/doc/git-annex-pre-commit.mdwn b/doc/git-annex-pre-commit.mdwn
index a08845b..0759e0d 100644
--- a/doc/git-annex-pre-commit.mdwn
+++ b/doc/git-annex-pre-commit.mdwn
@@ -17,9 +17,6 @@ point to annexed content.
When in a view, updates metadata to reflect changes
made to files in the view.
-When in a repository that has not been upgraded to v7,
-also handles injecting changes to unlocked files into the annex.
-
# SEE ALSO
[[git-annex]](1)
diff --git a/doc/git-annex-proxy.mdwn b/doc/git-annex-proxy.mdwn
index 2744b11..374bd27 100644
--- a/doc/git-annex-proxy.mdwn
+++ b/doc/git-annex-proxy.mdwn
@@ -1,6 +1,6 @@
# NAME
-git-annex proxy - safely bypass direct mode guard
+git-annex proxy - safely bypass direct mode guard (deprecated)
# SYNOPSIS
@@ -8,36 +8,9 @@ git annex proxy `-- git cmd [options]`
# DESCRIPTION
-Only useful in a direct mode repository, this runs the specified git
-command with a temporary work tree, and updates the working tree to
-reflect any changes staged or committed by the git command.
-
-For example, to revert the most recent change that was committed
-to the repository:
-
- git annex proxy -- git revert HEAD
-
-To check out a past version of the repository:
-
- git annex proxy -- git checkout HEAD^^
-
-To rename a directory:
-
- git annex proxy -- git mv mydir newname
-
-To commit the changes to a specific file, first use git annex add to
-stage the changes in the index, and then proxy a commit:
-
- git annex add myfile
- git annex proxy -- git commit myfile -m foo
-
-The temporary work tree that the git command is run in is set up by
-checking out all files that are in the index, and copying (or hard linking)
-any unstaged files from the real work tree. Since the git command is run
-using this temporary work tree, it won't see eg, local modifications to
-files. So, it probably is not useful to proxy a command like "git add".
-However, you can use the proxy with any git command you like, as long as
-you think about how it will interact with the temporary work tree.
+This command was for use in a direct mode repository, and such
+repositories are automatically updated to use an adjusted unlocked branch.
+So, there's no reason to use this command any longer.
# SEE ALSO
diff --git a/doc/git-annex-status.mdwn b/doc/git-annex-status.mdwn
index f322606..98a6c6f 100644
--- a/doc/git-annex-status.mdwn
+++ b/doc/git-annex-status.mdwn
@@ -14,8 +14,6 @@ in the working tree.
Show files that are not checked into git (?), deleted (D),
modified (M), added but not committed (A), and type changed/unlocked (T).
-Particularly useful in direct mode.
-
# OPTIONS
* `--ignore-submodules=when`
diff --git a/doc/git-annex-unlock.mdwn b/doc/git-annex-unlock.mdwn
index 9e93fc7..3dea02b 100644
--- a/doc/git-annex-unlock.mdwn
+++ b/doc/git-annex-unlock.mdwn
@@ -11,24 +11,26 @@ git annex unlock `[path ...]`
Normally, the content of annexed files is protected from being changed.
Unlocking an annexed file allows it to be modified. This replaces the
symlink for each specified file with the file's content.
-You can then modify it and `git annex add` (or `git commit`) to save your
-changes.
-
-In v5 repositories, unlocking a file is local
-to the repository, and is temporary. In v7 repositories, unlocking a file
-changes how it is stored in the git repository (from a symlink to a pointer
-file), so you can commit it like any other change. Also in v7, you
-can use `git add` to add a file to the annex in unlocked form. This allows
-workflows where a file starts out unlocked, is modified as necessary, and
-is locked once it reaches its final version.
-
-Normally, unlocking a file requires a copy to be made of its content,
-so that its original content is preserved, while the copy can be modified.
-To use less space, annex.thin can be set to true; this makes a hard link
-to the content be made instead of a copy. (Only when supported by the file
-system, and only in v7 and higher.) While this can save considerable
-disk space, any modification made to a file will cause the old version of the
-file to be lost from the local repository. So, enable annex.thin with care.
+
+Unlocking a file changes how it is stored in the git repository (from a
+symlink to a pointer file), so this command will make a change that you
+can commit.
+
+The content of an unlocked file is still stored in git-annex, not git,
+and when you commit modifications to the file, the modifications will also
+be stored in git-annex, with only the pointer file stored in git.
+
+If you use `git add` to add a file, it will be added in unlocked form from
+the beginning. This allows workflows where a file starts out unlocked, is
+modified as necessary, and is locked once it reaches its final version.
+
+Normally, unlocking a file requires a copy to be made of its content, so
+that its original content is preserved, while the copy can be modified. To
+use less space, annex.thin can be set to true; this makes a hard link to
+the content be made instead of a copy. (Only when supported by the file
+system.) While this can save considerable disk space, any modification made
+to a file will cause the old version of the file to be lost from the local
+repository. So, enable annex.thin with care.
# OPTIONS
diff --git a/doc/git-annex-upgrade.mdwn b/doc/git-annex-upgrade.mdwn
index 07b319c..c27fedd 100644
--- a/doc/git-annex-upgrade.mdwn
+++ b/doc/git-annex-upgrade.mdwn
@@ -1,6 +1,6 @@
# NAME
-git-annex upgrade - upgrade repository layout
+git-annex upgrade - upgrade repository
# SYNOPSIS
@@ -8,13 +8,16 @@ git annex upgrade
# DESCRIPTION
-Upgrades the repository to current layout.
+Upgrades the repository.
Each git-annex repository has an annex.version in its git configuration,
-that indicates the repository version. If git-annex changes to a new
-layout, you must upgrade the repository before git-annex can be used in it.
+that indicates the repository version. When an old repository version
+becomes deprecated, git-annex will automatically upgrade it
+(unless annex.autoupgraderepository is set to false). To manually upgrade,
+you can use this command.
-To see version information, run `git annex version`.
+Sometimes there's a newer repository version that is not the default yet,
+and then you can use this command to upgrade to it.
Currently, git-annex supports upgrades all the way back to version 0, which
was only used by its author. It's expected that git-annex will always
diff --git a/doc/git-annex.mdwn b/doc/git-annex.mdwn
index dc9868e..121e0d9 100644
--- a/doc/git-annex.mdwn
+++ b/doc/git-annex.mdwn
@@ -100,7 +100,7 @@ subdirectories).
* `status [path ...]`
Similar to `git status --short`, displays the status of the files in the
- working tree. Particularly useful in direct mode.
+ working tree.
See [[git-annex-status]](1) for details.
@@ -313,26 +313,25 @@ subdirectories).
See [[git-annex-vicfg]](1) for details.
+* `adjust`
+
+ Switches a repository to use an adjusted branch, which can automatically
+ unlock all files, etc.
+
+ See [[git-annex-adjust]](1) for details.
+
* `direct`
- Switches a repository to use direct mode, where rather than symlinks to
- files, the files are directly present in the repository.
+ Switches a repository to use direct mode. (deprecated)
See [[git-annex-direct]](1) for details.
* `indirect`
- Switches a repository back from direct mode to the default, indirect mode.
+ Switches a repository to use indirect mode. (deprecated)
See [[git-annex-indirect]](1) for details.
-* `adjust`
-
- Switches a repository to use an adjusted branch, which can automatically
- unlock all files, etc.
-
- See [[git-annex-adjust]](1) for details.
-
# REPOSITORY MAINTENANCE COMMANDS
* `fsck [path ...]`
@@ -384,7 +383,7 @@ subdirectories).
* `upgrade`
- Upgrades the repository to current layout.
+ Upgrades the repository.
See [[git-annex-upgrade]](1) for details.
@@ -665,20 +664,6 @@ subdirectories).
See [[git-annex-rekey]](1) for details.
-* `findref [ref]`
-
- Lists files in a git ref. (deprecated)
-
- See [[git-annex-findref]](1) for details.
-
-* `proxy -- git cmd [options]`
-
- Only useful in a direct mode repository, this runs the specified git
- command with a temporary work tree, and updates the working tree to
- reflect any changes staged or committed by the git command.
-
- See [[git-annex-proxy]](1) for details.
-
* `resolvemerge`
Resolves a conflicted merge, by adding both conflicting versions of the
@@ -708,6 +693,18 @@ subdirectories).
See [[git-annex-remotedaemon]](1) for details.
+* `findref [ref]`
+
+ Lists files in a git ref. (deprecated)
+
+ See [[git-annex-findref]](1) for details.
+
+* `proxy -- git cmd [options]`
+
+ Bypass direct mode guard. (deprecated)
+
+ See [[git-annex-proxy]](1) for details.
+
# TESTING COMMANDS
* `test`
@@ -839,10 +836,9 @@ may not be explicitly listed on their individual man pages.
Overrides git configuration settings. May be specified multiple times.
-# CONFIGURATION VIA .git/config
+# CONFIGURATION
Like other git commands, git-annex is configured via `.git/config`.
-Here are all the supported configuration settings.
* `annex.uuid`
@@ -911,7 +907,7 @@ Here are all the supported configuration settings.
Set to true to make commands like `git-annex add` that add files to the
repository add them in unlocked form. The default is to add files in
- locked form. This only has effect in v7 repositories.
+ locked form.
When a repository has core.symlinks set to false, it implicitly
sets annex.addunlocked to true.
@@ -1047,55 +1043,6 @@ Here are all the supported configuration settings.
And when multiple files in the work tree have the same content, only
one of them gets hard linked to the annex.
-* `annex.delayadd`
-
- Makes the watch and assistant commands delay for the specified number of
- seconds before adding a newly created file to the annex. Normally this
- is not needed, because they already wait for all writers of the file
- to close it. On Mac OSX, when not using direct mode this defaults to
- 1 second, to work around a bad interaction with software there.
-
-* `annex.expireunused`
-
- Controls what the assistant does about unused file contents
- that are stored in the repository.
-
- The default is `false`, which causes
- all old and unused file contents to be retained, unless the assistant
- is able to move them to some other repository (such as a backup repository).
-
- Can be set to a time specification, like "7d" or "1m", and then
- file contents that have been known to be unused for a week or a
- month will be deleted.
-
-* `annex.fscknudge`
-
- When set to false, prevents the webapp from reminding you when using
- repositories that lack consistency checks.
-
-* `annex.autoupgrade`
-
- When set to ask (the default), the webapp will check for new versions
- and prompt if they should be upgraded to. When set to true, automatically
- upgrades without prompting (on some supported platforms). When set to
- false, disables any upgrade checking.
-
- Note that upgrade checking is only done when git-annex is installed
- from one of the prebuilt images from its website. This does not
- bypass e.g., a Linux distribution's own upgrade handling code.
-
- This setting also controls whether to restart the git-annex assistant
- when the git-annex binary is detected to have changed. That is useful
- no matter how you installed git-annex.
-
-* `annex.autocommit`
-
- Set to false to prevent the git-annex assistant and git-annex sync
- from automatically committing changes to files in the repository.
-
- To configure the behavior in all clones of the repository,
- this can be set in [[git-annex-config]].
-
* `annex.resolvemerge`
Set to false to prevent merge conflicts in the checked out branch
@@ -1113,32 +1060,25 @@ Here are all the supported configuration settings.
To configure the behavior in all clones of the repository,
this can be set in [[git-annex-config]].
-* `annex.startupscan`
-
- Set to false to prevent the git-annex assistant from scanning the
- repository for new and changed files on startup. This will prevent it
- from noticing changes that were made while it was not running, but can be
- a useful performance tweak for a large repository.
-
-* `annex.listen`
-
- Configures which address the webapp listens on. The default is localhost.
- Can be either an IP address, or a hostname that resolves to the desired
- address.
-
* `annex.debug`
Set to true to enable debug logging by default.
* `annex.version`
- Automatically maintained, and used to automate upgrades between versions.
+ The current version of the git-annex repository. This is
+ maintained by git-annex and should never be manually changed.
+
+* `annex.autoupgraderepository`
-* `annex.direct`
+ When an old git-annex repository version has become deprecated,
+ git-annex will normally automatically upgrade the repository to
+ the new version.
- Set to true when the repository is in direct mode. Should not be set
- manually; use the "git annex direct" and "git annex indirect" commands
- instead.
+ If this is set to false, git-annex won't automatically upgrade the
+ repository. Instead it will exit with an error message. You can run
+ `git annex upgrade` yourself when you are ready to upgrade the
+ repository.
* `annex.crippledfilesystem`
@@ -1182,6 +1122,27 @@ Here are all the supported configuration settings.
be extracted and decrypted each time git-annex needs to access the
remote.
+* `annex.secure-erase-command`
+
+ This can be set to a command that should be run whenever git-annex
+ removes the content of a file from the repository.
+
+ In the command line, %file is replaced with the file that should be
+ erased.
+
+ For example, to use the wipe command, set it to `wipe -f %file`.
+
+* `annex.tune.objecthash1`, `annex.tune.objecthashlower`, `annex.tune.branchhash1`
+
+ These can be passed to `git annex init` to tune the repository.
+ They cannot be safely changed in a running repository and should never be
+ set in global git configuration.
+ For details, see <https://git-annex.branchable.com/tuning/>.
+
+# CONFIGURATION OF REMOTES
+
+Remotes are configured using these settings in `.git/config`.
+
* `remote.<name>.annex-cost`
When determining which repository to
@@ -1417,6 +1378,91 @@ Here are all the supported configuration settings.
Default options to use if a remote does not have more specific options
as described above.
+* `remote.<name>.annex-rsyncurl`
+
+ Used by rsync special remotes, this configures
+ the location of the rsync repository to use. Normally this is automatically
+ set up by `git annex initremote`, but you can change it if needed.
+
+* `remote.<name>.annex-buprepo`
+
+ Used by bup special remotes, this configures
+ the location of the bup repository to use. Normally this is automatically
+ set up by `git annex initremote`, but you can change it if needed.
+
+* `remote.<name>.annex-ddarrepo`
+
+ Used by ddar special remotes, this configures
+ the location of the ddar repository to use. Normally this is automatically
+ set up by `git annex initremote`, but you can change it if needed.
+
+* `remote.<name>.annex-directory`
+
+ Used by directory special remotes, this configures
+ the location of the directory where annexed files are stored for this
+ remote. Normally this is automatically set up by `git annex initremote`,
+ but you can change it if needed.
+
+* `remote.<name>.annex-adb`
+
+ Used to identify remotes on Android devices accessed via adb.
+ Normally this is automatically set up by `git annex initremote`.
+
+* `remote.<name>.annex-androiddirectory`
+
+ Used by adb special remotes, this is the directory on the Android
+ device where files are stored for this remote. Normally this is
+ automatically set up by `git annex initremote`, but you can change
+ it if needed.
+
+* `remote.<name>.annex-androidserial`
+
+ Used by adb special remotes, this is the serial number of the Android
+ device used by the remote. Normally this is automatically set up by
+ `git annex initremote`, but you can change it if needed, eg when
+ upgrading to a new Android device.
+
+* `remote.<name>.annex-s3`
+
+ Used to identify Amazon S3 special remotes.
+ Normally this is automatically set up by `git annex initremote`.
+
+* `remote.<name>.annex-glacier`
+
+ Used to identify Amazon Glacier special remotes.
+ Normally this is automatically set up by `git annex initremote`.
+
+* `remote.<name>.annex-webdav`
+
+ Used to identify webdav special remotes.
+ Normally this is automatically set up by `git annex initremote`.
+
+* `remote.<name>.annex-tahoe`
+
+ Used to identify tahoe special remotes.
+ Points to the configuration directory for tahoe.
+
+* `remote.<name>.annex-gcrypt`
+
+ Used to identify gcrypt special remotes.
+ Normally this is automatically set up by `git annex initremote`.
+
+ It is set to "true" if this is a gcrypt remote.
+ If the gcrypt remote is accessible over ssh and has git-annex-shell
+ available to manage it, it's set to "shell".
+
+* `remote.<name>.annex-git-lfs`
+
+ Used to identify git-lfs special remotes.
+ Normally this is automatically set up by `git annex initremote`.
+
+ It is set to "true" if this is a git-lfs remote.
+
+* `remote.<name>.annex-hooktype`, `remote.<name>.annex-externaltype`
+
+ Used by hook special remotes and external special remotes to record
+ the type of the remote.
+
* `annex.web-options`
Options to pass to curl when git-annex uses it to download urls
@@ -1532,111 +1578,72 @@ Here are all the supported configuration settings.
It would be a good idea to check that it downloaded the file you expected,
too.
-* `remote.name.annex-security-allow-unverified-downloads`
+* `remote.<name>.annex-security-allow-unverified-downloads`
Per-remote configuration of annex.security.allow-unverified-downloads.
-* `annex.secure-erase-command`
-
- This can be set to a command that should be run whenever git-annex
- removes the content of a file from the repository.
-
- In the command line, %file is replaced with the file that should be
- erased.
-
- For example, to use the wipe command, set it to `wipe -f %file`.
-
-* `remote.<name>.annex-rsyncurl`
-
- Used by rsync special remotes, this configures
- the location of the rsync repository to use. Normally this is automatically
- set up by `git annex initremote`, but you can change it if needed.
-
-* `remote.<name>.annex-buprepo`
-
- Used by bup special remotes, this configures
- the location of the bup repository to use. Normally this is automatically
- set up by `git annex initremote`, but you can change it if needed.
-
-* `remote.<name>.annex-ddarrepo`
-
- Used by ddar special remotes, this configures
- the location of the ddar repository to use. Normally this is automatically
- set up by `git annex initremote`, but you can change it if needed.
-
-* `remote.<name>.annex-directory`
-
- Used by directory special remotes, this configures
- the location of the directory where annexed files are stored for this
- remote. Normally this is automatically set up by `git annex initremote`,
- but you can change it if needed.
-
-* `remote.<name>.annex-adb`
-
- Used to identify remotes on Android devices accessed via adb.
- Normally this is automatically set up by `git annex initremote`.
-
-* `remote.<name>.annex-androiddirectory`
-
- Used by adb special remotes, this is the directory on the Android
- device where files are stored for this remote. Normally this is
- automatically set up by `git annex initremote`, but you can change
- it if needed.
-
-* `remote.<name>.annex-androidserial`
+# CONFIGURATION OF ASSISTANT
- Used by adb special remotes, this is the serial number of the Android
- device used by the remote. Normally this is automatically set up by
- `git annex initremote`, but you can change it if needed, eg when
- upgrading to a new Android device.
+* `annex.delayadd`
-* `remote.<name>.annex-s3`
+ Makes the watch and assistant commands delay for the specified number of
+ seconds before adding a newly created file to the annex. Normally this
+ is not needed, because they already wait for all writers of the file
+ to close it.
- Used to identify Amazon S3 special remotes.
- Normally this is automatically set up by `git annex initremote`.
+* `annex.expireunused`
-* `remote.<name>.annex-glacier`
+ Controls what the assistant does about unused file contents
+ that are stored in the repository.
- Used to identify Amazon Glacier special remotes.
- Normally this is automatically set up by `git annex initremote`.
+ The default is `false`, which causes
+ all old and unused file contents to be retained, unless the assistant
+ is able to move them to some other repository (such as a backup repository).
-* `remote.<name>.annex-webdav`
+ Can be set to a time specification, like "7d" or "1m", and then
+ file contents that have been known to be unused for a week or a
+ month will be deleted.
- Used to identify webdav special remotes.
- Normally this is automatically set up by `git annex initremote`.
+* `annex.fscknudge`
-* `remote.<name>.annex-tahoe`
+ When set to false, prevents the webapp from reminding you when using
+ repositories that lack consistency checks.
- Used to identify tahoe special remotes.
- Points to the configuration directory for tahoe.
+* `annex.autoupgrade`
-* `remote.<name>.annex-gcrypt`
+ When set to ask (the default), the webapp will check for new versions
+ and prompt if they should be upgraded to. When set to true, automatically
+ upgrades without prompting (on some supported platforms). When set to
+ false, disables any upgrade checking.
- Used to identify gcrypt special remotes.
- Normally this is automatically set up by `git annex initremote`.
+ Note that upgrade checking is only done when git-annex is installed
+ from one of the prebuilt images from its website. This does not
+ bypass e.g., a Linux distribution's own upgrade handling code.
- It is set to "true" if this is a gcrypt remote.
- If the gcrypt remote is accessible over ssh and has git-annex-shell
- available to manage it, it's set to "shell".
+ This setting also controls whether to restart the git-annex assistant
+ when the git-annex binary is detected to have changed. That is useful
+ no matter how you installed git-annex.
-* `remote.<name>.annex-git-lfs`
+* `annex.autocommit`
- Used to identify git-lfs special remotes.
- Normally this is automatically set up by `git annex initremote`.
+ Set to false to prevent the git-annex assistant and git-annex sync
+ from automatically committing changes to files in the repository.
- It is set to "true" if this is a git-lfs remote.
+ To configure the behavior in all clones of the repository,
+ this can be set in [[git-annex-config]].
-* `remote.<name>.annex-hooktype`, `remote.<name>.annex-externaltype`
+* `annex.startupscan`
- Used by hook special remotes and external special remotes to record
- the type of the remote.
+ Set to false to prevent the git-annex assistant from scanning the
+ repository for new and changed files on startup. This will prevent it
+ from noticing changes that were made while it was not running, but can be
+ a useful performance tweak for a large repository.
-* `annex.tune.objecthash1`, `annex.tune.objecthashlower`, `annex.tune.branchhash1`
+* `annex.listen`
- These can be passed to `git annex init` to tune the repository.
- They cannot be safely changed in a running repository and should never be
- set in global git configuration.
- For details, see <https://git-annex.branchable.com/tuning/>.
+ Configures which address the webapp listens on. The default is localhost.
+ Can be either an IP address, or a hostname that resolves to the desired
+ address.
# CONFIGURATION VIA .gitattributes
diff --git a/git-annex.cabal b/git-annex.cabal
index 7842ff4..c2a99e5 100644
--- a/git-annex.cabal
+++ b/git-annex.cabal
@@ -1,5 +1,5 @@
Name: git-annex
-Version: 7.20190819
+Version: 7.20190912
Cabal-Version: >= 1.8
License: AGPL-3
Maintainer: Joey Hess <id@joeyh.name>
@@ -577,7 +577,7 @@ Executable git-annex
Assistant.WebApp.RepoList
Assistant.WebApp.SideBar
Assistant.WebApp.Types
- Annex.MakeRepo
+ Assistant.MakeRepo
Utility.Yesod
Utility.WebApp
@@ -618,13 +618,11 @@ Executable git-annex
Annex.Common
Annex.Concurrent
Annex.Content
- Annex.Content.Direct
Annex.Content.LowLevel
Annex.Content.PointerFile
Annex.CurrentBranch
Annex.Difference
Annex.DirHashes
- Annex.Direct
Annex.Drop
Annex.Environment
Annex.Export
@@ -1011,6 +1009,7 @@ Executable git-annex
Upgrade.V3
Upgrade.V4
Upgrade.V5
+ Upgrade.V5.Direct
Upgrade.V6
Utility.Aeson
Utility.Android