annex.numcopies works
This commit is contained in:
parent
aa2f4bd810
commit
508a3b65ed
5 changed files with 71 additions and 11 deletions
15
Backend.hs
15
Backend.hs
|
@ -15,8 +15,9 @@
|
||||||
|
|
||||||
module Backend (
|
module Backend (
|
||||||
storeFileKey,
|
storeFileKey,
|
||||||
removeKey,
|
|
||||||
retrieveKeyFile,
|
retrieveKeyFile,
|
||||||
|
removeKey,
|
||||||
|
hasKey,
|
||||||
lookupFile
|
lookupFile
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
@ -77,6 +78,18 @@ retrieveKeyFile backend key dest = (B.retrieveKeyFile backend) key dest
|
||||||
removeKey :: Backend -> Key -> Annex Bool
|
removeKey :: Backend -> Key -> Annex Bool
|
||||||
removeKey backend key = (B.removeKey backend) key
|
removeKey backend key = (B.removeKey backend) key
|
||||||
|
|
||||||
|
{- Checks if any backend has a key. -}
|
||||||
|
hasKey :: Key -> Annex Bool
|
||||||
|
hasKey key = do
|
||||||
|
b <- backendList
|
||||||
|
hasKey' b key
|
||||||
|
hasKey' [] key = return False
|
||||||
|
hasKey' (b:bs) key = do
|
||||||
|
has <- (B.hasKey b) key
|
||||||
|
if (has)
|
||||||
|
then return True
|
||||||
|
else hasKey' bs key
|
||||||
|
|
||||||
{- Looks up the key and backend corresponding to an annexed file,
|
{- Looks up the key and backend corresponding to an annexed file,
|
||||||
- by examining what the file symlinks to. -}
|
- by examining what the file symlinks to. -}
|
||||||
lookupFile :: FilePath -> IO (Maybe (Key, Backend))
|
lookupFile :: FilePath -> IO (Maybe (Key, Backend))
|
||||||
|
|
|
@ -15,6 +15,8 @@ import qualified Remotes
|
||||||
import qualified GitRepo as Git
|
import qualified GitRepo as Git
|
||||||
import Utility
|
import Utility
|
||||||
import Core
|
import Core
|
||||||
|
import qualified Annex
|
||||||
|
import UUID
|
||||||
|
|
||||||
backend = Backend {
|
backend = Backend {
|
||||||
name = "file",
|
name = "file",
|
||||||
|
@ -49,6 +51,9 @@ checkKeyFile k = inAnnex backend k
|
||||||
copyKeyFile :: Key -> FilePath -> Annex (Bool)
|
copyKeyFile :: Key -> FilePath -> Annex (Bool)
|
||||||
copyKeyFile key file = do
|
copyKeyFile key file = do
|
||||||
remotes <- Remotes.withKey key
|
remotes <- Remotes.withKey key
|
||||||
|
if (0 == length remotes)
|
||||||
|
then cantfind
|
||||||
|
else return ()
|
||||||
trycopy remotes remotes
|
trycopy remotes remotes
|
||||||
where
|
where
|
||||||
trycopy full [] = error $ "unable to get: " ++ (keyFile key) ++ "\n" ++
|
trycopy full [] = error $ "unable to get: " ++ (keyFile key) ++ "\n" ++
|
||||||
|
@ -68,6 +73,14 @@ copyKeyFile key file = do
|
||||||
liftIO $ hPutStrLn stderr (show err)
|
liftIO $ hPutStrLn stderr (show err)
|
||||||
trycopy full rs
|
trycopy full rs
|
||||||
Right succ -> return True
|
Right succ -> return True
|
||||||
|
cantfind = do
|
||||||
|
g <- Annex.gitRepo
|
||||||
|
uuids <- liftIO $ keyLocations g key
|
||||||
|
error $ "no available git remotes have: " ++
|
||||||
|
(keyFile key) ++ (uuidlist uuids)
|
||||||
|
uuidlist [] = ""
|
||||||
|
uuidlist uuids = "\nIt has been seen before in these repositories:\n" ++
|
||||||
|
prettyPrintUUIDs uuids
|
||||||
|
|
||||||
{- Tries to copy a file from a remote, exception on error. -}
|
{- Tries to copy a file from a remote, exception on error. -}
|
||||||
copyFromRemote :: Git.Repo -> Key -> FilePath -> IO ()
|
copyFromRemote :: Git.Repo -> Key -> FilePath -> IO ()
|
||||||
|
|
41
Commands.hs
41
Commands.hs
|
@ -8,6 +8,7 @@ import System.Posix.Files
|
||||||
import System.Directory
|
import System.Directory
|
||||||
import Data.String.Utils
|
import Data.String.Utils
|
||||||
import List
|
import List
|
||||||
|
import IO
|
||||||
import qualified GitRepo as Git
|
import qualified GitRepo as Git
|
||||||
import qualified Annex
|
import qualified Annex
|
||||||
import Utility
|
import Utility
|
||||||
|
@ -18,6 +19,7 @@ import UUID
|
||||||
import LocationLog
|
import LocationLog
|
||||||
import Types
|
import Types
|
||||||
import Core
|
import Core
|
||||||
|
import qualified Remotes
|
||||||
|
|
||||||
options :: [OptDescr (String -> Annex ())]
|
options :: [OptDescr (String -> Annex ())]
|
||||||
options =
|
options =
|
||||||
|
@ -138,7 +140,7 @@ wantCmd file = do error "not implemented" -- TODO
|
||||||
{- Indicates a file is not wanted. -}
|
{- Indicates a file is not wanted. -}
|
||||||
dropCmd :: FilePath -> Annex ()
|
dropCmd :: FilePath -> Annex ()
|
||||||
dropCmd file = notinBackend file err $ \(key, backend) -> do
|
dropCmd file = notinBackend file err $ \(key, backend) -> do
|
||||||
-- TODO only remove if enough copies are present elsewhere
|
requireEnoughCopies key
|
||||||
success <- Backend.removeKey backend key
|
success <- Backend.removeKey backend key
|
||||||
if (success)
|
if (success)
|
||||||
then do
|
then do
|
||||||
|
@ -181,3 +183,40 @@ inBackend file yes no = do
|
||||||
Just v -> yes v
|
Just v -> yes v
|
||||||
Nothing -> no
|
Nothing -> no
|
||||||
notinBackend file yes no = inBackend file no yes
|
notinBackend file yes no = inBackend file no yes
|
||||||
|
|
||||||
|
{- Checks remotes to verify that enough copies of a key exist to allow
|
||||||
|
- for a key to be safely removed (with no data loss), and fails with an
|
||||||
|
- error if not. -}
|
||||||
|
requireEnoughCopies :: Key -> Annex ()
|
||||||
|
requireEnoughCopies key = do
|
||||||
|
g <- Annex.gitRepo
|
||||||
|
let numcopies = read $ Git.configGet g config "1"
|
||||||
|
remotes <- Remotes.withKey key
|
||||||
|
if (numcopies > length remotes)
|
||||||
|
then error $ "I only know about " ++ (show $ length remotes) ++
|
||||||
|
" out of " ++ (show numcopies) ++
|
||||||
|
" necessary copies of: " ++ (keyFile key) ++
|
||||||
|
unsafe
|
||||||
|
else findcopies numcopies remotes []
|
||||||
|
where
|
||||||
|
findcopies 0 _ _ = return () -- success, enough copies found
|
||||||
|
findcopies _ [] bad = die bad
|
||||||
|
findcopies n (r:rs) bad = do
|
||||||
|
result <- liftIO $ try $ haskey r
|
||||||
|
case (result) of
|
||||||
|
Right True -> findcopies (n-1) rs bad
|
||||||
|
Left _ -> findcopies n rs (r:bad)
|
||||||
|
haskey r = do
|
||||||
|
-- To check if a remote has a key, construct a new
|
||||||
|
-- Annex monad and query its backend.
|
||||||
|
a <- Annex.new r
|
||||||
|
(result, _) <- Annex.run a (Backend.hasKey key)
|
||||||
|
return result
|
||||||
|
die bad =
|
||||||
|
error $ "I failed to find enough other copies of: " ++
|
||||||
|
(keyFile key) ++ "\n" ++
|
||||||
|
"I was unable to access these remotes: " ++
|
||||||
|
(Remotes.list bad) ++ unsafe
|
||||||
|
unsafe = "\n -- According to the " ++ config ++
|
||||||
|
" setting, it is not safe to remove it!"
|
||||||
|
config = "annex.numcopies"
|
||||||
|
|
10
Remotes.hs
10
Remotes.hs
|
@ -40,15 +40,7 @@ withKey key = do
|
||||||
mayberemotes <- mapM tryGitConfigRead allremotes
|
mayberemotes <- mapM tryGitConfigRead allremotes
|
||||||
let allremotes' = catMaybes mayberemotes
|
let allremotes' = catMaybes mayberemotes
|
||||||
remotes' <- reposByUUID allremotes' uuids
|
remotes' <- reposByUUID allremotes' uuids
|
||||||
if (0 == length remotes')
|
return remotes'
|
||||||
then err uuids
|
|
||||||
else return remotes'
|
|
||||||
err uuids =
|
|
||||||
error $ "no available git remotes have: " ++
|
|
||||||
(keyFile key) ++ (uuidlist uuids)
|
|
||||||
uuidlist [] = ""
|
|
||||||
uuidlist uuids = "\nIt has been seen before in these repositories:\n" ++
|
|
||||||
prettyPrintUUIDs uuids
|
|
||||||
|
|
||||||
{- Cost Ordered list of remotes. -}
|
{- Cost Ordered list of remotes. -}
|
||||||
remotesByCost :: Annex [Git.Repo]
|
remotesByCost :: Annex [Git.Repo]
|
||||||
|
|
3
TODO
3
TODO
|
@ -1,6 +1,9 @@
|
||||||
* bug when annexing files while in a subdir of a git repo
|
* bug when annexing files while in a subdir of a git repo
|
||||||
* bug when specifying absolute path to files when annexing
|
* bug when specifying absolute path to files when annexing
|
||||||
|
|
||||||
|
* need to include backend name as part of the key, because currently
|
||||||
|
if two backends have overlapping key spaces, it can confuse things
|
||||||
|
|
||||||
* --push/--pull/--want
|
* --push/--pull/--want
|
||||||
|
|
||||||
* how to handle git mv file?
|
* how to handle git mv file?
|
||||||
|
|
Loading…
Reference in a new issue