summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Annex.hs2
-rw-r--r--Backend/SHA.hs3
-rw-r--r--Command/Migrate.hs2
-rw-r--r--Command/SetKey.hs3
-rw-r--r--Command/Unlock.hs2
-rw-r--r--Command/Unused.hs27
-rw-r--r--Command/Upgrade.hs2
-rw-r--r--Content.hs50
-rw-r--r--Makefile2
-rw-r--r--Options.hs3
-rw-r--r--StatFS.hsc121
-rw-r--r--Upgrade/V0.hs2
-rw-r--r--Upgrade/V1.hs5
-rw-r--r--debian/changelog17
-rw-r--r--debian/copyright4
-rw-r--r--doc/bugs/free_space_checking.mdwn3
-rw-r--r--doc/git-annex.mdwn14
18 files changed, 248 insertions, 15 deletions
diff --git a/.gitignore b/.gitignore
index 69d2c8070..aa677c133 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,4 @@ html
*.tix
.hpc
Touch.hs
+StatFS.hs
diff --git a/Annex.hs b/Annex.hs
index 608151d82..f45415a72 100644
--- a/Annex.hs
+++ b/Annex.hs
@@ -40,6 +40,7 @@ data AnnexState = AnnexState
, repoqueue :: GitQueue.Queue
, quiet :: Bool
, force :: Bool
+ , fast :: Bool
, defaultbackend :: Maybe String
, defaultkey :: Maybe String
, toremote :: Maybe String
@@ -56,6 +57,7 @@ newState gitrepo allbackends = AnnexState
, repoqueue = GitQueue.empty
, quiet = False
, force = False
+ , fast = False
, defaultbackend = Nothing
, defaultkey = Nothing
, toremote = Nothing
diff --git a/Backend/SHA.hs b/Backend/SHA.hs
index 056385107..0ec555ce3 100644
--- a/Backend/SHA.hs
+++ b/Backend/SHA.hs
@@ -80,9 +80,10 @@ keyValue size file = do
checkKeyChecksum :: SHASize -> Key -> Annex Bool
checkKeyChecksum size key = do
g <- Annex.gitRepo
+ fast <- Annex.getState Annex.fast
let file = gitAnnexLocation g key
present <- liftIO $ doesFileExist file
- if not present
+ if (not present || fast)
then return True
else do
s <- shaN size file
diff --git a/Command/Migrate.hs b/Command/Migrate.hs
index 584f6e34e..56147113b 100644
--- a/Command/Migrate.hs
+++ b/Command/Migrate.hs
@@ -55,7 +55,7 @@ perform file oldkey newbackend = do
case stored of
Nothing -> return Nothing
Just (newkey, _) -> do
- ok <- getViaTmp newkey $ \t -> do
+ ok <- getViaTmpUnchecked newkey $ \t -> do
-- Make a hard link to the old backend's
-- cached key, to avoid wasting disk space.
liftIO $ createLink src t
diff --git a/Command/SetKey.hs b/Command/SetKey.hs
index af46fe06e..6f6078e4b 100644
--- a/Command/SetKey.hs
+++ b/Command/SetKey.hs
@@ -32,7 +32,8 @@ perform :: FilePath -> CommandPerform
perform file = do
key <- cmdlineKey
-- the file might be on a different filesystem, so mv is used
- -- rather than simply calling moveToObjectDir
+ -- rather than simply calling moveToObjectDir; disk space is also
+ -- checked this way.
ok <- getViaTmp key $ \dest -> do
if dest /= file
then liftIO $
diff --git a/Command/Unlock.hs b/Command/Unlock.hs
index ac7b22ac7..bf593e1e9 100644
--- a/Command/Unlock.hs
+++ b/Command/Unlock.hs
@@ -41,6 +41,8 @@ perform dest key = do
inbackend <- Backend.hasKey key
when (not inbackend) $
error "content not present"
+
+ checkDiskSpace key
g <- Annex.gitRepo
let src = gitAnnexLocation g key
diff --git a/Command/Unused.hs b/Command/Unused.hs
index a1c4ee03c..518e98656 100644
--- a/Command/Unused.hs
+++ b/Command/Unused.hs
@@ -44,7 +44,6 @@ perform = do
checkUnused :: Annex Bool
checkUnused = do
- showNote "checking for unused data..."
(unused, staletmp) <- unusedKeys
let unusedlist = number 0 unused
let staletmplist = number (length unused) staletmp
@@ -81,17 +80,27 @@ number n (x:xs) = (n+1, x):(number (n+1) xs)
unusedKeys :: Annex ([Key], [Key])
unusedKeys = do
g <- Annex.gitRepo
- present <- getKeysPresent
- referenced <- getKeysReferenced
- tmps <- tmpKeys
- let (unused, staletmp, duptmp) = calcUnusedKeys present referenced tmps
+ fast <- Annex.getState Annex.fast
+ if fast
+ then do
+ showNote "fast mode enabled; assuming all temporary files are unused"
+ tmps <- tmpKeys
+ return ([], tmps)
+ else do
+ showNote "checking for unused data..."
+ present <- getKeysPresent
+ referenced <- getKeysReferenced
+ tmps <- tmpKeys
+
+ let (unused, staletmp, duptmp) = calcUnusedKeys present referenced tmps
- -- Tmp files that are dups of content already present can simply
- -- be removed.
- liftIO $ forM_ duptmp $ \t -> removeFile $ gitAnnexTmpLocation g t
+ -- Tmp files that are dups of content already present
+ -- can simply be removed.
+ liftIO $ forM_ duptmp $ \t -> removeFile $
+ gitAnnexTmpLocation g t
- return (unused, staletmp)
+ return (unused, staletmp)
calcUnusedKeys :: [Key] -> [Key] -> [Key] -> ([Key], [Key], [Key])
calcUnusedKeys present referenced tmps = (unused, staletmp, duptmp)
diff --git a/Command/Upgrade.hs b/Command/Upgrade.hs
index 94398c70a..880a5324f 100644
--- a/Command/Upgrade.hs
+++ b/Command/Upgrade.hs
@@ -10,6 +10,7 @@ module Command.Upgrade where
import Command
import Upgrade
import Version
+import Messages
command :: [Command]
command = [standaloneCommand "upgrade" paramNothing seek
@@ -20,6 +21,7 @@ seek = [withNothing start]
start :: CommandStartNothing
start = do
+ showStart "upgrade" ""
r <- upgrade
checkVersion
return $ Just $ return $ Just $ return r
diff --git a/Content.hs b/Content.hs
index 4bd8265c2..39a3addcc 100644
--- a/Content.hs
+++ b/Content.hs
@@ -10,6 +10,8 @@ module Content (
calcGitLink,
logStatus,
getViaTmp,
+ getViaTmpUnchecked,
+ checkDiskSpace,
preventWrite,
allowWrite,
moveAnnex,
@@ -35,6 +37,8 @@ import UUID
import qualified GitRepo as Git
import qualified Annex
import Utility
+import StatFS
+import Key
{- Checks if a given key is currently present in the gitAnnexLocation. -}
inAnnex :: Key -> Annex Bool
@@ -75,6 +79,27 @@ getViaTmp :: Key -> (FilePath -> Annex Bool) -> Annex Bool
getViaTmp key action = do
g <- Annex.gitRepo
let tmp = gitAnnexTmpLocation g key
+
+ -- Check that there is enough free disk space.
+ -- When the temp file already exists, count the space
+ -- it is using as free.
+ e <- liftIO $ doesFileExist tmp
+ if e
+ then do
+ stat <- liftIO $ getFileStatus tmp
+ checkDiskSpace' (fromIntegral $ fileSize stat) key
+ else checkDiskSpace key
+
+ getViaTmpUnchecked key action
+
+{- Like getViaTmp, but does not check that there is enough disk space
+ - for the incoming key. For use when the key content is already on disk
+ - and not being copied into place. -}
+getViaTmpUnchecked :: Key -> (FilePath -> Annex Bool) -> Annex Bool
+getViaTmpUnchecked key action = do
+ g <- Annex.gitRepo
+ let tmp = gitAnnexTmpLocation g key
+
liftIO $ createDirectoryIfMissing True (parentDir tmp)
success <- action tmp
if success
@@ -87,6 +112,31 @@ getViaTmp key action = do
-- to resume its transfer
return False
+{- Checks that there is disk space available to store a given key,
+ - throwing an error if not. -}
+checkDiskSpace :: Key -> Annex ()
+checkDiskSpace = checkDiskSpace' 0
+
+checkDiskSpace' :: Integer -> Key -> Annex ()
+checkDiskSpace' adjustment key = do
+ g <- Annex.gitRepo
+ r <- Annex.repoConfig g "diskreserve" ""
+ let reserve = if null r then megabyte else (read r :: Integer)
+ stats <- liftIO $ getFileSystemStats (gitAnnexDir g)
+ case (stats, keySize key) of
+ (Nothing, _) -> return ()
+ (_, Nothing) -> return ()
+ (Just (FileSystemStats { fsStatBytesAvailable = have }), Just need) ->
+ if (need + reserve > have + adjustment)
+ then error $ "not enough free space (have " ++
+ showsize (have + adjustment) ++ "; need " ++
+ showsize (need + reserve) ++ ")"
+ else return ()
+ where
+ showsize i = show i
+ megabyte :: Integer
+ megabyte = 1024 * 1024
+
{- Removes the write bits from a file. -}
preventWrite :: FilePath -> IO ()
preventWrite f = unsetFileMode f writebits
diff --git a/Makefile b/Makefile
index c60e19b31..08e2f59fb 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@ SysConfig.hs: configure.hs TestConfig.hs
$(GHCMAKE) configure
./configure
-Touch.hs: Touch.hsc
+%.hs: %.hsc
hsc2hs $<
perl -i -pe 's/^{-# INCLUDE.*//' $@
diff --git a/Options.hs b/Options.hs
index 4cd62c222..10c3714e4 100644
--- a/Options.hs
+++ b/Options.hs
@@ -22,6 +22,8 @@ commonOptions :: [Option]
commonOptions =
[ Option ['f'] ["force"] (NoArg (setforce True))
"allow actions that may lose annexed data"
+ , Option ['F'] ["fast"] (NoArg (setfast True))
+ "avoid slow operations"
, Option ['q'] ["quiet"] (NoArg (setquiet True))
"avoid verbose output"
, Option ['v'] ["verbose"] (NoArg (setquiet False))
@@ -31,5 +33,6 @@ commonOptions =
]
where
setforce v = Annex.changeState $ \s -> s { Annex.force = v }
+ setfast v = Annex.changeState $ \s -> s { Annex.fast = v }
setquiet v = Annex.changeState $ \s -> s { Annex.quiet = v }
setdefaultbackend v = Annex.changeState $ \s -> s { Annex.defaultbackend = Just v }
diff --git a/StatFS.hsc b/StatFS.hsc
new file mode 100644
index 000000000..8b453dc19
--- /dev/null
+++ b/StatFS.hsc
@@ -0,0 +1,121 @@
+-----------------------------------------------------------------------------
+-- |
+--
+-- (This code originally comes from xmobar)
+--
+-- Module : StatFS
+-- Copyright : (c) Jose A Ortega Ruiz
+-- License : BSD-3-clause
+--
+-- All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions
+-- are met:
+--
+-- 1. Redistributions of source code must retain the above copyright
+-- notice, this list of conditions and the following disclaimer.
+-- 2. Redistributions in binary form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+-- 3. Neither the name of the author nor the names of his contributors
+-- may be used to endorse or promote products derived from this software
+-- without specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+-- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+-- SUCH DAMAGE.
+--
+-- Maintainer : Jose A Ortega Ruiz <jao@gnu.org>
+-- Stability : unstable
+-- Portability : unportable
+--
+-- A binding to C's statvfs(2)
+--
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP, ForeignFunctionInterface, EmptyDataDecls #-}
+
+
+module StatFS ( FileSystemStats(..), getFileSystemStats ) where
+
+import Foreign
+import Foreign.C.Types
+import Foreign.C.String
+import Data.ByteString (useAsCString)
+import Data.ByteString.Char8 (pack)
+
+#if defined (__FreeBSD__)
+# include <sys/param.h>
+# include <sys/mount.h>
+#else
+#if defined (__linux__)
+#include <sys/vfs.h>
+#else
+#define UNKNOWN
+#endif
+#endif
+
+data FileSystemStats = FileSystemStats {
+ fsStatBlockSize :: Integer
+ -- ^ Optimal transfer block size.
+ , fsStatBlockCount :: Integer
+ -- ^ Total data blocks in file system.
+ , fsStatByteCount :: Integer
+ -- ^ Total bytes in file system.
+ , fsStatBytesFree :: Integer
+ -- ^ Free bytes in file system.
+ , fsStatBytesAvailable :: Integer
+ -- ^ Free bytes available to non-superusers.
+ , fsStatBytesUsed :: Integer
+ -- ^ Bytes used.
+ } deriving (Show, Eq)
+
+data CStatfs
+
+#ifdef UNKNOWN
+#warning free space checking code not available for this OS
+#else
+#if defined(__FreeBSD__)
+foreign import ccall unsafe "sys/mount.h statfs"
+#else
+foreign import ccall unsafe "sys/vfs.h statfs64"
+#endif
+ c_statfs :: CString -> Ptr CStatfs -> IO CInt
+#endif
+
+toI :: CLong -> Integer
+toI = toInteger
+
+getFileSystemStats :: String -> IO (Maybe FileSystemStats)
+getFileSystemStats path =
+#ifdef UNKNOWN
+ return Nothing
+#else
+ allocaBytes (#size struct statfs) $ \vfs ->
+ useAsCString (pack path) $ \cpath -> do
+ res <- c_statfs cpath vfs
+ if res == -1 then return Nothing
+ else do
+ bsize <- (#peek struct statfs, f_bsize) vfs
+ bcount <- (#peek struct statfs, f_blocks) vfs
+ bfree <- (#peek struct statfs, f_bfree) vfs
+ bavail <- (#peek struct statfs, f_bavail) vfs
+ let bpb = toI bsize
+ return $ Just FileSystemStats
+ { fsStatBlockSize = bpb
+ , fsStatBlockCount = toI bcount
+ , fsStatByteCount = toI bcount * bpb
+ , fsStatBytesFree = toI bfree * bpb
+ , fsStatBytesAvailable = toI bavail * bpb
+ , fsStatBytesUsed = toI (bcount - bfree) * bpb
+ }
+#endif
diff --git a/Upgrade/V0.hs b/Upgrade/V0.hs
index 5ba305817..eabd03009 100644
--- a/Upgrade/V0.hs
+++ b/Upgrade/V0.hs
@@ -23,7 +23,7 @@ import qualified Upgrade.V1
upgrade :: Annex Bool
upgrade = do
- showSideAction "Upgrading object directory layout v0 to v1..."
+ showNote "v0 to v1..."
g <- Annex.gitRepo
-- do the reorganisation of the key files
diff --git a/Upgrade/V1.hs b/Upgrade/V1.hs
index 43f279ad0..c0470a3bc 100644
--- a/Upgrade/V1.hs
+++ b/Upgrade/V1.hs
@@ -55,7 +55,7 @@ import qualified Command.Init
upgrade :: Annex Bool
upgrade = do
- showSideAction "Upgrading object directory layout v1 to v2..."
+ showNote "v1 to v2"
g <- Annex.gitRepo
if Git.repoIsLocalBare g
@@ -78,6 +78,7 @@ upgrade = do
moveContent :: Annex ()
moveContent = do
+ showNote "moving content..."
keys <- getKeysPresent1
forM_ keys move
where
@@ -92,6 +93,7 @@ moveContent = do
updateSymlinks :: Annex ()
updateSymlinks = do
+ showNote "updating symlinks..."
g <- Annex.gitRepo
files <- liftIO $ Git.inRepo g [Git.workTree g]
forM_ files $ fixlink
@@ -109,6 +111,7 @@ updateSymlinks = do
moveLocationLogs :: Annex ()
moveLocationLogs = do
+ showNote "moving location logs..."
logkeys <- oldlocationlogs
forM_ logkeys move
where
diff --git a/debian/changelog b/debian/changelog
index eb8d73504..88e0986a9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,20 @@
+git-annex (0.20110321) UNRELEASED; urgency=low
+
+ * Free space checking is now done, for transfers of data for keys
+ that have free space metadata. (Notably, not for SHA* keys generated
+ with git-annex 0.24 or earlier.) The code is believed to work on
+ Linux, FreeBSD, and OSX; check compile-time messages to see if it
+ is not enabled for your OS.
+ * Add annex.diskreserve config setting, to control how much free space
+ to reserve for other purposes and avoid using (defaults to 1 mb).
+ * Add --fast flag, that can enable less expensive, but also less thurough
+ versions of some commands.
+ * fsck: In fast mode, avoid checking checksums.
+ * unused: In fast mode, just show all existing temp files as unused,
+ and avoid expensive scan for other unused content.
+
+ -- Joey Hess <joeyh@debian.org> Tue, 22 Mar 2011 16:52:00 -0400
+
git-annex (0.20110320) experimental; urgency=low
* Fix dropping of files using the URL backend.
diff --git a/debian/copyright b/debian/copyright
index 90e26b752..2144501e1 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -7,3 +7,7 @@ License: GPL-3+
The full text of version 3 of the GPL is distributed as doc/GPL in
this package's source, or in /usr/share/common-licenses/GPL-3 on
Debian systems.
+
+Files: StatFS.hsc
+Copyright: Jose A Ortega Ruiz <jao@gnu.org>
+License: BSD-3-clause
diff --git a/doc/bugs/free_space_checking.mdwn b/doc/bugs/free_space_checking.mdwn
index eaa3294d6..92e8be40d 100644
--- a/doc/bugs/free_space_checking.mdwn
+++ b/doc/bugs/free_space_checking.mdwn
@@ -16,3 +16,6 @@ file around.
find files that lack size info, and rename their keys to add the size
info. Users with old repos can run this on them, to get the missing
info recorded.
+
+> [[done]]; no migtation process for old SHA1 keys from v1 repo though.
+> --[[Joey]]
diff --git a/doc/git-annex.mdwn b/doc/git-annex.mdwn
index 1e4af022f..3cf408939 100644
--- a/doc/git-annex.mdwn
+++ b/doc/git-annex.mdwn
@@ -278,6 +278,12 @@ Many git-annex commands will stage changes for later `git commit` by you.
Force unsafe actions, such as dropping a file's content when no other
source of it can be verified to still exist. Use with care.
+* --fast
+
+ Enables less expensive, but also less thorough versions of some commands.
+ What is avoided depends on the command. A fast fsck avoids calculating
+ checksums; a fast unused only shows temp files and not other unused files.
+
* --quiet
Avoid the default verbose logging of what is done; only show errors
@@ -371,6 +377,14 @@ Here are all the supported configuration settings.
Default ssh and rsync options to use if a remote does not have
specific options.
+* `annex.diskreserve`
+
+ Amount of disk space to reserve. Disk space is checked when transferring
+ content to avoid running out, and additional free space can be reserved
+ via this option, to make space for more important content (such as git
+ commit logs). The units are bytes.
+ The default reserve is 1048576 (1 megabyte).
+
* `annex.version`
Automatically maintained, and used to automate upgrades between versions.