[PATCH v4 0/2] blame: make diff algorithm configurable
From: Antonin Delpeuch via GitGitGadget <hidden>
Date: 2025-11-01 21:57:37
Changes since v3: * fix resetting of diff algorithm by adding XDF_NEED_MINIMAL to XDF_DIFF_ALGORITHM_MASK * restore --no-minimal support * fix typo in description of --minimal option * remove the 'for now' in test description * remove piping in tests * pass configuration variables to the blame command directly instead of calling 'git config' Antonin Delpeuch (2): xdiff: add 'minimal' to XDF_DIFF_ALGORITHM_MASK blame: make diff algorithm configurable Documentation/diff-algorithm-option.adoc | 20 +++ Documentation/diff-options.adoc | 21 +-- Documentation/git-blame.adoc | 2 + builtin/blame.c | 52 +++++- diff.c | 2 - merge-ort.c | 2 - t/meson.build | 1 + t/t8015-blame-diff-algorithm.sh | 203 +++++++++++++++++++++++ xdiff/xdiff.h | 2 +- 9 files changed, 279 insertions(+), 26 deletions(-) create mode 100644 Documentation/diff-algorithm-option.adoc create mode 100755 t/t8015-blame-diff-algorithm.sh base-commit: 4253630c6f07a4bdcc9aa62a50e26a4d466219d1 Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2075%2Fwetneb%2Fblame_respects_diff_algorithm-v4 Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2075/wetneb/blame_respects_diff_algorithm-v4 Pull-Request: https://github.com/git/git/pull/2075 Range-diff vs v3: -: ---------- > 1: e81a5d2bd2 xdiff: add 'minimal' to XDF_DIFF_ALGORITHM_MASK 1: b8bdb03516 ! 2: 920a6f3acb blame: make diff algorithm configurable @@ builtin/blame.c: static int blame_move_callback(const struct option *option, con +{ + int *opt = option->value; + -+ BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); + + *opt &= ~XDF_DIFF_ALGORITHM_MASK; -+ *opt |= XDF_NEED_MINIMAL; ++ if (!unset) ++ *opt |= XDF_NEED_MINIMAL; + + return 0; +} @@ builtin/blame.c: int cmd_blame(int argc, OPT_BIT(0, "color-by-age", &output_option, N_("color lines by age"), OUTPUT_SHOW_AGE_WITH_COLOR), - OPT_BIT(0, "minimal", &xdl_opts, N_("spend extra cycles to find better match"), XDF_NEED_MINIMAL), + OPT_CALLBACK_F(0, "minimal", &xdl_opts, NULL, -+ N_("spend extra cycles to find better match"), -+ PARSE_OPT_NONEG | PARSE_OPT_NOARG, -+ blame_diff_algorithm_minimal), ++ N_("spend extra cycles to find a better match"), ++ PARSE_OPT_NOARG, blame_diff_algorithm_minimal), OPT_STRING('S', NULL, &revs_file, N_("file"), N_("use revisions from <file> instead of calling git-rev-list")), OPT_STRING(0, "contents", &contents_from, N_("file"), N_("use <file>'s contents as the final image")), OPT_CALLBACK_F('C', NULL, &opt, N_("score"), N_("find line copies within and across files"), PARSE_OPT_OPTARG, blame_copy_callback), @@ t/t8015-blame-diff-algorithm.sh (new) + GIT_AUTHOR_NAME=Commit_2 git commit -m Commit_2 +' + -+test_expect_success 'blame uses Myers diff algorithm by default for now' ' ++test_expect_success 'blame uses Myers diff algorithm by default' ' + cat >expected <<-\EOF && + Commit_2 int g(size_t u) + Commit_1 { @@ t/t8015-blame-diff-algorithm.sh (new) + Commit_1 } + EOF + -+ -+ git blame file.c | \ -+ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" | \ -+ sed -e "s/ *$//g" > actual && ++ git blame file.c > output && ++ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" output > without_varying_parts && ++ sed -e "s/ *$//g" without_varying_parts > actual && + test_cmp expected actual +' + @@ t/t8015-blame-diff-algorithm.sh (new) + Commit_2 } + EOF + -+ git blame file.c --diff-algorithm histogram | \ -+ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" | \ -+ sed -e "s/ *$//g" > actual && ++ git blame file.c --diff-algorithm histogram > output && ++ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" output > without_varying_parts && ++ sed -e "s/ *$//g" without_varying_parts > actual && + test_cmp expected actual +' + @@ t/t8015-blame-diff-algorithm.sh (new) + Commit_2 } + EOF + -+ git config diff.algorithm histogram && -+ git blame file.c | \ -+ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" | \ -+ sed -e "s/ *$//g" > actual && ++ git -c diff.algorithm=histogram blame file.c > output && ++ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" output > without_varying_parts && ++ sed -e "s/ *$//g" without_varying_parts > actual && + test_cmp expected actual +' + @@ t/t8015-blame-diff-algorithm.sh (new) + Commit_2 } + EOF + -+ git config diff.algorithm myers && -+ git blame file.c --diff-algorithm histogram | \ -+ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" | \ -+ sed -e "s/ *$//g" > actual && ++ git -c diff.algorithm=myers blame file.c --diff-algorithm histogram && ++ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" output > without_varying_parts && ++ sed -e "s/ *$//g" without_varying_parts > actual && + test_cmp expected actual +' ++ +test_expect_success 'blame honors --minimal option' ' + cat >expected <<-\EOF && + Commit_1 x @@ t/t8015-blame-diff-algorithm.sh (new) + Commit_2 G + EOF + -+ git blame file.txt --minimal | \ -+ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" > actual && ++ git blame file.txt --minimal > output && ++ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" output > actual && + test_cmp expected actual +' + @@ t/t8015-blame-diff-algorithm.sh (new) + Commit_2 G + EOF + -+ git blame file.txt --minimal --diff-algorithm myers | \ -+ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" > actual && ++ git blame file.txt --minimal --diff-algorithm myers > output && ++ sed -e "s/^[^ ]* (\([^ ]*\) [^)]*)/\1/g" output > actual && + test_cmp expected actual +' + -+ +test_done -- gitgitgadget