From 24838547e2475b37d7e910361f9b6e087a1a0648 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 18 Oct 2018 15:32:42 -0400 Subject: [PATCH] adjust --hide-missing * 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. Still needs integration with sync and the assistant, and not as fast as it could be, but already usable. This commit was sponsored by Ethan Aubin. --- Annex/AdjustedBranch.hs | 68 +++++++++++++++---- CHANGELOG | 6 ++ Command/Adjust.hs | 25 ++++--- ..._1ed5e10e51078a0aa7e6968ef48687a3._comment | 10 +++ ..._1ed5e10e51078a0aa7e6968ef48687a3._comment | 10 +++ doc/git-annex-adjust.mdwn | 27 +++++++- ..._e3bf8aaecc0f612873609c92814dcd12._comment | 25 +++++++ 7 files changed, 148 insertions(+), 23 deletions(-) create mode 100644 doc/forum/How_do_I_hide_files_not_present_in_the_local_annex__63__/comment_5_1ed5e10e51078a0aa7e6968ef48687a3._comment create mode 100644 doc/forum/How_to_hide_broken_symlinks/comment_5_1ed5e10e51078a0aa7e6968ef48687a3._comment create mode 100644 doc/todo/hide_missing_files/comment_4_e3bf8aaecc0f612873609c92814dcd12._comment 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. +"""]]