2011-01-07 00:09:49 +00:00
|
|
|
{- git-annex test suite
|
|
|
|
-
|
2011-01-08 20:09:17 +00:00
|
|
|
- Copyright 2010,2011 Joey Hess <joey@kitenet.net>
|
2011-01-07 00:09:49 +00:00
|
|
|
-
|
|
|
|
- Licensed under the GNU GPL version 3 or higher.
|
|
|
|
-}
|
|
|
|
|
2010-11-02 21:08:16 +00:00
|
|
|
import Test.HUnit
|
|
|
|
import Test.HUnit.Tools
|
2011-01-07 00:09:49 +00:00
|
|
|
import System.Directory
|
|
|
|
import System.Posix.Directory (changeWorkingDirectory)
|
|
|
|
import System.Posix.Files
|
|
|
|
import IO (bracket_, bracket)
|
|
|
|
import Control.Monad (unless, when)
|
|
|
|
import Data.List
|
|
|
|
import System.IO.Error
|
2011-01-07 06:14:48 +00:00
|
|
|
import System.Posix.Env
|
2011-01-07 01:39:26 +00:00
|
|
|
import qualified Control.Exception.Extensible as E
|
2011-01-08 19:14:41 +00:00
|
|
|
import Control.Exception (throw)
|
2011-01-11 22:50:18 +00:00
|
|
|
import Control.Monad.State (liftIO)
|
2011-01-11 23:59:11 +00:00
|
|
|
import Maybe
|
2011-01-12 05:58:23 +00:00
|
|
|
import qualified Data.Map as M
|
2010-11-02 21:08:16 +00:00
|
|
|
|
2011-01-11 19:43:29 +00:00
|
|
|
import qualified Annex
|
|
|
|
import qualified BackendList
|
|
|
|
import qualified Backend
|
2011-01-07 00:09:49 +00:00
|
|
|
import qualified GitRepo as Git
|
2011-01-07 00:26:57 +00:00
|
|
|
import qualified Locations
|
|
|
|
import qualified Utility
|
|
|
|
import qualified TypeInternals
|
|
|
|
import qualified GitAnnex
|
2011-01-11 19:43:29 +00:00
|
|
|
import qualified LocationLog
|
2011-01-11 22:50:18 +00:00
|
|
|
import qualified UUID
|
|
|
|
import qualified Remotes
|
2011-01-16 20:05:05 +00:00
|
|
|
import qualified Content
|
2011-01-11 23:59:11 +00:00
|
|
|
import qualified Backend.SHA1
|
2011-01-12 03:02:21 +00:00
|
|
|
import qualified Backend.WORM
|
2011-01-12 05:58:23 +00:00
|
|
|
import qualified Command.DropUnused
|
2010-11-02 20:49:35 +00:00
|
|
|
|
2011-01-07 06:14:48 +00:00
|
|
|
main :: IO ()
|
2011-01-07 01:39:26 +00:00
|
|
|
main = do
|
2011-01-07 18:06:32 +00:00
|
|
|
prepare
|
2011-01-07 01:39:26 +00:00
|
|
|
r <- runVerboseTests $ TestList [quickchecks, toplevels]
|
|
|
|
cleanup tmpdir
|
2011-01-07 06:14:48 +00:00
|
|
|
propigate r
|
|
|
|
|
|
|
|
propigate :: (Counts, Int) -> IO ()
|
|
|
|
propigate (Counts { errors = e }, _)
|
|
|
|
| e > 0 = error "failed"
|
|
|
|
| otherwise = return ()
|
2011-01-07 00:09:49 +00:00
|
|
|
|
|
|
|
quickchecks :: Test
|
|
|
|
quickchecks = TestLabel "quickchecks" $ TestList
|
|
|
|
[ qctest "prop_idempotent_deencode" Git.prop_idempotent_deencode
|
2011-01-07 00:26:57 +00:00
|
|
|
, qctest "prop_idempotent_fileKey" Locations.prop_idempotent_fileKey
|
|
|
|
, qctest "prop_idempotent_key_read_show" TypeInternals.prop_idempotent_key_read_show
|
|
|
|
, qctest "prop_idempotent_shellEscape" Utility.prop_idempotent_shellEscape
|
|
|
|
, qctest "prop_idempotent_shellEscape_multiword" Utility.prop_idempotent_shellEscape_multiword
|
|
|
|
, qctest "prop_parentDir_basics" Utility.prop_parentDir_basics
|
|
|
|
, qctest "prop_relPathDirToDir_basics" Utility.prop_relPathDirToDir_basics
|
2010-11-02 21:08:16 +00:00
|
|
|
]
|
|
|
|
|
2011-01-07 00:09:49 +00:00
|
|
|
toplevels :: Test
|
|
|
|
toplevels = TestLabel "toplevel" $ TestList
|
2011-01-07 01:39:26 +00:00
|
|
|
-- test order matters, later tests may rely on state from earlier
|
2011-01-07 00:09:49 +00:00
|
|
|
[ test_init
|
|
|
|
, test_add
|
2011-01-11 23:59:11 +00:00
|
|
|
, test_setkey
|
2011-01-07 01:39:26 +00:00
|
|
|
, test_unannex
|
|
|
|
, test_drop
|
2011-01-07 02:22:09 +00:00
|
|
|
, test_get
|
2011-01-07 05:02:06 +00:00
|
|
|
, test_move
|
2011-01-07 06:14:48 +00:00
|
|
|
, test_copy
|
2011-01-07 18:06:32 +00:00
|
|
|
, test_lock
|
|
|
|
, test_edit
|
|
|
|
, test_fix
|
2011-01-11 22:50:18 +00:00
|
|
|
, test_trust
|
2011-01-11 23:34:28 +00:00
|
|
|
, test_fsck
|
2011-01-12 01:11:32 +00:00
|
|
|
, test_migrate
|
2011-01-12 05:58:23 +00:00
|
|
|
, test_unused
|
2011-01-07 00:09:49 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
test_init :: Test
|
2011-01-07 18:06:32 +00:00
|
|
|
test_init = "git-annex init" ~: TestCase $ innewrepo $ do
|
2011-01-07 00:09:49 +00:00
|
|
|
git_annex "init" ["-q", reponame] @? "init failed"
|
|
|
|
e <- doesFileExist annexlog
|
2011-01-07 05:02:06 +00:00
|
|
|
e @? (annexlog ++ " not created")
|
2011-01-07 00:09:49 +00:00
|
|
|
c <- readFile annexlog
|
2011-01-07 05:02:06 +00:00
|
|
|
isInfixOf reponame c @? annexlog ++ " does not contain repo name"
|
2011-01-07 00:09:49 +00:00
|
|
|
where
|
|
|
|
annexlog = ".git-annex/uuid.log"
|
|
|
|
reponame = "test repo"
|
|
|
|
|
|
|
|
test_add :: Test
|
2011-01-07 18:06:32 +00:00
|
|
|
test_add = "git-annex add" ~: TestCase $ inmainrepo $ do
|
2011-01-07 05:02:06 +00:00
|
|
|
writeFile annexedfile $ content annexedfile
|
|
|
|
git_annex "add" ["-q", annexedfile] @? "add failed"
|
2011-01-07 18:06:32 +00:00
|
|
|
annexed_present annexedfile
|
2011-01-07 05:02:06 +00:00
|
|
|
writeFile ingitfile $ content ingitfile
|
|
|
|
Utility.boolSystem "git" ["add", ingitfile] @? "git add failed"
|
|
|
|
Utility.boolSystem "git" ["commit", "-q", "-a", "-m", "commit"] @? "git commit failed"
|
|
|
|
git_annex "add" ["-q", ingitfile] @? "add ingitfile should be no-op"
|
2011-01-07 18:06:32 +00:00
|
|
|
unannexed ingitfile
|
2011-01-07 00:09:49 +00:00
|
|
|
|
2011-01-11 23:59:11 +00:00
|
|
|
test_setkey :: Test
|
|
|
|
test_setkey = "git-annex setkey/fromkey" ~: TestCase $ inmainrepo $ do
|
|
|
|
writeFile tmp $ content sha1annexedfile
|
|
|
|
r <- annexeval $ TypeInternals.getKey Backend.SHA1.backend tmp
|
|
|
|
let sha1 = TypeInternals.keyName $ fromJust r
|
|
|
|
git_annex "setkey" ["-q", "--backend", "SHA1", "--key", sha1, tmp] @? "setkey failed"
|
|
|
|
git_annex "fromkey" ["-q", "--backend", "SHA1", "--key", sha1, sha1annexedfile] @? "fromkey failed"
|
2011-01-12 00:06:15 +00:00
|
|
|
Utility.boolSystem "git" ["commit", "-q", "-a", "-m", "commit"] @? "git commit failed"
|
2011-01-11 23:59:11 +00:00
|
|
|
annexed_present sha1annexedfile
|
|
|
|
where
|
|
|
|
tmp = "tmpfile"
|
|
|
|
|
2011-01-07 01:39:26 +00:00
|
|
|
test_unannex :: Test
|
2011-01-08 19:00:04 +00:00
|
|
|
test_unannex = "git-annex unannex" ~: TestList [nocopy, withcopy]
|
|
|
|
where
|
|
|
|
nocopy = "no content" ~: intmpclonerepo $ do
|
2011-01-08 19:14:41 +00:00
|
|
|
annexed_notpresent annexedfile
|
|
|
|
git_annex "unannex" ["-q", annexedfile] @? "unannex failed with no copy"
|
|
|
|
annexed_notpresent annexedfile
|
2011-01-08 19:00:04 +00:00
|
|
|
withcopy = "with content" ~: intmpcopyrepo $ do
|
2011-01-08 19:14:41 +00:00
|
|
|
annexed_present annexedfile
|
2011-01-08 19:00:04 +00:00
|
|
|
git_annex "unannex" ["-q", annexedfile] @? "unannex failed"
|
|
|
|
unannexed annexedfile
|
|
|
|
git_annex "unannex" ["-q", annexedfile] @? "unannex failed on non-annexed file"
|
|
|
|
unannexed annexedfile
|
|
|
|
git_annex "unannex" ["-q", ingitfile] @? "unannex ingitfile should be no-op"
|
|
|
|
unannexed ingitfile
|
2011-01-07 01:39:26 +00:00
|
|
|
|
|
|
|
test_drop :: Test
|
2011-01-08 19:00:04 +00:00
|
|
|
test_drop = "git-annex drop" ~: TestList [noremote, withremote]
|
2011-01-07 18:06:32 +00:00
|
|
|
where
|
2011-01-08 19:00:04 +00:00
|
|
|
noremote = "no remotes" ~: TestCase $ intmpcopyrepo $ do
|
2011-01-07 18:06:32 +00:00
|
|
|
r <- git_annex "drop" ["-q", annexedfile]
|
|
|
|
(not r) @? "drop wrongly succeeded with no known copy of file"
|
|
|
|
annexed_present annexedfile
|
|
|
|
git_annex "drop" ["-q", "--force", annexedfile] @? "drop --force failed"
|
|
|
|
annexed_notpresent annexedfile
|
|
|
|
git_annex "drop" ["-q", annexedfile] @? "drop of dropped file failed"
|
|
|
|
git_annex "drop" ["-q", ingitfile] @? "drop ingitfile should be no-op"
|
|
|
|
unannexed ingitfile
|
2011-01-08 19:00:04 +00:00
|
|
|
withremote = "with remote" ~: TestCase $ intmpclonerepo $ do
|
2011-01-07 18:06:32 +00:00
|
|
|
git_annex "drop" ["-q", annexedfile] @? "drop failed though origin has copy"
|
|
|
|
annexed_notpresent annexedfile
|
|
|
|
inmainrepo $ annexed_present annexedfile
|
2011-01-07 02:22:09 +00:00
|
|
|
|
|
|
|
test_get :: Test
|
2011-01-07 18:06:32 +00:00
|
|
|
test_get = "git-annex get" ~: TestCase $ intmpclonerepo $ do
|
|
|
|
inmainrepo $ annexed_present annexedfile
|
|
|
|
annexed_notpresent annexedfile
|
2011-01-07 05:02:06 +00:00
|
|
|
git_annex "get" ["-q", annexedfile] @? "get of file failed"
|
2011-01-07 18:06:32 +00:00
|
|
|
inmainrepo $ annexed_present annexedfile
|
|
|
|
annexed_present annexedfile
|
2011-01-07 05:02:06 +00:00
|
|
|
git_annex "get" ["-q", annexedfile] @? "get of file already here failed"
|
2011-01-07 18:06:32 +00:00
|
|
|
inmainrepo $ annexed_present annexedfile
|
|
|
|
annexed_present annexedfile
|
|
|
|
inmainrepo $ unannexed ingitfile
|
|
|
|
unannexed ingitfile
|
2011-01-07 05:02:06 +00:00
|
|
|
git_annex "get" ["-q", ingitfile] @? "get ingitfile should be no-op"
|
2011-01-07 18:06:32 +00:00
|
|
|
inmainrepo $ unannexed ingitfile
|
|
|
|
unannexed ingitfile
|
2011-01-07 05:02:06 +00:00
|
|
|
|
|
|
|
test_move :: Test
|
2011-01-07 18:06:32 +00:00
|
|
|
test_move = "git-annex move" ~: TestCase $ intmpclonerepo $ do
|
|
|
|
annexed_notpresent annexedfile
|
|
|
|
inmainrepo $ annexed_present annexedfile
|
2011-01-07 05:02:06 +00:00
|
|
|
git_annex "move" ["-q", "--from", "origin", annexedfile] @? "move --from of file failed"
|
2011-01-07 18:06:32 +00:00
|
|
|
annexed_present annexedfile
|
|
|
|
inmainrepo $ annexed_notpresent annexedfile
|
2011-01-07 05:02:06 +00:00
|
|
|
git_annex "move" ["-q", "--from", "origin", annexedfile] @? "move --from of file already here failed"
|
2011-01-07 18:06:32 +00:00
|
|
|
annexed_present annexedfile
|
|
|
|
inmainrepo $ annexed_notpresent annexedfile
|
2011-01-07 05:02:06 +00:00
|
|
|
git_annex "move" ["-q", "--to", "origin", annexedfile] @? "move --to of file failed"
|
2011-01-07 18:06:32 +00:00
|
|
|
inmainrepo $ annexed_present annexedfile
|
|
|
|
annexed_notpresent annexedfile
|
2011-01-07 06:14:48 +00:00
|
|
|
git_annex "move" ["-q", "--to", "origin", annexedfile] @? "move --to of file already there failed"
|
2011-01-07 18:06:32 +00:00
|
|
|
inmainrepo $ annexed_present annexedfile
|
|
|
|
annexed_notpresent annexedfile
|
|
|
|
unannexed ingitfile
|
|
|
|
inmainrepo $ unannexed ingitfile
|
2011-01-07 06:18:39 +00:00
|
|
|
git_annex "move" ["-q", "--to", "origin", ingitfile] @? "move of ingitfile should be no-op"
|
2011-01-07 18:06:32 +00:00
|
|
|
unannexed ingitfile
|
|
|
|
inmainrepo $ unannexed ingitfile
|
2011-01-07 06:18:39 +00:00
|
|
|
git_annex "move" ["-q", "--from", "origin", ingitfile] @? "move of ingitfile should be no-op"
|
2011-01-07 18:06:32 +00:00
|
|
|
unannexed ingitfile
|
|
|
|
inmainrepo $ unannexed ingitfile
|
2011-01-07 06:14:48 +00:00
|
|
|
|
|
|
|
test_copy :: Test
|
2011-01-07 18:06:32 +00:00
|
|
|
test_copy = "git-annex copy" ~: TestCase $ intmpclonerepo $ do
|
|
|
|
annexed_notpresent annexedfile
|
|
|
|
inmainrepo $ annexed_present annexedfile
|
2011-01-07 06:14:48 +00:00
|
|
|
git_annex "copy" ["-q", "--from", "origin", annexedfile] @? "copy --from of file failed"
|
2011-01-07 18:06:32 +00:00
|
|
|
annexed_present annexedfile
|
|
|
|
inmainrepo $ annexed_present annexedfile
|
2011-01-07 06:14:48 +00:00
|
|
|
git_annex "copy" ["-q", "--from", "origin", annexedfile] @? "copy --from of file already here failed"
|
2011-01-07 18:06:32 +00:00
|
|
|
annexed_present annexedfile
|
|
|
|
inmainrepo $ annexed_present annexedfile
|
2011-01-07 06:14:48 +00:00
|
|
|
git_annex "copy" ["-q", "--to", "origin", annexedfile] @? "copy --to of file already there failed"
|
2011-01-07 18:06:32 +00:00
|
|
|
annexed_present annexedfile
|
|
|
|
inmainrepo $ annexed_present annexedfile
|
2011-01-07 06:14:48 +00:00
|
|
|
git_annex "move" ["-q", "--to", "origin", annexedfile] @? "move --to of file already there failed"
|
2011-01-07 18:06:32 +00:00
|
|
|
annexed_notpresent annexedfile
|
|
|
|
inmainrepo $ annexed_present annexedfile
|
|
|
|
unannexed ingitfile
|
|
|
|
inmainrepo $ unannexed ingitfile
|
2011-01-07 06:18:39 +00:00
|
|
|
git_annex "copy" ["-q", "--to", "origin", ingitfile] @? "copy of ingitfile should be no-op"
|
2011-01-07 18:06:32 +00:00
|
|
|
unannexed ingitfile
|
|
|
|
inmainrepo $ unannexed ingitfile
|
2011-01-07 06:18:39 +00:00
|
|
|
git_annex "copy" ["-q", "--from", "origin", ingitfile] @? "copy of ingitfile should be no-op"
|
|
|
|
checkregularfile ingitfile
|
|
|
|
checkcontent ingitfile
|
2011-01-07 05:02:06 +00:00
|
|
|
|
2011-01-07 18:06:32 +00:00
|
|
|
test_lock :: Test
|
|
|
|
test_lock = "git-annex unlock/lock" ~: intmpclonerepo $ do
|
2011-01-14 03:46:02 +00:00
|
|
|
-- regression test: unlock of not present file should skip it
|
|
|
|
annexed_notpresent annexedfile
|
|
|
|
r <- git_annex "unlock" ["-q", annexedfile]
|
2011-01-14 04:02:33 +00:00
|
|
|
not r @? "unlock failed to fail with not present file"
|
2011-01-14 03:46:02 +00:00
|
|
|
annexed_notpresent annexedfile
|
|
|
|
|
2011-01-07 18:06:32 +00:00
|
|
|
git_annex "get" ["-q", annexedfile] @? "get of file failed"
|
|
|
|
annexed_present annexedfile
|
|
|
|
git_annex "unlock" ["-q", annexedfile] @? "unlock failed"
|
|
|
|
unannexed annexedfile
|
|
|
|
-- write different content, to verify that lock
|
|
|
|
-- throws it away
|
|
|
|
changecontent annexedfile
|
|
|
|
writeFile annexedfile $ (content annexedfile) ++ "foo"
|
|
|
|
git_annex "lock" ["-q", annexedfile] @? "lock failed"
|
|
|
|
annexed_present annexedfile
|
|
|
|
git_annex "unlock" ["-q", annexedfile] @? "unlock failed"
|
|
|
|
unannexed annexedfile
|
|
|
|
changecontent annexedfile
|
|
|
|
git_annex "add" ["-q", annexedfile] @? "add of modified file failed"
|
|
|
|
runchecks [checklink, checkunwritable] annexedfile
|
|
|
|
c <- readFile annexedfile
|
|
|
|
assertEqual ("content of modified file") c (changedcontent annexedfile)
|
2011-01-14 03:46:02 +00:00
|
|
|
r' <- git_annex "drop" ["-q", annexedfile]
|
|
|
|
not r' @? "drop wrongly succeeded with no known copy of modified file"
|
2011-01-07 18:06:32 +00:00
|
|
|
|
|
|
|
test_edit :: Test
|
2011-01-12 00:48:58 +00:00
|
|
|
test_edit = "git-annex edit/commit" ~: TestList [t False, t True]
|
|
|
|
where t precommit = TestCase $ intmpclonerepo $ do
|
|
|
|
git_annex "get" ["-q", annexedfile] @? "get of file failed"
|
|
|
|
annexed_present annexedfile
|
|
|
|
git_annex "edit" ["-q", annexedfile] @? "edit failed"
|
|
|
|
unannexed annexedfile
|
|
|
|
changecontent annexedfile
|
|
|
|
if precommit
|
|
|
|
then do
|
|
|
|
-- pre-commit depends on the file being
|
|
|
|
-- staged, normally git commit does this
|
|
|
|
Utility.boolSystem "git" ["add", annexedfile]
|
|
|
|
@? "git add of edited file failed"
|
|
|
|
git_annex "pre-commit" ["-q"]
|
|
|
|
@? "pre-commit failed"
|
|
|
|
else do
|
|
|
|
Utility.boolSystem "git" ["commit", "-q", "-a", "-m", "content changed"]
|
|
|
|
@? "git commit of edited file failed"
|
|
|
|
runchecks [checklink, checkunwritable] annexedfile
|
|
|
|
c <- readFile annexedfile
|
|
|
|
assertEqual ("content of modified file") c (changedcontent annexedfile)
|
|
|
|
r <- git_annex "drop" ["-q", annexedfile]
|
|
|
|
(not r) @? "drop wrongly succeeded with no known copy of modified file"
|
2011-01-07 18:06:32 +00:00
|
|
|
|
|
|
|
test_fix :: Test
|
|
|
|
test_fix = "git-annex fix" ~: intmpclonerepo $ do
|
2011-01-07 18:08:43 +00:00
|
|
|
annexed_notpresent annexedfile
|
|
|
|
git_annex "fix" ["-q", annexedfile] @? "fix of not present failed"
|
|
|
|
annexed_notpresent annexedfile
|
2011-01-07 18:06:32 +00:00
|
|
|
git_annex "get" ["-q", annexedfile] @? "get of file failed"
|
|
|
|
annexed_present annexedfile
|
2011-01-07 18:08:43 +00:00
|
|
|
git_annex "fix" ["-q", annexedfile] @? "fix of present file failed"
|
|
|
|
annexed_present annexedfile
|
2011-01-07 18:06:32 +00:00
|
|
|
createDirectory subdir
|
|
|
|
Utility.boolSystem "git" ["mv", annexedfile, subdir]
|
|
|
|
@? "git mv failed"
|
2011-01-07 18:08:43 +00:00
|
|
|
git_annex "fix" ["-q", newfile] @? "fix of moved file failed"
|
2011-01-07 18:06:32 +00:00
|
|
|
runchecks [checklink, checkunwritable] newfile
|
|
|
|
c <- readFile newfile
|
|
|
|
assertEqual ("content of moved file") c (content annexedfile)
|
|
|
|
where
|
|
|
|
subdir = "s"
|
|
|
|
newfile = subdir ++ "/" ++ annexedfile
|
2011-01-07 01:39:26 +00:00
|
|
|
|
2011-01-11 22:50:18 +00:00
|
|
|
test_trust :: Test
|
|
|
|
test_trust = "git-annex trust/untrust" ~: intmpclonerepo $ do
|
|
|
|
trust False
|
|
|
|
git_annex "trust" ["-q", "origin"] @? "trust failed"
|
|
|
|
trust True
|
|
|
|
git_annex "trust" ["-q", "origin"] @? "trust of trusted failed"
|
|
|
|
trust True
|
|
|
|
git_annex "untrust" ["-q", "origin"] @? "untrust failed"
|
|
|
|
trust False
|
|
|
|
git_annex "untrust" ["-q", "origin"] @? "untrust of untrusted failed"
|
|
|
|
trust False
|
|
|
|
where
|
|
|
|
trust expected = do
|
|
|
|
istrusted <- annexeval $ do
|
|
|
|
uuids <- UUID.getTrusted
|
|
|
|
r <- Remotes.byName "origin"
|
|
|
|
u <- UUID.getUUID r
|
|
|
|
return $ elem u uuids
|
|
|
|
assertEqual "trust value" expected istrusted
|
|
|
|
|
2011-01-11 23:34:28 +00:00
|
|
|
test_fsck :: Test
|
|
|
|
test_fsck = "git-annex fsck" ~: intmpclonerepo $ do
|
|
|
|
git_annex "fsck" ["-q"] @? "fsck failed"
|
|
|
|
Utility.boolSystem "git" ["config", "annex.numcopies", "2"] @? "git config failed"
|
|
|
|
r <- git_annex "fsck" ["-q"]
|
|
|
|
not r @? "fsck failed to fail with numcopies unsatisfied"
|
|
|
|
Utility.boolSystem "git" ["config", "annex.numcopies", "1"] @? "git config failed"
|
2011-01-12 00:06:15 +00:00
|
|
|
corrupt annexedfile
|
|
|
|
corrupt sha1annexedfile
|
|
|
|
where
|
|
|
|
corrupt f = do
|
|
|
|
git_annex "get" ["-q", f] @? "get of file failed"
|
2011-01-16 20:05:05 +00:00
|
|
|
Content.allowWrite f
|
2011-01-12 00:06:15 +00:00
|
|
|
writeFile f (changedcontent f)
|
|
|
|
r <- git_annex "fsck" ["-q"]
|
|
|
|
not r @? "fsck failed to fail with corrupted file content"
|
|
|
|
git_annex "fsck" ["-q"] @? "fsck unexpectedly failed again; previous one did not fix problem"
|
2011-01-11 23:34:28 +00:00
|
|
|
|
2011-01-12 01:11:32 +00:00
|
|
|
test_migrate :: Test
|
|
|
|
test_migrate = "git-annex migrate" ~: TestList [t False, t True]
|
|
|
|
where t usegitattributes = TestCase $ intmpclonerepo $ do
|
|
|
|
annexed_notpresent annexedfile
|
|
|
|
annexed_notpresent sha1annexedfile
|
|
|
|
git_annex "migrate" ["-q", annexedfile] @? "migrate of not present failed"
|
|
|
|
git_annex "migrate" ["-q", sha1annexedfile] @? "migrate of not present failed"
|
|
|
|
git_annex "get" ["-q", annexedfile] @? "get of file failed"
|
|
|
|
git_annex "get" ["-q", sha1annexedfile] @? "get of file failed"
|
|
|
|
annexed_present annexedfile
|
|
|
|
annexed_present sha1annexedfile
|
|
|
|
if usegitattributes
|
|
|
|
then do
|
2011-01-12 03:02:21 +00:00
|
|
|
writeFile ".gitattributes" $ "* annex.backend=SHA1"
|
|
|
|
git_annex "migrate" ["-q", sha1annexedfile]
|
|
|
|
@? "migrate sha1annexedfile failed"
|
|
|
|
git_annex "migrate" ["-q", annexedfile]
|
|
|
|
@? "migrate annexedfile failed"
|
2011-01-12 01:11:32 +00:00
|
|
|
else do
|
2011-01-12 03:02:21 +00:00
|
|
|
git_annex "migrate" ["-q", sha1annexedfile, "--backend", "SHA1"]
|
|
|
|
@? "migrate sha1annexedfile failed"
|
|
|
|
git_annex "migrate" ["-q", annexedfile, "--backend", "SHA1"]
|
|
|
|
@? "migrate annexedfile failed"
|
2011-01-12 01:11:32 +00:00
|
|
|
annexed_present annexedfile
|
|
|
|
annexed_present sha1annexedfile
|
2011-01-12 03:02:21 +00:00
|
|
|
checkbackend annexedfile Backend.SHA1.backend
|
|
|
|
checkbackend sha1annexedfile Backend.SHA1.backend
|
|
|
|
|
|
|
|
-- check that reversing a migration works
|
|
|
|
writeFile ".gitattributes" $ "* annex.backend=WORM"
|
|
|
|
git_annex "migrate" ["-q", sha1annexedfile]
|
|
|
|
@? "migrate sha1annexedfile failed"
|
|
|
|
git_annex "migrate" ["-q", annexedfile]
|
|
|
|
@? "migrate annexedfile failed"
|
|
|
|
annexed_present annexedfile
|
|
|
|
annexed_present sha1annexedfile
|
|
|
|
checkbackend annexedfile Backend.WORM.backend
|
|
|
|
checkbackend sha1annexedfile Backend.WORM.backend
|
|
|
|
|
2011-01-12 01:11:32 +00:00
|
|
|
where
|
2011-01-12 03:02:21 +00:00
|
|
|
checkbackend file expected = do
|
2011-01-12 01:11:32 +00:00
|
|
|
r <- annexeval $ Backend.lookupFile file
|
|
|
|
let b = snd $ fromJust r
|
|
|
|
assertEqual ("backend for " ++ file) expected b
|
|
|
|
|
2011-01-12 05:58:23 +00:00
|
|
|
test_unused :: Test
|
|
|
|
test_unused = "git-annex unused/dropunused" ~: intmpclonerepo $ do
|
|
|
|
-- keys have to be looked up before files are removed
|
|
|
|
annexedfilekey <- annexeval $ findkey annexedfile
|
|
|
|
sha1annexedfilekey <- annexeval $ findkey sha1annexedfile
|
|
|
|
git_annex "get" ["-q", annexedfile] @? "get of file failed"
|
|
|
|
git_annex "get" ["-q", sha1annexedfile] @? "get of file failed"
|
|
|
|
checkunused []
|
|
|
|
Utility.boolSystem "git" ["rm", "-q", annexedfile] @? "git rm failed"
|
|
|
|
checkunused [annexedfilekey]
|
|
|
|
Utility.boolSystem "git" ["rm", "-q", sha1annexedfile] @? "git rm failed"
|
|
|
|
checkunused [annexedfilekey, sha1annexedfilekey]
|
|
|
|
|
|
|
|
-- good opportunity to test dropkey also
|
|
|
|
git_annex "dropkey" ["-q", "--force", TypeInternals.keyName annexedfilekey]
|
|
|
|
@? "dropkey failed"
|
|
|
|
checkunused [sha1annexedfilekey]
|
|
|
|
|
|
|
|
git_annex "dropunused" ["-q", "1", "2"] @? "dropunused failed"
|
|
|
|
checkunused []
|
|
|
|
git_annex "dropunused" ["-q", "10", "501"] @? "dropunused failed on bogus numbers"
|
|
|
|
|
|
|
|
where
|
|
|
|
checkunused expectedkeys = do
|
|
|
|
git_annex "unused" ["-q"] @? "unused failed"
|
|
|
|
unusedmap <- annexeval $ Command.DropUnused.readUnusedLog
|
|
|
|
let unusedkeys = M.elems unusedmap
|
|
|
|
assertEqual "unused keys differ"
|
|
|
|
(sort expectedkeys) (sort unusedkeys)
|
|
|
|
findkey f = do
|
|
|
|
r <- Backend.lookupFile f
|
|
|
|
return $ fst $ fromJust r
|
|
|
|
|
2011-01-11 22:50:18 +00:00
|
|
|
-- This is equivilant to running git-annex, but it's all run in-process
|
|
|
|
-- so test coverage collection works.
|
2011-01-07 00:09:49 +00:00
|
|
|
git_annex :: String -> [String] -> IO Bool
|
2011-01-07 00:26:57 +00:00
|
|
|
git_annex command params = do
|
2011-01-07 01:39:26 +00:00
|
|
|
-- catch all errors, including normally fatal errors
|
|
|
|
r <- E.try (run)::IO (Either E.SomeException ())
|
2011-01-07 00:26:57 +00:00
|
|
|
case r of
|
|
|
|
Right _ -> return True
|
|
|
|
Left _ -> return False
|
2011-01-07 01:39:26 +00:00
|
|
|
where
|
2011-01-07 06:14:48 +00:00
|
|
|
run = GitAnnex.run (command:params)
|
2011-01-07 00:09:49 +00:00
|
|
|
|
2011-01-11 22:50:18 +00:00
|
|
|
-- Runs an action in the current annex. Note that shutdown actions
|
|
|
|
-- are not run; this should only be used for actions that query state.
|
|
|
|
annexeval :: TypeInternals.Annex a -> IO a
|
|
|
|
annexeval a = do
|
|
|
|
g <- Git.repoFromCwd
|
|
|
|
g' <- Git.configRead g
|
|
|
|
s <- Annex.new g' BackendList.allBackends
|
|
|
|
Annex.eval s a
|
|
|
|
|
2011-01-07 18:06:32 +00:00
|
|
|
innewrepo :: Assertion -> Assertion
|
|
|
|
innewrepo a = withgitrepo $ \r -> indir r a
|
2011-01-07 01:39:26 +00:00
|
|
|
|
2011-01-07 18:06:32 +00:00
|
|
|
inmainrepo :: Assertion -> Assertion
|
|
|
|
inmainrepo a = indir mainrepodir a
|
2011-01-07 01:39:26 +00:00
|
|
|
|
2011-01-07 18:06:32 +00:00
|
|
|
intmpcopyrepo :: Assertion -> Assertion
|
|
|
|
intmpcopyrepo a = withtmpcopyrepo $ \r -> indir r a
|
2011-01-07 01:39:26 +00:00
|
|
|
|
2011-01-07 18:06:32 +00:00
|
|
|
intmpclonerepo :: Assertion -> Assertion
|
|
|
|
intmpclonerepo a = withtmpclonerepo $ \r -> indir r a
|
2011-01-07 02:22:09 +00:00
|
|
|
|
2011-01-07 01:39:26 +00:00
|
|
|
withtmpcopyrepo :: (FilePath -> Assertion) -> Assertion
|
2011-01-07 18:06:32 +00:00
|
|
|
withtmpcopyrepo = bracket (copyrepo mainrepodir tmprepodir) cleanup
|
2011-01-07 01:39:26 +00:00
|
|
|
|
2011-01-07 02:22:09 +00:00
|
|
|
withtmpclonerepo :: (FilePath -> Assertion) -> Assertion
|
2011-01-07 18:06:32 +00:00
|
|
|
withtmpclonerepo = bracket (clonerepo mainrepodir tmprepodir) cleanup
|
2011-01-07 02:22:09 +00:00
|
|
|
|
2011-01-07 01:39:26 +00:00
|
|
|
withgitrepo :: (FilePath -> Assertion) -> Assertion
|
2011-01-07 18:06:32 +00:00
|
|
|
withgitrepo = bracket (setuprepo mainrepodir) return
|
2011-01-07 01:39:26 +00:00
|
|
|
|
|
|
|
indir :: FilePath -> Assertion -> Assertion
|
|
|
|
indir dir a = do
|
2011-01-07 00:09:49 +00:00
|
|
|
cwd <- getCurrentDirectory
|
2011-01-08 19:00:04 +00:00
|
|
|
-- Assertion failures throw non-IO errors; catch
|
|
|
|
-- any type of error and change back to cwd before
|
|
|
|
-- rethrowing.
|
|
|
|
r <- bracket_ (changeToTmpDir dir)
|
2011-01-07 00:09:49 +00:00
|
|
|
(\_ -> changeWorkingDirectory cwd)
|
2011-01-08 19:00:04 +00:00
|
|
|
(E.try (a)::IO (Either E.SomeException ()))
|
|
|
|
case r of
|
|
|
|
Right () -> return ()
|
2011-01-08 19:14:41 +00:00
|
|
|
Left e -> throw e
|
2011-01-07 00:09:49 +00:00
|
|
|
|
2011-01-07 01:39:26 +00:00
|
|
|
setuprepo :: FilePath -> IO FilePath
|
|
|
|
setuprepo dir = do
|
|
|
|
cleanup dir
|
|
|
|
ensuretmpdir
|
2011-01-07 05:02:06 +00:00
|
|
|
Utility.boolSystem "git" ["init", "-q", dir] @? "git init failed"
|
2011-01-07 01:39:26 +00:00
|
|
|
return dir
|
|
|
|
|
|
|
|
copyrepo :: FilePath -> FilePath -> IO FilePath
|
|
|
|
copyrepo old new = do
|
|
|
|
cleanup new
|
|
|
|
ensuretmpdir
|
2011-01-07 05:02:06 +00:00
|
|
|
Utility.boolSystem "cp" ["-pr", old, new] @? "cp -pr failed"
|
2011-01-07 01:39:26 +00:00
|
|
|
return new
|
2011-01-07 02:22:09 +00:00
|
|
|
|
|
|
|
-- clones are always done as local clones; we cannot test ssh clones
|
|
|
|
clonerepo :: FilePath -> FilePath -> IO FilePath
|
|
|
|
clonerepo old new = do
|
|
|
|
cleanup new
|
|
|
|
ensuretmpdir
|
2011-01-07 05:02:06 +00:00
|
|
|
Utility.boolSystem "git" ["clone", "-q", old, new] @? "git clone failed"
|
2011-01-07 18:06:32 +00:00
|
|
|
indir new $ git_annex "init" ["-q", new] @? "git annex init failed"
|
2011-01-07 02:22:09 +00:00
|
|
|
return new
|
2011-01-07 01:39:26 +00:00
|
|
|
|
|
|
|
ensuretmpdir :: IO ()
|
|
|
|
ensuretmpdir = do
|
|
|
|
e <- doesDirectoryExist tmpdir
|
|
|
|
unless e $
|
|
|
|
createDirectory tmpdir
|
|
|
|
|
|
|
|
cleanup :: FilePath -> IO ()
|
|
|
|
cleanup dir = do
|
|
|
|
e <- doesDirectoryExist dir
|
|
|
|
when e $ do
|
|
|
|
-- git-annex prevents annexed file content from being
|
|
|
|
-- removed via permissions bits; undo
|
|
|
|
_ <- Utility.boolSystem "chmod" ["+rw", "-R", dir]
|
|
|
|
removeDirectoryRecursive dir
|
2011-01-07 02:22:09 +00:00
|
|
|
|
|
|
|
checklink :: FilePath -> Assertion
|
|
|
|
checklink f = do
|
|
|
|
s <- getSymbolicLinkStatus f
|
2011-01-07 05:02:06 +00:00
|
|
|
isSymbolicLink s @? f ++ " is not a symlink"
|
2011-01-07 02:22:09 +00:00
|
|
|
|
2011-01-07 05:02:06 +00:00
|
|
|
checkregularfile :: FilePath -> Assertion
|
|
|
|
checkregularfile f = do
|
|
|
|
s <- getSymbolicLinkStatus f
|
|
|
|
isRegularFile s @? f ++ " is not a normal file"
|
|
|
|
return ()
|
|
|
|
|
|
|
|
checkcontent :: FilePath -> Assertion
|
|
|
|
checkcontent f = do
|
|
|
|
c <- readFile f
|
|
|
|
assertEqual ("checkcontent " ++ f) c (content f)
|
2011-01-07 02:22:09 +00:00
|
|
|
|
|
|
|
checkunwritable :: FilePath -> Assertion
|
|
|
|
checkunwritable f = do
|
2011-01-07 18:06:32 +00:00
|
|
|
r <- try $ writeFile f $ content f
|
2011-01-07 02:22:09 +00:00
|
|
|
case r of
|
|
|
|
Left _ -> return () -- expected permission error
|
|
|
|
Right _ -> assertFailure $ "was able to modify annexed file's " ++ f ++ " content"
|
|
|
|
|
2011-01-07 18:06:32 +00:00
|
|
|
checkwritable :: FilePath -> Assertion
|
|
|
|
checkwritable f = do
|
|
|
|
r <- try $ writeFile f $ content f
|
|
|
|
case r of
|
|
|
|
Left _ -> assertFailure $ "unable to modify " ++ f
|
|
|
|
Right _ -> return ()
|
|
|
|
|
2011-01-07 02:22:09 +00:00
|
|
|
checkdangling :: FilePath -> Assertion
|
|
|
|
checkdangling f = do
|
|
|
|
r <- try $ readFile f
|
|
|
|
case r of
|
|
|
|
Left _ -> return () -- expected; dangling link
|
|
|
|
Right _ -> assertFailure $ f ++ " was not a dangling link as expected"
|
2011-01-07 01:39:26 +00:00
|
|
|
|
2011-01-11 19:43:29 +00:00
|
|
|
checklocationlog :: FilePath -> Bool -> Assertion
|
|
|
|
checklocationlog f expected = do
|
2011-01-11 22:50:18 +00:00
|
|
|
thisuuid <- annexeval $ do
|
|
|
|
g <- Annex.gitRepo
|
|
|
|
UUID.getUUID g
|
|
|
|
r <- annexeval $ Backend.lookupFile f
|
2011-01-11 19:43:29 +00:00
|
|
|
case r of
|
|
|
|
Just (k, _) -> do
|
2011-01-11 22:50:18 +00:00
|
|
|
uuids <- annexeval $ do
|
|
|
|
g <- Annex.gitRepo
|
|
|
|
liftIO $ LocationLog.keyLocations g k
|
|
|
|
assertEqual ("bad content in location log for " ++ f ++ " key " ++ (show k) ++ " uuid " ++ thisuuid)
|
2011-01-11 19:43:29 +00:00
|
|
|
expected (elem thisuuid uuids)
|
2011-01-11 20:00:40 +00:00
|
|
|
|
|
|
|
-- Location log files should always be checked
|
|
|
|
-- into git, and any modifications staged for
|
|
|
|
-- commit. This is a regression test, as some
|
|
|
|
-- commands forgot to.
|
2011-01-11 22:50:18 +00:00
|
|
|
(fs, ufs) <- annexeval $ do
|
|
|
|
g <- Annex.gitRepo
|
|
|
|
let lf = LocationLog.logFile g k
|
|
|
|
fs <- liftIO $ Git.inRepo g [lf]
|
|
|
|
ufs <- liftIO $ Git.changedUnstagedFiles g [lf]
|
|
|
|
return (fs, ufs)
|
2011-01-11 20:00:40 +00:00
|
|
|
when (null fs) $
|
|
|
|
assertFailure $ f ++ " logfile not added to git repo"
|
|
|
|
when (not $ null ufs) $
|
|
|
|
assertFailure $ f ++ " logfile changes not staged"
|
2011-01-11 19:43:29 +00:00
|
|
|
_ -> assertFailure $ f ++ " failed to look up key"
|
|
|
|
|
|
|
|
inlocationlog :: FilePath -> Assertion
|
|
|
|
inlocationlog f = checklocationlog f True
|
|
|
|
|
|
|
|
notinlocationlog :: FilePath -> Assertion
|
|
|
|
notinlocationlog f = checklocationlog f False
|
|
|
|
|
2011-01-07 18:06:32 +00:00
|
|
|
runchecks :: [FilePath -> Assertion] -> FilePath -> Assertion
|
|
|
|
runchecks [] _ = return ()
|
|
|
|
runchecks (a:as) f = do
|
|
|
|
a f
|
|
|
|
runchecks as f
|
|
|
|
|
|
|
|
annexed_notpresent :: FilePath -> Assertion
|
2011-01-11 19:43:29 +00:00
|
|
|
annexed_notpresent = runchecks
|
|
|
|
[checklink, checkdangling, checkunwritable, notinlocationlog]
|
2011-01-07 18:06:32 +00:00
|
|
|
|
|
|
|
annexed_present :: FilePath -> Assertion
|
2011-01-11 19:43:29 +00:00
|
|
|
annexed_present = runchecks
|
|
|
|
[checklink, checkcontent, checkunwritable, inlocationlog]
|
2011-01-07 18:06:32 +00:00
|
|
|
|
|
|
|
unannexed :: FilePath -> Assertion
|
|
|
|
unannexed = runchecks [checkregularfile, checkcontent, checkwritable]
|
|
|
|
|
|
|
|
prepare :: IO ()
|
|
|
|
prepare = do
|
|
|
|
-- While PATH is mostly avoided, the commit hook does run it. Make
|
|
|
|
-- sure that the just-built git annex is used.
|
|
|
|
cwd <- getCurrentDirectory
|
|
|
|
p <- getEnvDefault "PATH" ""
|
|
|
|
setEnv "PATH" (cwd ++ ":" ++ p) True
|
|
|
|
setEnv "TOPDIR" cwd True
|
|
|
|
|
|
|
|
changeToTmpDir :: FilePath -> IO ()
|
|
|
|
changeToTmpDir t = do
|
|
|
|
-- Hack alert. Threading state to here was too much bother.
|
|
|
|
topdir <- getEnvDefault "TOPDIR" ""
|
|
|
|
changeWorkingDirectory $ topdir ++ "/" ++ t
|
|
|
|
|
|
|
|
tmpdir :: String
|
2011-01-07 01:39:26 +00:00
|
|
|
tmpdir = ".t"
|
|
|
|
|
2011-01-07 18:06:32 +00:00
|
|
|
mainrepodir :: String
|
|
|
|
mainrepodir = tmpdir ++ "/repo"
|
2011-01-07 01:39:26 +00:00
|
|
|
|
|
|
|
tmprepodir :: String
|
|
|
|
tmprepodir = tmpdir ++ "/tmprepo"
|
2011-01-07 18:06:32 +00:00
|
|
|
|
2011-01-07 05:02:06 +00:00
|
|
|
annexedfile :: String
|
|
|
|
annexedfile = "foo"
|
|
|
|
|
2011-01-11 23:59:11 +00:00
|
|
|
sha1annexedfile :: String
|
|
|
|
sha1annexedfile = "sha1foo"
|
|
|
|
|
2011-01-07 05:02:06 +00:00
|
|
|
ingitfile :: String
|
|
|
|
ingitfile = "bar"
|
2011-01-07 02:22:09 +00:00
|
|
|
|
2011-01-07 05:02:06 +00:00
|
|
|
content :: FilePath -> String
|
|
|
|
content f
|
|
|
|
| f == annexedfile = "annexed file content"
|
|
|
|
| f == ingitfile = "normal file content"
|
2011-01-11 23:59:11 +00:00
|
|
|
| f == sha1annexedfile ="sha1 annexed file content"
|
2011-01-07 05:02:06 +00:00
|
|
|
| otherwise = "unknown file " ++ f
|
2011-01-07 18:06:32 +00:00
|
|
|
|
|
|
|
changecontent :: FilePath -> IO ()
|
|
|
|
changecontent f = writeFile f $ changedcontent f
|
|
|
|
|
|
|
|
changedcontent :: FilePath -> String
|
|
|
|
changedcontent f = (content f) ++ " (modified)"
|