Annexed file contents are now made unwritable and put in unwriteable directories, to avoid them accidentially being removed or modified. (Thanks Josh Triplett for the idea.)
This commit is contained in:
parent
8dd9f8e49e
commit
1d32d902c9
8 changed files with 74 additions and 49 deletions
|
@ -9,12 +9,9 @@ module Command.Add where
|
||||||
|
|
||||||
import Control.Monad.State (liftIO)
|
import Control.Monad.State (liftIO)
|
||||||
import System.Posix.Files
|
import System.Posix.Files
|
||||||
import System.Directory
|
|
||||||
|
|
||||||
import Command
|
import Command
|
||||||
import qualified Annex
|
import qualified Annex
|
||||||
import Utility
|
|
||||||
import Locations
|
|
||||||
import qualified Backend
|
import qualified Backend
|
||||||
import LocationLog
|
import LocationLog
|
||||||
import Types
|
import Types
|
||||||
|
@ -42,11 +39,9 @@ perform (file, backend) = do
|
||||||
|
|
||||||
cleanup :: FilePath -> Key -> SubCmdCleanup
|
cleanup :: FilePath -> Key -> SubCmdCleanup
|
||||||
cleanup file key = do
|
cleanup file key = do
|
||||||
|
moveAnnex key file
|
||||||
logStatus key ValuePresent
|
logStatus key ValuePresent
|
||||||
g <- Annex.gitRepo
|
|
||||||
let dest = annexLocation g key
|
|
||||||
liftIO $ createDirectoryIfMissing True (parentDir dest)
|
|
||||||
liftIO $ renameFile file dest
|
|
||||||
link <- calcGitLink file key
|
link <- calcGitLink file key
|
||||||
liftIO $ createSymbolicLink link file
|
liftIO $ createSymbolicLink link file
|
||||||
Annex.queue "add" [] file
|
Annex.queue "add" [] file
|
||||||
|
|
|
@ -7,12 +7,9 @@
|
||||||
|
|
||||||
module Command.Drop where
|
module Command.Drop where
|
||||||
|
|
||||||
import Control.Monad.State (liftIO)
|
import Control.Monad (when)
|
||||||
import System.Directory
|
|
||||||
|
|
||||||
import Command
|
import Command
|
||||||
import qualified Annex
|
|
||||||
import Locations
|
|
||||||
import qualified Backend
|
import qualified Backend
|
||||||
import LocationLog
|
import LocationLog
|
||||||
import Types
|
import Types
|
||||||
|
@ -39,13 +36,7 @@ perform key backend = do
|
||||||
|
|
||||||
cleanup :: Key -> SubCmdCleanup
|
cleanup :: Key -> SubCmdCleanup
|
||||||
cleanup key = do
|
cleanup key = do
|
||||||
logStatus key ValueMissing
|
|
||||||
inannex <- inAnnex key
|
inannex <- inAnnex key
|
||||||
if (inannex)
|
when (inannex) $ removeAnnex key
|
||||||
then do
|
logStatus key ValueMissing
|
||||||
g <- Annex.gitRepo
|
|
||||||
let loc = annexLocation g key
|
|
||||||
liftIO $ removeFile loc
|
|
||||||
return True
|
return True
|
||||||
else return True
|
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,8 @@
|
||||||
|
|
||||||
module Command.DropKey where
|
module Command.DropKey where
|
||||||
|
|
||||||
import Control.Monad.State (liftIO)
|
|
||||||
import System.Directory
|
|
||||||
|
|
||||||
import Command
|
import Command
|
||||||
import qualified Annex
|
import qualified Annex
|
||||||
import Locations
|
|
||||||
import qualified Backend
|
import qualified Backend
|
||||||
import LocationLog
|
import LocationLog
|
||||||
import Types
|
import Types
|
||||||
|
@ -36,9 +32,7 @@ start keyname = do
|
||||||
|
|
||||||
perform :: Key -> SubCmdPerform
|
perform :: Key -> SubCmdPerform
|
||||||
perform key = do
|
perform key = do
|
||||||
g <- Annex.gitRepo
|
removeAnnex key
|
||||||
let loc = annexLocation g key
|
|
||||||
liftIO $ removeFile loc
|
|
||||||
return $ Just $ cleanup key
|
return $ Just $ cleanup key
|
||||||
|
|
||||||
cleanup :: Key -> SubCmdCleanup
|
cleanup :: Key -> SubCmdCleanup
|
||||||
|
|
|
@ -13,7 +13,6 @@ import Control.Monad (when)
|
||||||
import Command
|
import Command
|
||||||
import qualified Annex
|
import qualified Annex
|
||||||
import Utility
|
import Utility
|
||||||
import Locations
|
|
||||||
import qualified Backend
|
import qualified Backend
|
||||||
import LocationLog
|
import LocationLog
|
||||||
import Types
|
import Types
|
||||||
|
@ -22,21 +21,22 @@ import Messages
|
||||||
|
|
||||||
{- Sets cached content for a key. -}
|
{- Sets cached content for a key. -}
|
||||||
start :: SubCmdStartString
|
start :: SubCmdStartString
|
||||||
start tmpfile = do
|
start file = do
|
||||||
keyname <- Annex.flagGet "key"
|
keyname <- Annex.flagGet "key"
|
||||||
when (null keyname) $ error "please specify the key with --key"
|
when (null keyname) $ error "please specify the key with --key"
|
||||||
backends <- Backend.list
|
backends <- Backend.list
|
||||||
let key = genKey (backends !! 0) keyname
|
let key = genKey (backends !! 0) keyname
|
||||||
showStart "setkey" tmpfile
|
showStart "setkey" file
|
||||||
return $ Just $ perform tmpfile key
|
return $ Just $ perform file key
|
||||||
perform :: FilePath -> Key -> SubCmdPerform
|
perform :: FilePath -> Key -> SubCmdPerform
|
||||||
perform tmpfile key = do
|
perform file key = do
|
||||||
g <- Annex.gitRepo
|
-- the file might be on a different filesystem, so mv is used
|
||||||
let loc = annexLocation g key
|
-- rather than simply calling moveToObjectDir key file
|
||||||
ok <- liftIO $ boolSystem "mv" [tmpfile, loc]
|
ok <- getViaTmp key $ \dest -> liftIO $ boolSystem "mv" [file, dest]
|
||||||
if (not ok)
|
if ok
|
||||||
then error "mv failed!"
|
then return $ Just $ cleanup key
|
||||||
else return $ Just $ cleanup key
|
else error "mv failed!"
|
||||||
|
|
||||||
cleanup :: Key -> SubCmdCleanup
|
cleanup :: Key -> SubCmdCleanup
|
||||||
cleanup key = do
|
cleanup key = do
|
||||||
logStatus key ValuePresent
|
logStatus key ValuePresent
|
||||||
|
|
|
@ -13,7 +13,6 @@ import System.Directory
|
||||||
import Command
|
import Command
|
||||||
import qualified Annex
|
import qualified Annex
|
||||||
import Utility
|
import Utility
|
||||||
import Locations
|
|
||||||
import qualified Backend
|
import qualified Backend
|
||||||
import LocationLog
|
import LocationLog
|
||||||
import Types
|
import Types
|
||||||
|
@ -38,12 +37,14 @@ perform file key backend = do
|
||||||
|
|
||||||
cleanup :: FilePath -> Key -> SubCmdCleanup
|
cleanup :: FilePath -> Key -> SubCmdCleanup
|
||||||
cleanup file key = do
|
cleanup file key = do
|
||||||
logStatus key ValueMissing
|
|
||||||
g <- Annex.gitRepo
|
g <- Annex.gitRepo
|
||||||
let src = annexLocation g key
|
|
||||||
liftIO $ removeFile file
|
liftIO $ removeFile file
|
||||||
liftIO $ Git.run g ["rm", "--quiet", file]
|
liftIO $ Git.run g ["rm", "--quiet", file]
|
||||||
-- git rm deletes empty directories; put them back
|
-- git rm deletes empty directories; put them back
|
||||||
liftIO $ createDirectoryIfMissing True (parentDir file)
|
liftIO $ createDirectoryIfMissing True (parentDir file)
|
||||||
liftIO $ renameFile src file
|
|
||||||
|
fromAnnex key file
|
||||||
|
logStatus key ValueMissing
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
53
Core.hs
53
Core.hs
|
@ -144,7 +144,7 @@ getViaTmp key action = do
|
||||||
success <- action tmp
|
success <- action tmp
|
||||||
if (success)
|
if (success)
|
||||||
then do
|
then do
|
||||||
moveToObjectDir key tmp
|
moveAnnex key tmp
|
||||||
logStatus key ValuePresent
|
logStatus key ValuePresent
|
||||||
return True
|
return True
|
||||||
else do
|
else do
|
||||||
|
@ -152,14 +152,53 @@ getViaTmp key action = do
|
||||||
-- to resume its transfer
|
-- to resume its transfer
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
{- Removes the write bits from a file. -}
|
||||||
|
preventWrite :: FilePath -> IO ()
|
||||||
|
preventWrite f = unsetFileMode f writebits
|
||||||
|
where
|
||||||
|
writebits = foldl unionFileModes ownerWriteMode
|
||||||
|
[groupWriteMode, otherWriteMode]
|
||||||
|
|
||||||
|
{- Turns a file's write bit back on. -}
|
||||||
|
allowWrite :: FilePath -> IO ()
|
||||||
|
allowWrite f = do
|
||||||
|
s <- getFileStatus f
|
||||||
|
setFileMode f $ (fileMode s) `unionFileModes` ownerWriteMode
|
||||||
|
|
||||||
{- Moves a file into .git/annex/objects/ -}
|
{- Moves a file into .git/annex/objects/ -}
|
||||||
moveToObjectDir :: Key -> FilePath -> Annex ()
|
moveAnnex :: Key -> FilePath -> Annex ()
|
||||||
moveToObjectDir key src = do
|
moveAnnex key src = do
|
||||||
g <- Annex.gitRepo
|
g <- Annex.gitRepo
|
||||||
let dest = annexLocation g key
|
let dest = annexLocation g key
|
||||||
liftIO $ createDirectoryIfMissing True (parentDir dest)
|
let dir = parentDir dest
|
||||||
liftIO $ renameFile src dest
|
liftIO $ do
|
||||||
-- TODO directory and file mode tweaks
|
createDirectoryIfMissing True dir
|
||||||
|
renameFile src dest
|
||||||
|
preventWrite dest
|
||||||
|
preventWrite dir
|
||||||
|
|
||||||
|
{- Removes a key's file from .git/annex/objects/ -}
|
||||||
|
removeAnnex :: Key -> Annex ()
|
||||||
|
removeAnnex key = do
|
||||||
|
g <- Annex.gitRepo
|
||||||
|
let file = annexLocation g key
|
||||||
|
let dir = parentDir file
|
||||||
|
liftIO $ do
|
||||||
|
allowWrite dir
|
||||||
|
removeFile file
|
||||||
|
removeDirectory dir
|
||||||
|
|
||||||
|
{- Moves a key's file out of .git/annex/objects/ -}
|
||||||
|
fromAnnex :: Key -> FilePath -> Annex ()
|
||||||
|
fromAnnex key dest = do
|
||||||
|
g <- Annex.gitRepo
|
||||||
|
let file = annexLocation g key
|
||||||
|
let dir = parentDir file
|
||||||
|
liftIO $ do
|
||||||
|
allowWrite dir
|
||||||
|
allowWrite file
|
||||||
|
renameFile file dest
|
||||||
|
removeDirectory dir
|
||||||
|
|
||||||
{- List of keys whose content exists in .git/annex/objects/ -}
|
{- List of keys whose content exists in .git/annex/objects/ -}
|
||||||
getKeysPresent :: Annex [Key]
|
getKeysPresent :: Annex [Key]
|
||||||
|
@ -202,7 +241,7 @@ upgradeFrom0 = do
|
||||||
-- do the reorganisation of the files
|
-- do the reorganisation of the files
|
||||||
let olddir = annexDir g
|
let olddir = annexDir g
|
||||||
keys <- getKeysPresent' olddir
|
keys <- getKeysPresent' olddir
|
||||||
_ <- mapM (\k -> moveToObjectDir k $ olddir ++ "/" ++ keyFile k) keys
|
_ <- mapM (\k -> moveAnnex k $ olddir ++ "/" ++ keyFile k) keys
|
||||||
|
|
||||||
-- update the symlinks to the files
|
-- update the symlinks to the files
|
||||||
files <- liftIO $ Git.inRepo g $ Git.workTree g
|
files <- liftIO $ Git.inRepo g $ Git.workTree g
|
||||||
|
|
3
debian/changelog
vendored
3
debian/changelog
vendored
|
@ -8,6 +8,9 @@ git-annex (0.04) UNRELEASED; urgency=low
|
||||||
git-annex is used in a repository with the old layout.
|
git-annex is used in a repository with the old layout.
|
||||||
* Note that git-annex 0.04 cannot transfer content from old repositories
|
* Note that git-annex 0.04 cannot transfer content from old repositories
|
||||||
that have not yet been upgraded.
|
that have not yet been upgraded.
|
||||||
|
* Annexed file contents are now made unwritable and put in unwriteable
|
||||||
|
directories, to avoid them accidentially being removed or modified.
|
||||||
|
(Thanks Josh Triplett for the idea.)
|
||||||
|
|
||||||
-- Joey Hess <joeyh@debian.org> Mon, 08 Nov 2010 12:36:39 -0400
|
-- Joey Hess <joeyh@debian.org> Mon, 08 Nov 2010 12:36:39 -0400
|
||||||
|
|
||||||
|
|
|
@ -4,3 +4,5 @@
|
||||||
> josh: Oh, I just thought of another slightly crazy but handy idea.
|
> josh: Oh, I just thought of another slightly crazy but handy idea.
|
||||||
> josh: I'd hate to run into a program which somehow followed the symlink and then did an unlink to replace the file.
|
> josh: I'd hate to run into a program which somehow followed the symlink and then did an unlink to replace the file.
|
||||||
> josh: To break that, you could create a new directory under annex's internal directory for each file, and make the directory have no write permission.
|
> josh: To break that, you could create a new directory under annex's internal directory for each file, and make the directory have no write permission.
|
||||||
|
|
||||||
|
[[done]] and done --[[Joey]]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue