diff --git a/Annex/AdjustedBranch.hs b/Annex/AdjustedBranch.hs index bdac72bbeb..a23b70154e 100644 --- a/Annex/AdjustedBranch.hs +++ b/Annex/AdjustedBranch.hs @@ -240,12 +240,21 @@ originalBranch = fmap fromAdjustedBranch <$> inRepo Git.Branch.current - branch). - - Can fail, if no branch is checked out, or if the adjusted branch already - - exists, or perhaps if staged changes conflict with the adjusted branch. + - exists, or if staged changes prevent a checkout. -} enterAdjustedBranch :: Adjustment -> Annex Bool -enterAdjustedBranch adj = go =<< originalBranch +enterAdjustedBranch adj = inRepo Git.Branch.current >>= \case + Just currbranch -> case getAdjustment currbranch of + Just curradj | curradj == adj -> + reenterAdjustedBranch adj currbranch + (fromAdjustedBranch currbranch) + _ -> go currbranch + Nothing -> do + warning "not on any branch!" + return False where - go (Just origbranch) = do + go currbranch = do + let origbranch = fromAdjustedBranch currbranch let adjbranch = adjBranch $ originalToAdjusted origbranch adj ifM (inRepo (Git.Ref.exists adjbranch) <&&> (not <$> Annex.getState Annex.force)) ( do @@ -263,17 +272,52 @@ enterAdjustedBranch adj = go =<< originalBranch ] return False , do - AdjBranch b <- preventCommits $ const $ + b <- preventCommits $ const $ adjustBranch adj origbranch - showOutput -- checkout can have output in large repos - inRepo $ Git.Command.runBool - [ Param "checkout" - , Param $ fromRef $ Git.Ref.base b - ] + checkoutAdjustedBranch b [] ) - go Nothing = do - warning "not on any branch!" - return False + +checkoutAdjustedBranch :: AdjBranch -> [CommandParam] -> Annex Bool +checkoutAdjustedBranch (AdjBranch b) checkoutparams = do + showOutput -- checkout can have output in large repos + inRepo $ Git.Command.runBool $ + [ Param "checkout" + , Param $ fromRef $ Git.Ref.base b + -- always show checkout progress, even if --quiet is used + -- to suppress other messages + , Param "--progress" + ] ++ checkoutparams + +{- Already in a branch with this adjustment, but the user asked to enter it + - again. This should have the same result as checking out the original branch, + - deleting and rebuilding the adjusted branch, and then checking it out. + - But, it can be implemented more efficiently than that. + -} +reenterAdjustedBranch :: Adjustment -> Branch -> OrigBranch -> Annex Bool +reenterAdjustedBranch adj@(PresenceAdjustment _ _) currbranch origbranch = do + b <- preventCommits $ \commitlck -> do + -- Avoid losing any commits that the adjusted branch has that + -- have not yet been propigated back to the origbranch. + _ <- propigateAdjustedCommits' origbranch adj commitlck + + -- Git normally won't do anything when asked to check out the + -- currently checked out branch, even when its ref has + -- changed. Work around this by writing a raw sha to .git/HEAD. + inRepo (Git.Ref.sha currbranch) >>= \case + Just headsha -> inRepo $ \r -> + writeFile (Git.Ref.headFile r) (fromRef headsha) + _ -> noop + + adjustBranch adj origbranch + + -- Make git checkout quiet to avoid warnings about disconnected + -- branch tips being lost. + checkoutAdjustedBranch b [Param "--quiet"] +reenterAdjustedBranch adj@(LinkAdjustment _) _ origbranch = preventCommits $ \commitlck -> do + -- Not really needed here, but done for consistency. + _ <- propigateAdjustedCommits' origbranch adj commitlck + -- No need to do anything else, because link adjustments are stable. + return True adjustToCrippledFileSystem :: Annex () adjustToCrippledFileSystem = do diff --git a/CHANGELOG b/CHANGELOG index f0021ee1bc..7d4a46604a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,11 @@ git-annex (6.20181012) UNRELEASED; urgency=medium + * At long last there's a way to hide annexed files whose content + is missing from the working tree: git-annex adjust --hide-missing + * When already in an adjusted branch, running git-annex adjust + again will update the branch as needed. This is mostly + useful with --hide-missing to hide/unhide files after their content + has been dropped or received. * Removed the old Android app. * Removed support for building with very old ghc < 8.0.1, and with yesod < 1.4.3, and without concurrent-output, diff --git a/Command/Adjust.hs b/Command/Adjust.hs index b2956cbc4d..9f9e6153e5 100644 --- a/Command/Adjust.hs +++ b/Command/Adjust.hs @@ -1,6 +1,6 @@ {- git-annex command - - - Copyright 2016 Joey Hess + - Copyright 2016-2018 Joey Hess - - Licensed under the GNU GPL version 3 or higher. -} @@ -16,21 +16,30 @@ cmd = notBareRepo $ notDirect $ noDaemonRunning $ paramNothing (seek <$$> optParser) optParser :: CmdParamsDesc -> Parser Adjustment -optParser _ = - flag' (LinkAdjustment UnlockAdjustment) +optParser _ = + (LinkAdjustment <$> linkAdjustmentParser) + <|> (PresenceAdjustment <$> presenceAdjustmentParser <*> maybeLinkAdjustmentParser) + +linkAdjustmentParser :: Parser LinkAdjustment +linkAdjustmentParser = + flag' UnlockAdjustment ( long "unlock" <> help "unlock annexed files" ) - <|> flag' (LinkAdjustment FixAdjustment) + <|> flag' FixAdjustment ( long "fix" <> help "fix symlinks to annnexed files" ) - {- Not ready yet - <|> flag' (PresenseAdjustment HideMissingAdjustment) + +maybeLinkAdjustmentParser :: Parser (Maybe LinkAdjustment) +maybeLinkAdjustmentParser = Just <$> linkAdjustmentParser <|> pure Nothing + +presenceAdjustmentParser :: Parser PresenceAdjustment +presenceAdjustmentParser = + flag' HideMissingAdjustment ( long "hide-missing" - <> help "omit annexed files whose content is not present" + <> help "hide annexed files whose content is not present" ) - -} seek :: Adjustment -> CommandSeek seek = commandAction . start diff --git a/doc/forum/How_do_I_hide_files_not_present_in_the_local_annex__63__/comment_5_1ed5e10e51078a0aa7e6968ef48687a3._comment b/doc/forum/How_do_I_hide_files_not_present_in_the_local_annex__63__/comment_5_1ed5e10e51078a0aa7e6968ef48687a3._comment new file mode 100644 index 0000000000..bf55735a57 --- /dev/null +++ b/doc/forum/How_do_I_hide_files_not_present_in_the_local_annex__63__/comment_5_1ed5e10e51078a0aa7e6968ef48687a3._comment @@ -0,0 +1,10 @@ +[[!comment format=mdwn + username="joey" + subject="""comment 5""" + date="2018-10-18T18:59:54Z" + content=""" +Good news everyone! `git annex adjust --hide-missing` sets up a branch +where only files with content available are included. And once in such a +branch, `git annex sync` updates it as necessary to reflect changes in +content availability. +"""]] diff --git a/doc/forum/How_to_hide_broken_symlinks/comment_5_1ed5e10e51078a0aa7e6968ef48687a3._comment b/doc/forum/How_to_hide_broken_symlinks/comment_5_1ed5e10e51078a0aa7e6968ef48687a3._comment new file mode 100644 index 0000000000..bf55735a57 --- /dev/null +++ b/doc/forum/How_to_hide_broken_symlinks/comment_5_1ed5e10e51078a0aa7e6968ef48687a3._comment @@ -0,0 +1,10 @@ +[[!comment format=mdwn + username="joey" + subject="""comment 5""" + date="2018-10-18T18:59:54Z" + content=""" +Good news everyone! `git annex adjust --hide-missing` sets up a branch +where only files with content available are included. And once in such a +branch, `git annex sync` updates it as necessary to reflect changes in +content availability. +"""]] diff --git a/doc/git-annex-adjust.mdwn b/doc/git-annex-adjust.mdwn index 6f32f30298..07319f7f17 100644 --- a/doc/git-annex-adjust.mdwn +++ b/doc/git-annex-adjust.mdwn @@ -4,7 +4,7 @@ git-annex adjust - enter an adjusted branch # SYNOPSIS -git annex adjust `--unlock|--fix` +git annex adjust `--unlock|--fix|--hide-missing [--unlock|--fix]` # DESCRIPTION @@ -20,9 +20,14 @@ While in the adjusted branch, you can use git-annex and git commands as usual. Any commits that you make will initially only be made to the adjusted branch. -To propagate changes from the adjusted branch back to the original branch, +To propagate commits from the adjusted branch back to the original branch, and to other repositories, as well as to merge in changes from other -repositories, use `git annex sync`. +repositories, run `git annex sync`. + +Re-running this command with the same options +while inside the adjusted branch will update the adjusted branch +as necessary (eg for `--hide-missing`), and will also propagate commits +back to the original branch. This command can only be used in a v6 git-annex repository. @@ -40,6 +45,22 @@ This command can only be used in a v6 git-annex repository. unusual way that prevents the symlinks committed to git from pointing at the annex objects. +* `--hide-missing` + + Only include annexed files in the adjusted branch when their content + is present. + + The adjusted branch is not immediately changed when content availability + changes, so if you `git annex drop` files, they will become broken + links in the usual way. And when files that were missing are copied into the + repository from elsewhere, they won't immediatly become visible in the + branch. + + To update the adjusted branch to reflect changes to content availability, + run `git annex adjust --hide-missing` again. + + This option can be combined with --unlock or --fix. + # SEE ALSO [[git-annex]](1) diff --git a/doc/todo/hide_missing_files/comment_4_e3bf8aaecc0f612873609c92814dcd12._comment b/doc/todo/hide_missing_files/comment_4_e3bf8aaecc0f612873609c92814dcd12._comment new file mode 100644 index 0000000000..279d0557d7 --- /dev/null +++ b/doc/todo/hide_missing_files/comment_4_e3bf8aaecc0f612873609c92814dcd12._comment @@ -0,0 +1,25 @@ +[[!comment format=mdwn + username="joey" + subject="""comment 4""" + date="2018-10-18T19:27:43Z" + content=""" +I implemented `git annex adjust --hide-missing`. +It can be run after any change to content availability to update +the adjusted branch, hiding or unhiding files. + +My implementation is not as fast as it could be; each update +is a linear scan of the whole original branch and rebuild of the adjusted +branch. But it all works so we'll defer speeding this up to later bug +reports about it being too slow. ;) + +What still needs to be done: + +* `git annex sync --content` needs to scan the original branch, not the + adjusted branch, to find files to transfer. +* `git annex sync` needs to update the adjusted branch. +* The assistant also needs to scan the original branch when looking for + files to download. +* The assistant ought to update the adjusted branch at some point after + downloads, but it's not clear when. Perhaps this will need to be deferred + until it can be done more cheaply, so it can do it after every file. +"""]]