2010-11-09 19:59:49 +00:00
{- git - annex command
-
2015-12-11 14:42:18 +00:00
- Copyright 2010 , 2015 Joey Hess < id @ joeyh . name >
2010-11-09 19:59:49 +00:00
-
- Licensed under the GNU GPL version 3 or higher .
- }
module Command.Lock where
import Command
2011-10-04 04:40:47 +00:00
import qualified Annex.Queue
2013-12-05 20:05:07 +00:00
import qualified Annex
2015-12-11 14:42:18 +00:00
import Annex.Version
import Annex.Content
import Annex.Link
import Annex.InodeSentinal
2015-12-11 19:13:36 +00:00
import Annex.Perms
import Annex.ReplaceFile
2015-12-11 14:42:18 +00:00
import Utility.InodeCache
import qualified Database.Keys
2015-12-22 17:23:33 +00:00
import Annex.Ingest
2015-12-11 19:13:36 +00:00
import Logs.Location
2016-01-05 21:22:19 +00:00
import Git.FilePath
2010-12-30 19:06:26 +00:00
2015-07-08 16:33:27 +00:00
cmd :: Command
2015-07-10 17:18:46 +00:00
cmd = notDirect $ withGlobalOptions annexedMatchingOptions $
2015-07-08 19:08:02 +00:00
command " lock " SectionCommon
" undo unlock command "
paramPaths ( withParams seek )
2010-11-09 19:59:49 +00:00
2015-07-08 19:08:02 +00:00
seek :: CmdParams -> CommandSeek
2015-12-11 14:42:18 +00:00
seek ps = ifM versionSupportsUnlockedPointers
( withFilesInGit ( whenAnnexed startNew ) ps
, do
2015-12-15 18:08:07 +00:00
withFilesOldUnlocked startOld ps
withFilesOldUnlockedToBeCommitted startOld ps
2015-12-11 14:42:18 +00:00
)
2010-11-11 22:54:52 +00:00
2015-12-11 14:42:18 +00:00
startNew :: FilePath -> Key -> CommandStart
2015-12-11 19:13:36 +00:00
startNew file key = ifM ( isJust <$> isAnnexLink file )
( stop
, do
showStart " lock " file
2016-01-01 17:22:38 +00:00
go =<< liftIO ( isPointerFile file )
2015-12-11 19:13:36 +00:00
)
2015-12-11 14:42:18 +00:00
where
go ( Just key' )
2016-01-06 20:01:52 +00:00
| key' == key = error " content not present; cannot lock "
2015-12-11 14:42:18 +00:00
| otherwise = errorModified
go Nothing =
ifM ( isUnmodified key file )
( cont False
, ifM ( Annex . getState Annex . force )
( cont True
, errorModified
)
)
cont = next . performNew file key
2010-11-09 19:59:49 +00:00
2015-12-11 14:42:18 +00:00
performNew :: FilePath -> Key -> Bool -> CommandPerform
performNew file key filemodified = do
2015-12-11 19:13:36 +00:00
lockdown =<< calcRepo ( gitAnnexLocation key )
2015-12-22 17:23:33 +00:00
addLink file key
2015-12-11 14:42:18 +00:00
=<< withTSDelta ( liftIO . genInodeCache file )
next $ cleanupNew file key
2015-12-11 19:13:36 +00:00
where
lockdown obj = do
2015-12-16 19:35:42 +00:00
ifM ( catchBoolIO $ sameInodeCache obj =<< Database . Keys . getInodeCaches key )
2015-12-11 19:13:36 +00:00
( breakhardlink obj
, repopulate obj
)
2015-12-16 19:35:42 +00:00
whenM ( liftIO $ doesFileExist obj ) $
freezeContent obj
2015-12-11 19:13:36 +00:00
-- It's ok if the file is hard linked to obj, but if some other
-- associated file is, we need to break that link to lock down obj.
2015-12-16 19:35:42 +00:00
breakhardlink obj = whenM ( catchBoolIO $ ( > 1 ) . linkCount <$> liftIO ( getFileStatus obj ) ) $ do
2015-12-11 19:13:36 +00:00
mfc <- withTSDelta ( liftIO . genInodeCache file )
unlessM ( sameInodeCache obj ( maybeToList mfc ) ) $ do
modifyContent obj $ replaceFile obj $ \ tmp -> do
unlessM ( checkedCopyFile key obj tmp ) $
2015-12-27 19:59:59 +00:00
error " unable to lock file "
2015-12-11 19:13:36 +00:00
Database . Keys . storeInodeCaches key [ obj ]
-- Try to repopulate obj from an unmodified associated file.
repopulate obj
| filemodified = modifyContent obj $ do
2016-01-05 21:22:19 +00:00
g <- Annex . gitRepo
2016-01-26 18:28:43 +00:00
fs <- map ( ` fromTopFilePath ` g )
2016-01-05 21:22:19 +00:00
<$> Database . Keys . getAssociatedFiles key
2015-12-11 19:13:36 +00:00
mfile <- firstM ( isUnmodified key ) fs
liftIO $ nukeFile obj
case mfile of
Just unmodified ->
unlessM ( checkedCopyFile key unmodified obj )
lostcontent
Nothing -> lostcontent
| otherwise = modifyContent obj $
liftIO $ renameFile file obj
lostcontent = logStatus key InfoMissing
2015-12-11 14:42:18 +00:00
cleanupNew :: FilePath -> Key -> CommandCleanup
cleanupNew file key = do
2016-01-05 21:22:19 +00:00
Database . Keys . removeAssociatedFile key =<< inRepo ( toTopFilePath file )
2015-12-11 14:42:18 +00:00
return True
startOld :: FilePath -> CommandStart
startOld file = do
showStart " lock " file
unlessM ( Annex . getState Annex . force )
errorModified
next $ performOld file
performOld :: FilePath -> CommandPerform
performOld file = do
2012-06-07 19:19:44 +00:00
Annex . Queue . addCommand " checkout " [ Param " -- " ] [ file ]
2015-12-11 14:42:18 +00:00
next $ return True
errorModified :: a
errorModified = error " Locking this file would discard any changes you have made to it. Use 'git annex add' to stage your changes. (Or, use --force to override) "