diffdriver: Added --text option for easy diffing of the contents of annexed text...
authorJoey Hess <joeyh@joeyh.name>
Wed, 28 Jun 2023 19:26:46 +0000 (15:26 -0400)
committerJoey Hess <joeyh@joeyh.name>
Wed, 28 Jun 2023 19:27:16 +0000 (15:27 -0400)
This was already possible, but it was rather hard to come up with the
complex shell command needed.

Note that the diff output starts with "diff a/... b/...".
I left off the "--git" because it's not a git format diff.

CHANGELOG
Command/DiffDriver.hs
doc/git-annex-diffdriver.mdwn
doc/git-annex.mdwn
doc/todo/Straight-forward_diffing_with___39__git_annex_diff__39__.mdwn
doc/todo/Straight-forward_diffing_with___39__git_annex_diff__39__/comment_1_2f5ea091b7f6defa397d15055d04a67d._comment [new file with mode: 0644]

index e41f67de5358cee727b142b448b7f68fe8e5c180..220a2306b2d2ce54d135464002bc68a85e6e6689 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,8 @@
 git-annex (10.20230627) UNRELEASED; urgency=medium
 
   * reinject: Added --guesskeys option.
+  * diffdriver: Added --text option for easy diffing of the contents of
+    annexed text files.
 
  -- Joey Hess <id@joeyh.name>  Mon, 26 Jun 2023 13:10:40 -0400
 
index 9b1e3ec512a0ac314e8439081eaaea959c53adc8..c63994d8ab7ee0f4b73cbc1b0edafe838f9e1e2d 100644 (file)
@@ -1,6 +1,6 @@
 {- git-annex command
  -
- - Copyright 2014-2021 Joey Hess <id@joeyh.name>
+ - Copyright 2014-2023 Joey Hess <id@joeyh.name>
  -
  - Licensed under the GNU AGPL version 3 or higher.
  -}
@@ -15,13 +15,26 @@ import Git.Types
 cmd :: Command
 cmd = dontCheck repoExists $
        command "diffdriver" SectionPlumbing 
-               "external git diff driver shim"
-               ("-- cmd --") (withParams seek)
+               "git diff driver"
+               ("-- cmd --") (seek <$$> optParser)
 
-seek :: CmdParams -> CommandSeek
-seek = withWords (commandAction . start)
+data Options = Options
+       { textDiff :: Bool
+       , restOptions :: CmdParams
+       }
 
-start :: [String] -> CommandStart
+optParser :: CmdParamsDesc -> Parser Options
+optParser desc = Options
+       <$> switch
+               ( long "text"
+               <> help "diff text files with diff(1)"
+               )
+       <*> cmdParams desc
+
+seek :: Options -> CommandSeek
+seek = commandAction . start
+
+start :: Options -> CommandStart
 start opts = do
        let (req, differ) = parseReq opts
        void $ liftIO . exitBool =<< liftIO . differ =<< fixupReq req
@@ -55,10 +68,12 @@ serializeReq req@(Req {}) = map Param
        , rNewMode req
        ]
 
-parseReq :: [String] -> (Req, Differ)
-parseReq opts = case separate (== "--") opts of
-       (c:ps, l) -> (mk l, externalDiffer c ps)
-       ([],_) -> badopts
+parseReq :: Options -> (Req, Differ)
+parseReq opts
+       | textDiff opts = (mk (restOptions opts), textDiffer)
+       | otherwise = case separate (== "--") (restOptions opts) of
+               (c:ps, l) -> (mk l, externalDiffer c ps)
+               ([],_) -> badopts
   where
        mk (path:old_file:old_hex:old_mode:new_file:new_hex:new_mode:[]) =
                Req
@@ -73,7 +88,7 @@ parseReq opts = case separate (== "--") opts of
        mk (unmergedpath:[]) = UnmergedReq { rPath = unmergedpath }
        mk _ = badopts
 
