From 550097a645348426a3e5944d0457925381ff8e23 Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Mon, 23 Mar 2026 02:02:02 -0400 Subject: diff-highlight: drop perl version dependency back to 5.8 The diff-highlight code does not rely on any perl features beyond what perl 5.8 provides. We bumped it to v5.26 along with the rest of the project's perl scripts in 702d8c1f3b (Require Perl 5.26.0, 2024-10-23). There's some value in just having a uniform baseline for the project, but I think diff-highlight is special here: - it's in a contrib/ directory that is not frequently touched, so there is little risk of Git developers getting annoyed that modern perl features are not available - it provides a module used by other projects. In particular, diff-so-fancy relies on DiffHighlight.pm but does not otherwise require a perl version more modern than 5.8. Let's drop back to the more conservative requirement. Signed-off-by: Scott Baker Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- contrib/diff-highlight/DiffHighlight.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib/diff-highlight/DiffHighlight.pm') diff --git a/contrib/diff-highlight/DiffHighlight.pm b/contrib/diff-highlight/DiffHighlight.pm index f0607a4b68..a5e5de3b18 100644 --- a/contrib/diff-highlight/DiffHighlight.pm +++ b/contrib/diff-highlight/DiffHighlight.pm @@ -1,6 +1,6 @@ package DiffHighlight; -require v5.26; +require v5.008; use warnings FATAL => 'all'; use strict; -- cgit v1.3-5-g9baa From bd958e91dffdba00ef94dc9bfc04b46599362f9a Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Mon, 23 Mar 2026 02:02:15 -0400 Subject: diff-highlight: allow module callers to pass in color config Users of the module may want to pass in their own color config for a few obvious reasons: - they are pulling the config from different variables than diff-highlight itself uses - they are loading the config in a more efficient way (say, by parsing git-config --list) and don't want to incur the six (!) git-config calls that DiffHighlight.pm runs to check all config Let's allow users of the module to pass in the color config, and lazy-load it when needed if they haven't. Signed-off-by: Scott Baker Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- contrib/diff-highlight/DiffHighlight.pm | 41 +++++++++++++++++++++++---------- contrib/diff-highlight/README | 6 +++++ 2 files changed, 35 insertions(+), 12 deletions(-) (limited to 'contrib/diff-highlight/DiffHighlight.pm') diff --git a/contrib/diff-highlight/DiffHighlight.pm b/contrib/diff-highlight/DiffHighlight.pm index a5e5de3b18..96369eadf9 100644 --- a/contrib/diff-highlight/DiffHighlight.pm +++ b/contrib/diff-highlight/DiffHighlight.pm @@ -9,18 +9,11 @@ use File::Spec; my $NULL = File::Spec->devnull(); -# Highlight by reversing foreground and background. You could do -# other things like bold or underline if you prefer. -my @OLD_HIGHLIGHT = ( - color_config('color.diff-highlight.oldnormal'), - color_config('color.diff-highlight.oldhighlight', "\x1b[7m"), - color_config('color.diff-highlight.oldreset', "\x1b[27m") -); -my @NEW_HIGHLIGHT = ( - color_config('color.diff-highlight.newnormal', $OLD_HIGHLIGHT[0]), - color_config('color.diff-highlight.newhighlight', $OLD_HIGHLIGHT[1]), - color_config('color.diff-highlight.newreset', $OLD_HIGHLIGHT[2]) -); +# The color theme is initially set to nothing here to allow outside callers +# to set the colors for their application. If nothing is sent in we use +# colors from git config in load_color_config(). +our @OLD_HIGHLIGHT = (); +our @NEW_HIGHLIGHT = (); my $RESET = "\x1b[m"; my $COLOR = qr/\x1b\[[0-9;]*m/; @@ -170,6 +163,29 @@ sub show_hunk { $line_cb->(@queue); } +sub load_color_config { + # If the colors were NOT set from outside this module we load them on-demand + # from the git config. Note that only one of elements 0 and 2 in each + # array is used (depending on whether you are doing set/unset on an + # attribute, or specifying normal vs highlighted coloring). So we use + # element 1 as our check for whether colors were passed in; it should + # always be set if you want highlighting to do anything. + if (!defined $OLD_HIGHLIGHT[1]) { + @OLD_HIGHLIGHT = ( + color_config('color.diff-highlight.oldnormal'), + color_config('color.diff-highlight.oldhighlight', "\x1b[7m"), + color_config('color.diff-highlight.oldreset', "\x1b[27m") + ); + } + if (!defined $NEW_HIGHLIGHT[1]) { + @NEW_HIGHLIGHT = ( + color_config('color.diff-highlight.newnormal', $OLD_HIGHLIGHT[0]), + color_config('color.diff-highlight.newhighlight', $OLD_HIGHLIGHT[1]), + color_config('color.diff-highlight.newreset', $OLD_HIGHLIGHT[2]) + ); + }; +} + sub highlight_pair { my @a = split_line(shift); my @b = split_line(shift); @@ -218,6 +234,7 @@ sub highlight_pair { } if (is_pair_interesting(\@a, $pa, $sa, \@b, $pb, $sb)) { + load_color_config(); return highlight_line(\@a, $pa, $sa, \@OLD_HIGHLIGHT), highlight_line(\@b, $pb, $sb, \@NEW_HIGHLIGHT); } diff --git a/contrib/diff-highlight/README b/contrib/diff-highlight/README index 9c89146fb0..ed8d876a18 100644 --- a/contrib/diff-highlight/README +++ b/contrib/diff-highlight/README @@ -138,6 +138,12 @@ Your script may set up one or more of the following variables: processing a logical chunk of input). The default function flushes stdout. + - @DiffHighlight::OLD_HIGHLIGHT and @DiffHighlight::NEW_HIGHLIGHT - these + arrays specify the normal, highlighted, and reset colors (in that order) + for old/new lines. If unset, values will be retrieved by calling `git + config` (see "Color Config" above). Note that these should be the literal + color bytes (starting with an ANSI escape code), not color names. + The script may then feed lines, one at a time, to DiffHighlight::handle_line(). When lines are done processing, they will be fed to $line_cb. Note that DiffHighlight may queue up many input lines (to analyze a whole hunk) -- cgit v1.3-5-g9baa From 6689a6ea493b484d6a43601f42c1633706c963d6 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 23 Mar 2026 02:02:18 -0400 Subject: diff-highlight: fetch all config with one process When diff-highlight was written, there was no way to fetch multiple config keys _and_ have them interpreted as colors. So we were stuck with either invoking git-config once for each config key, or fetching them all and converting human-readable color names into ANSI codes ourselves. I chose the former, but it means that diff-highlight kicks off 6 git-config processes (even if you haven't configured anything, it has to check each one). But since Git 2.18.0, we can do: git config --type=color --get-regexp=^color\.diff-highlight\. to get all of them in one shot. Note that any callers which pass in colors directly to the module via @OLD_HIGHLIGHT and @NEW_HIGHLIGHT (like diff-so-fancy plans to do) are unaffected; those colors suppress any config lookup we'd do ourselves. You can see the effect like: # diff-highlight suppresses git-config's stderr, so dump # trace through descriptor 3 git show d1f33c753d | GIT_TRACE=3 diff-highlight 3>&2 >/dev/null which drops from 6 lines down to 1. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- contrib/diff-highlight/DiffHighlight.pm | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'contrib/diff-highlight/DiffHighlight.pm') diff --git a/contrib/diff-highlight/DiffHighlight.pm b/contrib/diff-highlight/DiffHighlight.pm index 96369eadf9..abe457882e 100644 --- a/contrib/diff-highlight/DiffHighlight.pm +++ b/contrib/diff-highlight/DiffHighlight.pm @@ -131,9 +131,21 @@ sub highlight_stdin { # of it being used in other settings. Let's handle our own # fallback, which means we will work even if git can't be run. sub color_config { + our $cached_config; my ($key, $default) = @_; - my $s = `git config --get-color $key 2>$NULL`; - return length($s) ? $s : $default; + + if (!defined $cached_config) { + $cached_config = {}; + my $data = `git config --type=color --get-regexp '^color\.diff-highlight\.' 2>$NULL`; + for my $line (split /\n/, $data) { + my ($key, $color) = split ' ', $line, 2; + $key =~ s/^color\.diff-highlight\.// or next; + $cached_config->{$key} = $color; + } + } + + my $s = $cached_config->{$key}; + return defined($s) ? $s : $default; } sub show_hunk { @@ -172,16 +184,16 @@ sub load_color_config { # always be set if you want highlighting to do anything. if (!defined $OLD_HIGHLIGHT[1]) { @OLD_HIGHLIGHT = ( - color_config('color.diff-highlight.oldnormal'), - color_config('color.diff-highlight.oldhighlight', "\x1b[7m"), - color_config('color.diff-highlight.oldreset', "\x1b[27m") + color_config('oldnormal'), + color_config('oldhighlight', "\x1b[7m"), + color_config('oldreset', "\x1b[27m") ); } if (!defined $NEW_HIGHLIGHT[1]) { @NEW_HIGHLIGHT = ( - color_config('color.diff-highlight.newnormal', $OLD_HIGHLIGHT[0]), - color_config('color.diff-highlight.newhighlight', $OLD_HIGHLIGHT[1]), - color_config('color.diff-highlight.newreset', $OLD_HIGHLIGHT[2]) + color_config('newnormal', $OLD_HIGHLIGHT[0]), + color_config('newhighlight', $OLD_HIGHLIGHT[1]), + color_config('newreset', $OLD_HIGHLIGHT[2]) ); }; } -- cgit v1.3-5-g9baa