summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Annex/Content.hs2
-rw-r--r--Annex/Init.hs12
-rw-r--r--Git/Objects.hs14
-rw-r--r--Logs/Trust.hs16
-rw-r--r--Logs/Trust/Basic.hs32
-rw-r--r--Remote/Git.hs18
-rw-r--r--Types/GitConfig.hs2
-rw-r--r--debian/changelog4
-rw-r--r--doc/git-annex.mdwn13
9 files changed, 94 insertions, 19 deletions
diff --git a/Annex/Content.hs b/Annex/Content.hs
index 6e5131f77..c0c79ae56 100644
--- a/Annex/Content.hs
+++ b/Annex/Content.hs
@@ -377,7 +377,7 @@ sendAnnex key rollback sendobject = go =<< prepSendAnnex key
)
{- Returns a file that contains an object's content,
- - and an check to run after the transfer is complete.
+ - and a check to run after the transfer is complete.
-
- In direct mode, it's possible for the file to change as it's being sent,
- and the check detects this case and returns False.
diff --git a/Annex/Init.hs b/Annex/Init.hs
index 637b130ee..2f7b66fbc 100644
--- a/Annex/Init.hs
+++ b/Annex/Init.hs
@@ -23,8 +23,11 @@ import qualified Git.LsFiles
import qualified Git.Config
import qualified Git.Construct
import qualified Git.Types as Git
+import qualified Git.Objects
import qualified Annex.Branch
import Logs.UUID
+import Logs.Trust.Basic
+import Types.TrustLevel
import Annex.Version
import Annex.UUID
import Config
@@ -70,6 +73,7 @@ initialize mdescription = do
Annex.Branch.create
describeUUID u =<< genDescription mdescription
+-- Everything except for uuid setup.
initialize' :: Annex ()
initialize' = do
checkFifoSupport
@@ -87,6 +91,7 @@ initialize' = do
switchHEADBack
)
createInodeSentinalFile
+ checkSharedClone
uninitialize :: Annex ()
uninitialize = do
@@ -242,3 +247,10 @@ checkBadBare = allM (not <$>)
where
hasPreCommitHook = inRepo $ doesFileExist . hookFile preCommitHook
hasDotGitHEAD = inRepo $ \r -> doesFileExist $ Git.localGitDir r </> "HEAD"
+
+checkSharedClone :: Annex ()
+checkSharedClone = whenM (inRepo Git.Objects.isSharedClone) $ do
+ showSideAction "Repository was cloned with --shared; setting annex.hardlink=true and making repository untrusted."
+ u <- getUUID
+ trustSet u UnTrusted
+ setConfig (annexConfig "hardlink") (Git.Config.boolConfig True)
diff --git a/Git/Objects.hs b/Git/Objects.hs
index 516aa6d3e..dadd4f543 100644
--- a/Git/Objects.hs
+++ b/Git/Objects.hs
@@ -33,3 +33,17 @@ looseObjectFile :: Repo -> Sha -> FilePath
looseObjectFile r sha = objectsDir r </> prefix </> rest
where
(prefix, rest) = splitAt 2 (fromRef sha)
+
+listAlternates :: Repo -> IO [FilePath]
+listAlternates r = catchDefaultIO [] (lines <$> readFile alternatesfile)
+ where
+ alternatesfile = objectsDir r </> "info" </> "alternates"
+
+{- A repository recently cloned with --shared will have one or more
+ - alternates listed, and contain no loose objects or packs. -}
+isSharedClone :: Repo -> IO Bool
+isSharedClone r = allM id
+ [ not . null <$> listAlternates r
+ , null <$> listLooseObjectShas r
+ , null <$> listPackFiles r
+ ]
diff --git a/Logs/Trust.hs b/Logs/Trust.hs
index c6f0ad3ab..047a728f4 100644
--- a/Logs/Trust.hs
+++ b/Logs/Trust.hs
@@ -11,7 +11,6 @@ module Logs.Trust (
TrustLevel(..),
trustGet,
trustMap,
- trustSet,
trustPartition,
trustExclude,
lookupTrust,
@@ -20,17 +19,15 @@ module Logs.Trust (
) where
import qualified Data.Map as M
-import Data.Time.Clock.POSIX
import Common.Annex
import Types.TrustLevel
import qualified Annex.Branch
import qualified Annex
import Logs
-import Logs.UUIDBased
import Remote.List
import qualified Types.Remote
-import Logs.Trust.Pure as X
+import Logs.Trust.Basic as X
{- Returns a list of UUIDs that the trustLog indicates have the
- specified trust level.
@@ -39,17 +36,6 @@ import Logs.Trust.Pure as X
trustGet :: TrustLevel -> Annex [UUID]
trustGet level = M.keys . M.filter (== level) <$> trustMap
-{- Changes the trust level for a uuid in the trustLog. -}
-trustSet :: UUID -> TrustLevel -> Annex ()
-trustSet uuid@(UUID _) level = do
- ts <- liftIO getPOSIXTime
- Annex.Branch.change trustLog $
- showLog showTrustLog .
- changeLog ts uuid level .
- parseLog (Just . parseTrustLog)
- Annex.changeState $ \s -> s { Annex.trustmap = Nothing }
-trustSet NoUUID _ = error "unknown UUID; cannot modify"
-
{- Returns the TrustLevel of a given repo UUID. -}
lookupTrust :: UUID -> Annex TrustLevel
lookupTrust u = (fromMaybe SemiTrusted . M.lookup u) <$> trustMap
diff --git a/Logs/Trust/Basic.hs b/Logs/Trust/Basic.hs
new file mode 100644
index 000000000..646e2e037
--- /dev/null
+++ b/Logs/Trust/Basic.hs
@@ -0,0 +1,32 @@
+{- git-annex trust log, basics
+ -
+ - Copyright 2010-2012 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Logs.Trust.Basic (
+ module X,
+ trustSet,
+) where
+
+import Data.Time.Clock.POSIX
+
+import Common.Annex
+import Types.TrustLevel
+import qualified Annex.Branch
+import qualified Annex
+import Logs
+import Logs.UUIDBased
+import Logs.Trust.Pure as X
+
+{- Changes the trust level for a uuid in the trustLog. -}
+trustSet :: UUID -> TrustLevel -> Annex ()
+trustSet uuid@(UUID _) level = do
+ ts <- liftIO getPOSIXTime
+ Annex.Branch.change trustLog $
+ showLog showTrustLog .
+ changeLog ts uuid level .
+ parseLog (Just . parseTrustLog)
+ Annex.changeState $ \s -> s { Annex.trustmap = Nothing }
+trustSet NoUUID _ = error "unknown UUID; cannot modify"
diff --git a/Remote/Git.hs b/Remote/Git.hs
index 0c760c3aa..6397c1a2e 100644
--- a/Remote/Git.hs
+++ b/Remote/Git.hs
@@ -355,15 +355,27 @@ copyFromRemote' r key file dest
| not $ Git.repoIsUrl (repo r) = guardUsable (repo r) (return False) $ do
params <- Ssh.rsyncParams r Download
u <- getUUID
+ hardlink <- annexHardLink <$> Annex.getGitConfig
-- run copy from perspective of remote
onLocal r $ do
ensureInitialized
v <- Annex.Content.prepSendAnnex key
case v of
Nothing -> return False
- Just (object, checksuccess) ->
- runTransfer (Transfer Download u key) file noRetry
- (rsyncOrCopyFile params object dest)
+ Just (object, checksuccess) -> do
+ let copier = rsyncOrCopyFile params object dest
+#ifndef mingw32_HOST_OS
+ let linker = createLink object dest >> return True
+ go <- ifM (pure hardlink <&&> not <$> isDirect)
+ ( return $ \m -> liftIO (catchBoolIO linker)
+ <||> copier m
+ , return copier
+ )
+#else
+ let go = copier
+#endif
+ runTransfer (Transfer Download u key)
+ file noRetry go
<&&> checksuccess
| Git.repoIsSsh (repo r) = feedprogressback $ \feeder -> do
direct <- isDirect
diff --git a/Types/GitConfig.hs b/Types/GitConfig.hs
index 29a7c9019..deae1df37 100644
--- a/Types/GitConfig.hs
+++ b/Types/GitConfig.hs
@@ -52,6 +52,7 @@ data GitConfig = GitConfig
, annexGenMetaData :: Bool
, annexListen :: Maybe String
, annexStartupScan :: Bool
+ , annexHardLink :: Bool
, coreSymlinks :: Bool
, gcryptId :: Maybe String
}
@@ -87,6 +88,7 @@ extractGitConfig r = GitConfig
, annexGenMetaData = getbool (annex "genmetadata") False
, annexListen = getmaybe (annex "listen")
, annexStartupScan = getbool (annex "startupscan") True
+ , annexHardLink = getbool (annex "hardlink") False
, coreSymlinks = getbool "core.symlinks" True
, gcryptId = getmaybe "core.gcrypt-id"
}
diff --git a/debian/changelog b/debian/changelog
index bc6668b0a..eb917a0b9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,6 +1,10 @@
git-annex (5.20140832) UNRELEASED; urgency=medium
* webapp: Fixed visual glitch in xmpp pairing.
+ * New annex.hardlink setting. Closes: #758593
+ * init: Automatically detect when a repository was cloned with --shared,
+ and set annex.hardlink=true, as well as marking the repository as
+ untrusted.
-- Joey Hess <joeyh@debian.org> Thu, 04 Sep 2014 16:17:22 -0400
diff --git a/doc/git-annex.mdwn b/doc/git-annex.mdwn
index 11e086a8c..224580d97 100644
--- a/doc/git-annex.mdwn
+++ b/doc/git-annex.mdwn
@@ -1433,6 +1433,19 @@ Here are all the supported configuration settings.
commit the data by running `git annex merge` (or by automatic merges)
or `git annex sync`.
+* `annex.hardlink`
+
+ Set this to `true` to make file contents be hard linked into the
+ repository when possible, instead of a more expensive copy.
+
+ Use with caution -- This can invalidate numcopies counting, since
+ with hard links, fewer copies of a file can exist. So, it is a good
+ idea to mark a repository using this setting as untrusted.
+
+ When a repository is set up using `git clone --shared`, git-annex init
+ will automatically set annex.hardlink and mark the repository as
+ untrusted.
+
* `annex.delayadd`
Makes the watch and assistant commands delay for the specified number of