-       badopts = giveup $ "Unexpected input: " ++ unwords opts
+       badopts = giveup $ "Unexpected input: " ++ unwords (restOptions opts)
 
 {- Check if either file is a symlink to a git-annex object,
  - which git-diff will leave as a normal file containing the link text.
@@ -101,3 +116,14 @@ fixupReq req@(Req {}) =
 
 externalDiffer :: String -> [String] -> Differ
 externalDiffer c ps = \req -> boolSystem c (map Param ps ++ serializeReq req )
+
+textDiffer :: Differ
+textDiffer req = do
+       putStrLn ("diff a/" ++ rPath req ++ " b/" ++ rPath req)
+       -- diff exits nonzero on difference, so ignore exit status
+       void $ boolSystem "diff"
+               [ Param "-u"
+               , Param (rOldFile req)
+               , Param (rNewFile req)
+               ]
+       return True
index 6033ebdb52e3bcbcacd0cb26ddb708a3934ef551..34e2ce1a71ab15c611aa09b22645f7bb99e62d47 100644 (file)
@@ -1,35 +1,50 @@
 # NAME
 
-git-annex diffdriver - external git diff driver shim
+git-annex diffdriver - git diff driver
 
 # SYNOPSIS
 
+git annex diffdriver --text
+
 git annex diffdriver `-- cmd --opts --`
 
 # DESCRIPTION
 
-This is an external git diff driver shim. Normally, when using `git diff`
-with an external diff driver, it will not see the contents of annexed
-files, since git passes to it the git-annex symlinks or pointer files.
-This command works around the problem, by running the 
-real external diff driver, and passing it the paths to the annexed content.
+Normally, `git diff` when run on annexed files displays the changes that
+are staged in git, eg annex symlinks and pointers. This command allows
+`git diff` to diff the content of annexed files instead.
+
+This command can be used either as a simple text differ,
+or as a shim that runs an external git diff driver.
 
-To use this, you will need to have installed some git external diff driver
-command. This is not the regular diff command; it takes a git-specific
-input. See git's documentation of `GIT_EXTERNAL_DIFF` and
+If some of your annexed files are textual in form, and can be usefully
+diffed with diff(1), you can configure git to use this command to diff
+them, by configuring `.gitattributes` to contain eg `*.txt diff=annextextdiff`
+and setting `git config diff.annextextdiff.command "git annex diffdriver --text"`
+
+If your annexed files are not textual in form, you will need an external
+diff driver program that is able to diff the file format(s) you use.
+See git's documentation of `GIT_EXTERNAL_DIFF` and
 gitattributes(5)'s documentation of external diff drivers.
 
-Configure git to use "git-annex diffdriver -- cmd params --"
+Normally, when using `git diff` with an external diff driver, it will not
+see the contents of annexed files, since git passes to it the git-annex
+symlinks or pointer files. This command works around the problem, by
+running the real external diff driver, and passing it the paths to the
+annexed content. Configure git to use "git-annex diffdriver -- cmd params --"
 as the external diff driver, where cmd is the external diff
 driver you want it to run, and params are any extra parameters to pass
 to it. Note the trailing "--", which is required.
 
-For example, set `GIT_EXTERNAL_DIFF="git-annex diffdriver -- j-c-diff --"`
+For example, to use the j-c-diff program as the external diff driver, 
+set `GIT_EXTERNAL_DIFF="git-annex diffdriver -- j-c-diff --"`
 
 # OPTIONS
 
-Normally "--" followed by the diff driver command, its options, 
-and another "--"
+To diff text files with diff(1), use the "--text" option.
+
+To use an external diff driver command, the options must start with
+"--" followed by the diff driver command, its options, and another "--"
 
 Also the [[git-annex-common-options]](1) can be used.
 
index 83112cd0c300cee14fdcf991ad19938f1479da59..1a2a2887a0548cc5f00a1c9b4567b5fa9762aab3 100644 (file)
@@ -731,8 +731,7 @@ content from the key-value store.
 
 * `diffdriver`
 
-  This can be used to make `git diff` use an external diff driver with
-  annexed files.
+  This can be used to make `git diff` diff the content of annexed files.
 
   See [[git-annex-diffdriver]](1) for details.
 
index 5b2eb9e2ef8f279c48cd0f66c54d96b6be36fcf7..243697db7acde490e6e771696681907a41b1b86e 100644 (file)
@@ -25,3 +25,5 @@ What do you think?
 Cheers, Yann
 
 PS: Thank you very much for git-annex, it's awesome! I'm giving a git-annex workshop next weekend [@Tuebix](https://cfp.tuebix.org/tuebix-2023/talk/review/GWRP3UKE3VFKVDG8RNQ8ZZPCZPNZYYWM), really looking forward to it.
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/todo/Straight-forward_diffing_with___39__git_annex_diff__39__/comment_1_2f5ea091b7f6defa397d15055d04a67d._comment b/doc/todo/Straight-forward_diffing_with___39__git_annex_diff__39__/comment_1_2f5ea091b7f6defa397d15055d04a67d._comment
new file mode 100644 (file)
index 0000000..618195c
--- /dev/null
@@ -0,0 +1,28 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2023-06-28T17:43:19Z"
+ content="""
+This works:
+
+       echo * diff=text >>.gitattributes
+       git config diff.text.command "git-annex diffdriver -- sh -c 'echo diff a/\$0 b/\$0; echo \$0; diff -u \$1 \$4 || true' --"
+
+Unfortunatly, the textconv approach will not work for locked files, because
+git does not apply the textconv to symlinks. It could be made to work for
+unlocked files but the above works for all annexed files.
+
+diffing like this is only useful on text files, and most annexed files
+are not text files. That's why the diffdriver command focuses on using some
+external diff driver that knows how to diff whatever type of binary file is
+being stored in git-annex. So this should certianly not be enabled by
+default. It makes sense to enable it in .gitattributes when you have
+annexed some textual files.
+
+That command is a bit hard to come up with, with the complex shell quoting.
+So rather than try to document it, I made an easier way to do the same
+thing:
+
+       echo * diff=text >>.gitattributes
+       git config diff.text.command "git annex diffdriver --text"
+"""]]