add --dry-run: New option
This is intended for users who want to see what it would output in order to eg, check if a file would be added to git or the annex. It is not intended as a way for scripts to get information. Sponsored-by: Dartmouth College's Datalad project
This commit is contained in:
parent
e005bd6f98
commit
3a513cfe73
10 changed files with 78 additions and 27 deletions
|
@ -10,6 +10,7 @@ git-annex (10.20220725) UNRELEASED; urgency=medium
|
|||
* Added new matching options --want-get-by and --want-drop-by.
|
||||
* Allow find --branch to be used in a bare repository, the same as
|
||||
the deprecated findref can be.
|
||||
* add --dry-run: New option.
|
||||
|
||||
-- Joey Hess <id@joeyh.name> Mon, 25 Jul 2022 15:35:45 -0400
|
||||
|
||||
|
|
|
@ -128,6 +128,12 @@ parseUUIDOption :: String -> DeferredParse UUID
|
|||
parseUUIDOption = DeferredParse
|
||||
. (Remote.nameToUUID)
|
||||
|
||||
parseDryRunOption :: Parser DryRun
|
||||
parseDryRunOption = DryRun <$> switch
|
||||
( long "dry-run"
|
||||
<> help "don't make changes, but show what would be done"
|
||||
)
|
||||
|
||||
-- | From or To a remote.
|
||||
data FromToOptions
|
||||
= FromRemote (DeferredParse Remote)
|
||||
|
|
|
@ -106,6 +106,12 @@ stop = return Nothing
|
|||
stopUnless :: Annex Bool -> Annex (Maybe a) -> Annex (Maybe a)
|
||||
stopUnless c a = ifM c ( a , stop )
|
||||
|
||||
{- When doing a dry run, avoid actually performing the action, but pretend
|
||||
- that it succeeded. -}
|
||||
skipWhenDryRun :: DryRun -> CommandPerform -> CommandPerform
|
||||
skipWhenDryRun (DryRun False) a = a
|
||||
skipWhenDryRun (DryRun True) _ = next $ return True
|
||||
|
||||
{- When acting on a failed transfer, stops unless it was in the specified
|
||||
- direction. -}
|
||||
checkFailedTransferDirection :: ActionItem -> Direction -> Annex (Maybe a) -> Annex (Maybe a)
|
||||
|
|
|
@ -52,6 +52,7 @@ data AddOptions = AddOptions
|
|||
, updateOnly :: Bool
|
||||
, largeFilesOverride :: Maybe Bool
|
||||
, checkGitIgnoreOption :: CheckGitIgnore
|
||||
, dryRunOption :: DryRun
|
||||
}
|
||||
|
||||
optParser :: CmdParamsDesc -> Parser AddOptions
|
||||
|
@ -65,6 +66,7 @@ optParser desc = AddOptions
|
|||
)
|
||||
<*> (parseforcelarge <|> parseforcesmall)
|
||||
<*> checkGitIgnoreSwitch
|
||||
<*> parseDryRunOption
|
||||
where
|
||||
parseforcelarge = flag Nothing (Just True)
|
||||
( long "force-large"
|
||||
|
@ -91,16 +93,16 @@ seek o = startConcurrency commandStages $ do
|
|||
ifM (pure (annexdotfiles || not (dotfile file))
|
||||
<&&> (checkFileMatcher largematcher file
|
||||
<||> Annex.getRead Annex.force))
|
||||
( start si file addunlockedmatcher
|
||||
( start dr si file addunlockedmatcher
|
||||
, if includingsmall
|
||||
then ifM (annexAddSmallFiles <$> Annex.getGitConfig)
|
||||
( startSmall si file s
|
||||
( startSmall dr si file s
|
||||
, stop
|
||||
)
|
||||
else stop
|
||||
)
|
||||
Just True -> start si file addunlockedmatcher
|
||||
Just False -> startSmallOverridden si file
|
||||
Just True -> start dr si file addunlockedmatcher
|
||||
Just False -> startSmallOverridden dr si file
|
||||
case batchOption o of
|
||||
Batch fmt
|
||||
| updateOnly o ->
|
||||
|
@ -126,25 +128,26 @@ seek o = startConcurrency commandStages $ do
|
|||
-- same as a modified unlocked file would get
|
||||
-- locked when added.
|
||||
go False withUnmodifiedUnlockedPointers
|
||||
where
|
||||
dr = dryRunOption o
|
||||
|
||||
{- Pass file off to git-add. -}
|
||||
startSmall :: SeekInput -> RawFilePath -> FileStatus -> CommandStart
|
||||
startSmall si file s =
|
||||
startSmall :: DryRun -> SeekInput -> RawFilePath -> FileStatus -> CommandStart
|
||||
startSmall dr si file s =
|
||||
starting "add" (ActionItemTreeFile file) si $
|
||||
next $ addSmall file s
|
||||
addSmall dr file s
|
||||
|
||||
addSmall :: RawFilePath -> FileStatus -> Annex Bool
|
||||
addSmall file s = do
|
||||
addSmall :: DryRun -> RawFilePath -> FileStatus -> CommandPerform
|
||||
addSmall dr file s = do
|
||||
showNote "non-large file; adding content to git repository"
|
||||
addFile Small file s
|
||||
skipWhenDryRun dr $ next $ addFile Small file s
|
||||
|
||||
startSmallOverridden :: SeekInput -> RawFilePath -> CommandStart
|
||||
startSmallOverridden si file =
|
||||
startSmallOverridden :: DryRun -> SeekInput -> RawFilePath -> CommandStart
|
||||
startSmallOverridden dr si file =
|
||||
liftIO (catchMaybeIO $ R.getSymbolicLinkStatus file) >>= \case
|
||||
Just s -> starting "add" (ActionItemTreeFile file) si $ next $ do
|
||||
|
||||
Just s -> starting "add" (ActionItemTreeFile file) si $ do
|
||||
showNote "adding content to git repository"
|
||||
addFile Small file s
|
||||
skipWhenDryRun dr $ next $ addFile Small file s
|
||||
Nothing -> stop
|
||||
|
||||
data SmallOrLarge = Small | Large
|
||||
|
@ -188,8 +191,8 @@ addFile smallorlarge file s = do
|
|||
isRegularFile a /= isRegularFile b ||
|
||||
isSymbolicLink a /= isSymbolicLink b
|
||||
|
||||
start :: SeekInput -> RawFilePath -> AddUnlockedMatcher -> CommandStart
|
||||
start si file addunlockedmatcher =
|
||||
start :: DryRun -> SeekInput -> RawFilePath -> AddUnlockedMatcher -> CommandStart
|
||||
start dr si file addunlockedmatcher =
|
||||
liftIO (catchMaybeIO $ R.getSymbolicLinkStatus file) >>= \case
|
||||
Nothing -> stop
|
||||
Just s
|
||||
|
@ -200,16 +203,17 @@ start si file addunlockedmatcher =
|
|||
where
|
||||
go s = ifAnnexed file (addpresent s) (add s)
|
||||
add s = starting "add" (ActionItemTreeFile file) si $
|
||||
if isSymbolicLink s
|
||||
then next $ addFile Small file s
|
||||
else perform file addunlockedmatcher
|
||||
skipWhenDryRun dr $
|
||||
if isSymbolicLink s
|
||||
then next $ addFile Small file s
|
||||
else perform file addunlockedmatcher
|
||||
addpresent s key
|
||||
| isSymbolicLink s = fixuplink key
|
||||
| otherwise = add s
|
||||
fixuplink key =
|
||||
starting "add" (ActionItemTreeFile file) si $
|
||||
addingExistingLink file key $
|
||||
withOtherTmp $ \tmp -> do
|
||||
skipWhenDryRun dr $ withOtherTmp $ \tmp -> do
|
||||
let tmpf = tmp P.</> P.takeFileName file
|
||||
liftIO $ moveFile file tmpf
|
||||
ifM (isSymbolicLink <$> liftIO (R.getSymbolicLinkStatus tmpf))
|
||||
|
@ -223,9 +227,10 @@ start si file addunlockedmatcher =
|
|||
)
|
||||
fixuppointer s key =
|
||||
starting "add" (ActionItemTreeFile file) si $
|
||||
addingExistingLink file key $ do
|
||||
Database.Keys.addAssociatedFile key =<< inRepo (toTopFilePath file)
|
||||
next $ addFile Large file s
|
||||
addingExistingLink file key $
|
||||
skipWhenDryRun dr $ do
|
||||
Database.Keys.addAssociatedFile key =<< inRepo (toTopFilePath file)
|
||||
next $ addFile Large file s
|
||||
|
||||
perform :: RawFilePath -> AddUnlockedMatcher -> CommandPerform
|
||||
perform file addunlockedmatcher = withOtherTmp $ \tmpdir -> do
|
||||
|
|
|
@ -476,7 +476,7 @@ addWorkTree _ addunlockedmatcher u url file key mtmp = case mtmp of
|
|||
(fromRawFilePath file)
|
||||
(fromRawFilePath tmp)
|
||||
go
|
||||
else void $ Command.Add.addSmall file s
|
||||
else void $ Command.Add.addSmall (DryRun False) file s
|
||||
where
|
||||
go = do
|
||||
maybeShowJSON $ JSONChunk [("key", serializeKey key)]
|
||||
|
|
|
@ -248,7 +248,7 @@ startLocal o addunlockedmatcher largematcher mode (srcfile, destfile) =
|
|||
>>= maybe
|
||||
stop
|
||||
(\addedk -> next $ Command.Add.cleanup addedk True)
|
||||
, next $ Command.Add.addSmall destfile s
|
||||
, Command.Add.addSmall (DryRun False) destfile s
|
||||
)
|
||||
notoverwriting why = do
|
||||
warning $ "not overwriting existing " ++ fromRawFilePath destfile ++ " " ++ why
|
||||
|
|
|
@ -133,3 +133,6 @@ descSection SectionUtility = "Utility commands"
|
|||
descSection SectionPlumbing = "Plumbing commands"
|
||||
descSection SectionTesting = "Testing commands"
|
||||
descSection SectionAddOn = "Addon commands"
|
||||
|
||||
newtype DryRun = DryRun Bool
|
||||
deriving (Show)
|
||||
|
|
|
@ -77,6 +77,10 @@ annexed content, and other symlinks.
|
|||
Like `git add --update`, this does not add new files, but any updates
|
||||
to tracked files will be added to the index.
|
||||
|
||||
* `--dry-run`
|
||||
|
||||
Output what would be done for each file, but avoid making any changes.
|
||||
|
||||
* `--json`
|
||||
|
||||
Enable JSON output. This is intended to be parsed by programs that use
|
||||
|
|
|
@ -22,3 +22,4 @@ well -- unless there was a version staged already you don't want to loose etc.
|
|||
[[!meta author=yoh]]
|
||||
[[!tag projects/datalad]]
|
||||
|
||||
> [[done]] joey
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
[[!comment format=mdwn
|
||||
username="joey"
|
||||
subject="""comment 2"""
|
||||
date="2022-08-03T14:53:35Z"
|
||||
content="""
|
||||
Implemented `git-annex add --dry-run`.
|
||||
|
||||
As noted it does not let you tell if a file would be added locked or unlocked
|
||||
since `git-annex add` output is the same either way.
|
||||
|
||||
Also when JSON output is enabled, `git-annex add` usually outputs the key,
|
||||
but with `--dry-run`, it does not. Generating the key would involve locking
|
||||
down the file, and by that point the command is making changes to the
|
||||
filesystem. Use `git-annex calckey` instead.
|
||||
|
||||
Implementation was not as simple as making CommandPerform a no-op. Some parts
|
||||
of CommandPerform actions needed to be run when doing a dry-run, in order for
|
||||
addingExistingLink to display its warning, and for showNote to display the
|
||||
very information that the user is interested in seeing from --dry-run.
|
||||
|
||||
A cleaner implementation would probably involve moving those actions out of
|
||||
CommandPerform, perhaps by splitting CommandPerform into two parts.
|
||||
Which would be a lot of work and still failure prone. That is why I don't
|
||||
think it's a good idea to add --dry-run to very many commands.
|
||||
"""]]
|
Loading…
Add table
Reference in a new issue