diffdriver: Added --text option for easy diffing of the contents of annexed text files
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.
This commit is contained in:
parent
2c18fc1d60
commit
d5c6197791
6 changed files with 98 additions and 26 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
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
|
||||
This command can be used either as a simple text differ,
|
||||
or as a shim that runs an external git diff driver.
|
||||
|
||||
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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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]]
|
||||
|
|
|
@ -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"
|
||||
"""]]
|
Loading…
Reference in a new issue