[PATCH] format-patch: clear UNINTERESTING flag before prepare_bases
When users specify the commit range with 'Z..C' pattern for format-patch, all the parents of Z (including Z) would be marked as UNINTERESTING which would prevent revision walk in prepare_bases from getting the prerequisite commits, thus `git format-patch --base Z..C` won't be able to generate the list of prerequisite patch ids. Clear UNINTERESTING flag with clear_object_flags solves this issue. Reported-by: Eduardo Habkost Signed-off-by: Xiaolong Ye --- builtin/log.c | 1 + t/t4014-format-patch.sh | 6 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/builtin/log.c b/builtin/log.c index 4686f68594..01993de6fe 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1746,6 +1746,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (base_commit || base_auto) { struct commit *base = get_base_commit(base_commit, list, nr); reset_revision_walk(); + clear_object_flags(UNINTERESTING); prepare_bases(, base, list, nr); } diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 028d5507a6..53880da7bb 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -1554,13 +1554,15 @@ test_expect_success 'format-patch -o overrides format.outputDirectory' ' test_expect_success 'format-patch --base' ' git checkout side && - git format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual && + git format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual1 && + git format-patch --stdout --base=HEAD~3 HEAD~.. | tail -n 7 >actual2 && echo >expected && echo "base-commit: $(git rev-parse HEAD~3)" >>expected && echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk "{print \$1}")" >>expected && echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk "{print \$1}")" >>expected && signature >> expected && - test_cmp expected actual + test_cmp expected actual1 && + test_cmp expected actual2 ' test_expect_success 'format-patch --base errors out when base commit is in revision list' ' -- 2.16.GIT
[PATCH v6 4/4] format-patch: introduce format.useAutoBase configuration
This allows to record the base commit automatically, it is equivalent to set --base=auto in cmdline. The format.useAutoBase has lower priority than command line option, so if user set format.useAutoBase and pass the command line option in the meantime, base_commit will be the one passed to command line option. Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- Documentation/config.txt | 5 + builtin/log.c| 17 +++-- t/t4014-format-patch.sh | 19 +++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 42d2b50..1fe2a85 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1259,6 +1259,11 @@ format.outputDirectory:: Set a custom directory to store the resulting files instead of the current working directory. +format.useAutoBase:: + A boolean value which lets you enable the `--base=auto` option of + format-patch by default. + + filter..clean:: The command which is used to convert the content of a worktree file to a blob upon checkin. See linkgit:gitattributes[5] for diff --git a/builtin/log.c b/builtin/log.c index db27135..099f4f7 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -702,6 +702,7 @@ static void add_header(const char *value) #define THREAD_DEEP 2 static int thread; static int do_signoff; +static int base_auto; static const char *signature = git_version_string; static const char *signature_file; static int config_cover_letter; @@ -786,6 +787,10 @@ static int git_format_config(const char *var, const char *value, void *cb) } if (!strcmp(var, "format.outputdirectory")) return git_config_string(_output_directory, var, value); + if (!strcmp(var, "format.useautobase")) { + base_auto = git_config_bool(var, value); + return 0; + } return git_log_config(var, value, cb); } @@ -1205,7 +1210,11 @@ static struct commit *get_base_commit(const char *base_commit, struct commit **rev; int i = 0, rev_nr = 0; - if (!strcmp(base_commit, "auto")) { + if (base_commit && strcmp(base_commit, "auto")) { + base = lookup_commit_reference_by_name(base_commit); + if (!base) + die(_("Unknown commit %s"), base_commit); + } else if ((base_commit && !strcmp(base_commit, "auto")) || base_auto) { struct branch *curr_branch = branch_get(NULL); const char *upstream = branch_get_upstream(curr_branch, NULL); if (upstream) { @@ -1227,10 +1236,6 @@ static struct commit *get_base_commit(const char *base_commit, "please use git branch --set-upstream-to to track a remote branch.\n" "Or you could specify base commit by --base= manually.")); } - } else { - base = lookup_commit_reference_by_name(base_commit); - if (!base) - die(_("Unknown commit %s"), base_commit); } ALLOC_ARRAY(rev, total); @@ -1669,7 +1674,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } memset(, 0, sizeof(bases)); - if (base_commit) { + if (base_commit || base_auto) { struct commit *base = get_base_commit(base_commit, list, nr); reset_revision_walk(); prepare_bases(, base, list, nr); diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 8102158..8049cad 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -1546,4 +1546,23 @@ test_expect_success 'format-patch errors out when history involves criss-cross' test_must_fail git format-patch --base=auto -1 ' +test_expect_success 'format-patch format.useAutoBaseoption' ' + test_when_finished "git config --unset format.useAutoBase" && + git checkout local && + git config format.useAutoBase true && + git format-patch --stdout -1 >patch && + grep "^base-commit:" patch >actual && + echo "base-commit: $(git rev-parse upstream)" >expected && + test_cmp expected actual +' + +test_expect_success 'format-patch --base overrides format.useAutoBase' ' + test_when_finished "git config --unset format.useAutoBase" && + git config format.useAutoBase true && + git format-patch --stdout --base=HEAD~1 -1 >patch && + grep "^base-commit:" patch >actual && + echo "base-commit: $(git rev-parse HEAD~1)" >expected && + test_cmp expected actual +' + test_done -- 2.8.1.343.gda643e5 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 3/4] format-patch: introduce --base=auto option
Introduce --base=auto to record the base commit info automatically, the base_commit will be the merge base of tip commit of the upstream branch and revision-range specified in cmdline. Helped-by: Junio C Hamano <gits...@pobox.com> Helped-by: Wu Fengguang <fengguang...@intel.com> Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- Documentation/git-format-patch.txt | 6 ++ builtin/log.c | 30 ++--- t/t4014-format-patch.sh| 39 ++ 3 files changed, 72 insertions(+), 3 deletions(-) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 1d790f1..bdeecd5 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -575,6 +575,12 @@ You can also use `git format-patch --base=P -3 C` to generate patches for A, B and C, and the identifiers for P, X, Y, Z are appended at the end of the first message. +If set `--base=auto` in cmdline, it will track base commit automatically, +the base commit will be the merge base of tip commit of the remote-tracking +branch and revision-range specified in cmdline. +For a local branch, you need to track a remote branch by `git branch +--set-upstream-to` before using this option. + EXAMPLES diff --git a/builtin/log.c b/builtin/log.c index ee332ab..db27135 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1205,9 +1205,33 @@ static struct commit *get_base_commit(const char *base_commit, struct commit **rev; int i = 0, rev_nr = 0; - base = lookup_commit_reference_by_name(base_commit); - if (!base) - die(_("Unknown commit %s"), base_commit); + if (!strcmp(base_commit, "auto")) { + struct branch *curr_branch = branch_get(NULL); + const char *upstream = branch_get_upstream(curr_branch, NULL); + if (upstream) { + struct commit_list *base_list; + struct commit *commit; + unsigned char sha1[20]; + + if (get_sha1(upstream, sha1)) + die(_("Failed to resolve '%s' as a valid ref."), upstream); + commit = lookup_commit_or_die(sha1, "upstream base"); + base_list = get_merge_bases_many(commit, total, list); + /* There should be one and only one merge base. */ + if (!base_list || base_list->next) + die(_("Could not find exact merge base.")); + base = base_list->item; + free_commit_list(base_list); + } else { + die(_("Failed to get upstream, if you want to record base commit automatically,\n" + "please use git branch --set-upstream-to to track a remote branch.\n" + "Or you could specify base commit by --base= manually.")); + } + } else { + base = lookup_commit_reference_by_name(base_commit); + if (!base) + die(_("Unknown commit %s"), base_commit); + } ALLOC_ARRAY(rev, total); for (i = 0; i < total; i++) diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 5dcf24f..8102158 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -1507,4 +1507,43 @@ test_expect_success 'format-patch --base errors out when base commit is not ance test_cmp expected actual ' +test_expect_success 'format-patch --base=auto' ' + git checkout -b upstream master && + git checkout -b local upstream && + git branch --set-upstream-to=upstream && + test_commit N1 && + test_commit N2 && + git format-patch --stdout --base=auto -2 >patch && + grep "^base-commit:" patch >actual && + echo "base-commit: $(git rev-parse upstream)" >expected && + test_cmp expected actual +' + +test_expect_success 'format-patch errors out when history involves criss-cross' ' + # setup criss-cross history + # + # B---M1---D + # / \ / + # A X + # \ / \ + # C---M2---E + # + git checkout master && + test_commit A && + git checkout -b xb master && + test_commit B && + git checkout -b xc master && + test_commit C && + git checkout -b xbc xb -- && + git merge xc && + git checkout -b xcb xc -- && + git branch --set-upstream-to=xbc && + git merge xb && + git checkout xbc && + test_commit D && +
[PATCH v6 1/4] patch-ids: make commit_patch_id() a public helper function
Make commit_patch_id() available to other builtins. Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- patch-ids.c | 2 +- patch-ids.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/patch-ids.c b/patch-ids.c index b7b3e5a..a4d0016 100644 --- a/patch-ids.c +++ b/patch-ids.c @@ -4,7 +4,7 @@ #include "sha1-lookup.h" #include "patch-ids.h" -static int commit_patch_id(struct commit *commit, struct diff_options *options, +int commit_patch_id(struct commit *commit, struct diff_options *options, unsigned char *sha1) { if (commit->parents) diff --git a/patch-ids.h b/patch-ids.h index c8c7ca1..eeb56b3 100644 --- a/patch-ids.h +++ b/patch-ids.h @@ -13,6 +13,8 @@ struct patch_ids { struct patch_id_bucket *patches; }; +int commit_patch_id(struct commit *commit, struct diff_options *options, + unsigned char *sha1); int init_patch_ids(struct patch_ids *); int free_patch_ids(struct patch_ids *); struct patch_id *add_commit_patch_id(struct commit *, struct patch_ids *); -- 2.8.1.343.gda643e5 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 2/4] format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree the patch series applies to. Teach git format-patch a '--base' option to record the base tree info and append it at the end of the first message (either the cover letter or the first patch in the series). The base tree info consists of the "base commit", which is a well-known commit that is part of the stable part of the project history everybody else works off of, and zero or more "prerequisite patches", which are well-known patches in flight that is not yet part of the "base commit" that need to be applied on top of "base commit" in topological order before the patches can be applied. The "base commit" is shown as "base-commit: " followed by the 40-hex of the commit object name. A "prerequisite patch" is shown as "prerequisite-patch-id: " followed by the 40-hex "patch id", which can be obtained by passing the patch through the "git patch-id --stable" command. Imagine that on top of the public commit P, you applied well-known patches X, Y and Z from somebody else, and then built your three-patch series A, B, C, the history would be like: ---P---X---Y---Z---A---B---C With "git format-patch --base=P -3 C" (or variants thereof, e.g. with "--cover-letter" of using "Z..C" instead of "-3 C" to specify the range), the base tree information block is shown at the end of the first message the command outputs (either the first patch, or the cover letter), like this: base-commit: P prerequisite-patch-id: X prerequisite-patch-id: Y prerequisite-patch-id: Z Helped-by: Junio C Hamano <gits...@pobox.com> Helped-by: Wu Fengguang <fengguang...@intel.com> Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- Documentation/git-format-patch.txt | 54 ++ builtin/log.c | 139 + t/t4014-format-patch.sh| 47 + 3 files changed, 240 insertions(+) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 6821441..1d790f1 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -265,6 +265,11 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`. Output an all-zero hash in each patch's From header instead of the hash of the commit. +--base=:: + Record the base tree information to identify the state the + patch series applies to. See the BASE TREE INFORMATION section + below for details. + --root:: Treat the revision argument as a , even if it is just a single commit (that would normally be treated as a @@ -520,6 +525,55 @@ This should help you to submit patches inline using KMail. 5. Back in the compose window: add whatever other text you wish to the message, complete the addressing and subject fields, and press send. +BASE TREE INFORMATION +- + +The base tree information block is used for maintainers or third party +testers to know the exact state the patch series applies to. It consists +of the 'base commit', which is a well-known commit that is part of the +stable part of the project history everybody else works off of, and zero +or more 'prerequisite patches', which are well-known patches in flight +that is not yet part of the 'base commit' that need to be applied on top +of 'base commit' in topological order before the patches can be applied. + +The 'base commit' is shown as "base-commit: " followed by the 40-hex of +the commit object name. A 'prerequisite patch' is shown as +"prerequisite-patch-id: " followed by the 40-hex 'patch id', which can +be obtained by passing the patch through the `git patch-id --stable` +command. + +Imagine that on top of the public commit P, you applied well-known +patches X, Y and Z from somebody else, and then built your three-patch +series A, B, C, the history would be like: + + +---P---X---Y---Z---A---B---C + + +With `git format-patch --base=P -3 C` (or variants thereof, e.g. with +`--cover-letter` of using `Z..C` instead of `-3 C` to specify the +range), the base tree information block is shown at the end of the +first message the command outputs (either the first patch, or the +cover letter), like this: + + +base-commit: P +prerequisite-patch-id: X +prerequisite-patch-id: Y +prerequisite-patch-id: Z + + +For non-linear topology, such as + + +---P---X---A---M---C +\ / + Y---Z---B + + +You can also use `git format-patch --base=P -3 C` to generate patches +for A, B and C, and the identifiers for P, X, Y, Z are appended at the +end of the first
[PATCH v6 0/4] Add --base option to git-format-patch to record base tree info
Thanks for Junio's reviews and suggestions. This version contains the following changes since v5: - Fix a decl-after-statement in patch 3/4. - Improve testcases to cover more scenarios and make them more portable and readable. Thanks, Xiaolong Xiaolong Ye (4): patch-ids: make commit_patch_id() a public helper function format-patch: add '--base' option to record base tree info format-patch: introduce --base=auto option format-patch: introduce format.useAutoBase configuration Documentation/config.txt | 5 ++ Documentation/git-format-patch.txt | 60 + builtin/log.c | 168 + patch-ids.c| 2 +- patch-ids.h| 2 + t/t4014-format-patch.sh| 105 +++ 6 files changed, 341 insertions(+), 1 deletion(-) -- 2.8.1.343.gda643e5 base-commit: 3ad15fd5e17bbb73fb1161ff4e9c3ed254d5b243 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 3/4] format-patch: introduce --base=auto option
Introduce --base=auto to record the base commit info automatically, the base_commit will be the merge base of tip commit of the upstream branch and revision-range specified in cmdline. Helped-by: Junio C Hamano <gits...@pobox.com> Helped-by: Wu Fengguang <fengguang...@intel.com> Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- Documentation/git-format-patch.txt | 6 ++ builtin/log.c | 27 --- t/t4014-format-patch.sh| 15 +++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 1d790f1..bdeecd5 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -575,6 +575,12 @@ You can also use `git format-patch --base=P -3 C` to generate patches for A, B and C, and the identifiers for P, X, Y, Z are appended at the end of the first message. +If set `--base=auto` in cmdline, it will track base commit automatically, +the base commit will be the merge base of tip commit of the remote-tracking +branch and revision-range specified in cmdline. +For a local branch, you need to track a remote branch by `git branch +--set-upstream-to` before using this option. + EXAMPLES diff --git a/builtin/log.c b/builtin/log.c index ee332ab..7851d20 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1205,9 +1205,30 @@ static struct commit *get_base_commit(const char *base_commit, struct commit **rev; int i = 0, rev_nr = 0; - base = lookup_commit_reference_by_name(base_commit); - if (!base) - die(_("Unknown commit %s"), base_commit); + if (!strcmp(base_commit, "auto")) { + struct branch *curr_branch = branch_get(NULL); + const char *upstream = branch_get_upstream(curr_branch, NULL); + if (upstream) { + unsigned char sha1[20]; + if (get_sha1(upstream, sha1)) + die(_("Failed to resolve '%s' as a valid ref."), upstream); + struct commit *commit = lookup_commit_or_die(sha1, "upstream base"); + struct commit_list *base_list = get_merge_bases_many(commit, total, list); + /* There should be one and only one merge base. */ + if (!base_list || base_list->next) + die(_("Could not find exact merge base.")); + base = base_list->item; + free_commit_list(base_list); + } else { + die(_("Failed to get upstream, if you want to record base commit automatically,\n" + "please use git branch --set-upstream-to to track a remote branch.\n" + "Or you could specify base commit by --base= manually.")); + } + } else { + base = lookup_commit_reference_by_name(base_commit); + if (!base) + die(_("Unknown commit %s"), base_commit); + } ALLOC_ARRAY(rev, total); for (i = 0; i < total; i++) diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index a6ce727..afcf8b8 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -1475,4 +1475,19 @@ test_expect_success 'format-patch --base error handling' ' ! git format-patch --base=HEAD~ -3 ' +test_expect_success 'format-patch --base=auto' ' + git checkout -b new master && + git branch --set-upstream-to=master && + echo "A" >>file && + git add file && + git commit -m "New change #A" && + echo "B" >>file && + git add file && + git commit -m "New change #B" && + git format-patch --stdout --base=auto -2 >patch && + grep -e "^base-commit:" patch >actual && + echo "base-commit: $(git rev-parse master)" >expected && + test_cmp expected actual +' + test_done -- 2.8.1.221.ga4c6ba7 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 2/4] format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree the patch series applies to. Teach git format-patch a '--base' option to record the base tree info and append it at the end of the first message (either the cover letter or the first patch in the series). The base tree info consists of the "base commit", which is a well-known commit that is part of the stable part of the project history everybody else works off of, and zero or more "prerequisite patches", which are well-known patches in flight that is not yet part of the "base commit" that need to be applied on top of "base commit" in topological order before the patches can be applied. The "base commit" is shown as "base-commit: " followed by the 40-hex of the commit object name. A "prerequisite patch" is shown as "prerequisite-patch-id: " followed by the 40-hex "patch id", which can be obtained by passing the patch through the "git patch-id --stable" command. Imagine that on top of the public commit P, you applied well-known patches X, Y and Z from somebody else, and then built your three-patch series A, B, C, the history would be like: ---P---X---Y---Z---A---B---C With "git format-patch --base=P -3 C" (or variants thereof, e.g. with "--cover-letter" of using "Z..C" instead of "-3 C" to specify the range), the base tree information block is shown at the end of the first message the command outputs (either the first patch, or the cover letter), like this: base-commit: P prerequisite-patch-id: X prerequisite-patch-id: Y prerequisite-patch-id: Z Helped-by: Junio C Hamano <gits...@pobox.com> Helped-by: Wu Fengguang <fengguang...@intel.com> Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- Documentation/git-format-patch.txt | 54 ++ builtin/log.c | 139 + t/t4014-format-patch.sh| 15 3 files changed, 208 insertions(+) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 6821441..1d790f1 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -265,6 +265,11 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`. Output an all-zero hash in each patch's From header instead of the hash of the commit. +--base=:: + Record the base tree information to identify the state the + patch series applies to. See the BASE TREE INFORMATION section + below for details. + --root:: Treat the revision argument as a , even if it is just a single commit (that would normally be treated as a @@ -520,6 +525,55 @@ This should help you to submit patches inline using KMail. 5. Back in the compose window: add whatever other text you wish to the message, complete the addressing and subject fields, and press send. +BASE TREE INFORMATION +- + +The base tree information block is used for maintainers or third party +testers to know the exact state the patch series applies to. It consists +of the 'base commit', which is a well-known commit that is part of the +stable part of the project history everybody else works off of, and zero +or more 'prerequisite patches', which are well-known patches in flight +that is not yet part of the 'base commit' that need to be applied on top +of 'base commit' in topological order before the patches can be applied. + +The 'base commit' is shown as "base-commit: " followed by the 40-hex of +the commit object name. A 'prerequisite patch' is shown as +"prerequisite-patch-id: " followed by the 40-hex 'patch id', which can +be obtained by passing the patch through the `git patch-id --stable` +command. + +Imagine that on top of the public commit P, you applied well-known +patches X, Y and Z from somebody else, and then built your three-patch +series A, B, C, the history would be like: + + +---P---X---Y---Z---A---B---C + + +With `git format-patch --base=P -3 C` (or variants thereof, e.g. with +`--cover-letter` of using `Z..C` instead of `-3 C` to specify the +range), the base tree information block is shown at the end of the +first message the command outputs (either the first patch, or the +cover letter), like this: + + +base-commit: P +prerequisite-patch-id: X +prerequisite-patch-id: Y +prerequisite-patch-id: Z + + +For non-linear topology, such as + + +---P---X---A---M---C +\ / + Y---Z---B + + +You can also use `git format-patch --base=P -3 C` to generate patches +for A, B and C, and the identifiers for P, X, Y, Z are appended at the +end of the first message. EXAMPLES
[PATCH v5 4/4] format-patch: introduce format.useAutoBase configuration
This allows to record the base commit automatically, it is equivalent to set --base=auto in cmdline. The format.useAutoBase has lower priority than command line option, so if user set format.useAutoBase and pass the command line option in the meantime, base_commit will be the one passed to command line option. Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- Documentation/config.txt | 5 + builtin/log.c| 17 +++-- t/t4014-format-patch.sh | 18 ++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 42d2b50..1fe2a85 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1259,6 +1259,11 @@ format.outputDirectory:: Set a custom directory to store the resulting files instead of the current working directory. +format.useAutoBase:: + A boolean value which lets you enable the `--base=auto` option of + format-patch by default. + + filter..clean:: The command which is used to convert the content of a worktree file to a blob upon checkin. See linkgit:gitattributes[5] for diff --git a/builtin/log.c b/builtin/log.c index 7851d20..c3aeef8 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -702,6 +702,7 @@ static void add_header(const char *value) #define THREAD_DEEP 2 static int thread; static int do_signoff; +static int base_auto; static const char *signature = git_version_string; static const char *signature_file; static int config_cover_letter; @@ -786,6 +787,10 @@ static int git_format_config(const char *var, const char *value, void *cb) } if (!strcmp(var, "format.outputdirectory")) return git_config_string(_output_directory, var, value); + if (!strcmp(var, "format.useautobase")) { + base_auto = git_config_bool(var, value); + return 0; + } return git_log_config(var, value, cb); } @@ -1205,7 +1210,11 @@ static struct commit *get_base_commit(const char *base_commit, struct commit **rev; int i = 0, rev_nr = 0; - if (!strcmp(base_commit, "auto")) { + if (base_commit && strcmp(base_commit, "auto")) { + base = lookup_commit_reference_by_name(base_commit); + if (!base) + die(_("Unknown commit %s"), base_commit); + } else if ((base_commit && !strcmp(base_commit, "auto")) || base_auto) { struct branch *curr_branch = branch_get(NULL); const char *upstream = branch_get_upstream(curr_branch, NULL); if (upstream) { @@ -1224,10 +1233,6 @@ static struct commit *get_base_commit(const char *base_commit, "please use git branch --set-upstream-to to track a remote branch.\n" "Or you could specify base commit by --base= manually.")); } - } else { - base = lookup_commit_reference_by_name(base_commit); - if (!base) - die(_("Unknown commit %s"), base_commit); } ALLOC_ARRAY(rev, total); @@ -1666,7 +1671,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } memset(, 0, sizeof(bases)); - if (base_commit) { + if (base_commit || base_auto) { struct commit *base = get_base_commit(base_commit, list, nr); reset_revision_walk(); prepare_bases(, base, list, nr); diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index afcf8b8..dfee0b6 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -1490,4 +1490,22 @@ test_expect_success 'format-patch --base=auto' ' test_cmp expected actual ' +test_expect_success 'format-patch format.base option' ' + test_when_finished "git config --unset format.useAutoBase" && + git config format.useAutoBase true && + git format-patch --stdout -1 >patch && + grep -e "^base-commit:" patch >actual && + echo "base-commit: $(git rev-parse master)" >expected && + test_cmp expected actual +' + +test_expect_success 'format-patch --base overrides format.base' ' + test_when_finished "git config --unset format.useAutoBase" && + git config format.useAutoBase true && + git format-patch --stdout --base=HEAD~ -1 >patch && + grep -e "^base-commit:" patch >actual && + echo "base-commit: $(git rev-parse HEAD~)" >expected && + test_cmp expected actual +' + test_done -- 2.8.1.221.ga4c6ba7 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 1/4] patch-ids: make commit_patch_id() a public helper function
Make commit_patch_id() available to other builtins. Helped-by: Junio C Hamano <gits...@pobox.com> Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- patch-ids.c | 2 +- patch-ids.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/patch-ids.c b/patch-ids.c index b7b3e5a..a4d0016 100644 --- a/patch-ids.c +++ b/patch-ids.c @@ -4,7 +4,7 @@ #include "sha1-lookup.h" #include "patch-ids.h" -static int commit_patch_id(struct commit *commit, struct diff_options *options, +int commit_patch_id(struct commit *commit, struct diff_options *options, unsigned char *sha1) { if (commit->parents) diff --git a/patch-ids.h b/patch-ids.h index c8c7ca1..eeb56b3 100644 --- a/patch-ids.h +++ b/patch-ids.h @@ -13,6 +13,8 @@ struct patch_ids { struct patch_id_bucket *patches; }; +int commit_patch_id(struct commit *commit, struct diff_options *options, + unsigned char *sha1); int init_patch_ids(struct patch_ids *); int free_patch_ids(struct patch_ids *); struct patch_id *add_commit_patch_id(struct commit *, struct patch_ids *); -- 2.8.1.221.ga4c6ba7 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 0/4] Add --base option to git-format-patch to record base tree info
Thanks for Junio's reviews and suggestions. This version contains the following changes since v4: - Refine the commit log as well as the documentation according to Junio's comments. - Separate out get_base_commit function from prepare_bases to obtain the base commit. - Use repeated pair-wise computation to get the merge base for the validation of base commit. - Extract "auto handling thing" from prepare_bases and put it into get_base_commit. - Use format.useAutoBase boolean variable for the auto configuration in format section. Thanks, Xiaolong. Xiaolong Ye (4): patch-ids: make commit_patch_id() a public helper function format-patch: add '--base' option to record base tree info format-patch: introduce --base=auto option format-patch: introduce format.useAutoBase configuration Documentation/config.txt | 5 ++ Documentation/git-format-patch.txt | 60 ++ builtin/log.c | 165 + patch-ids.c| 2 +- patch-ids.h| 2 + t/t4014-format-patch.sh| 48 +++ 6 files changed, 281 insertions(+), 1 deletion(-) -- 2.8.1.221.ga4c6ba7 base-commit: e6ac6e1f7d54584c2b03f073b5f329a37f4a9561 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 4/4] format-patch: introduce format.base configuration
We can set format.base=auto to record the base commit info automatically, it is equivalent to set --base=auto in cmdline. The format.base has lower priority than command line option, so if user set format.base=auto and pass the command line option in the meantime, base_commit will be the one passed to command line option. Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- Documentation/git-format-patch.txt | 4 builtin/log.c | 21 ++--- t/t4014-format-patch.sh| 19 +++ 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 8283eea..738121d 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -581,6 +581,10 @@ If set `--base=auto` in cmdline, it will track base commit automatically, the base commit will be the merge base of tip commit of the remote-tracking branch and revision-range specified in cmdline. +If 'format.base=auto' is set in configuration file, it is equivalent +to set '--base=auto' in cmdline. + + EXAMPLES diff --git a/builtin/log.c b/builtin/log.c index 510a427..489434a 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -705,6 +705,7 @@ static int do_signoff; static const char *signature = git_version_string; static const char *signature_file; static int config_cover_letter; +static int config_base_commit; static const char *config_output_directory; enum { @@ -786,6 +787,12 @@ static int git_format_config(const char *var, const char *value, void *cb) } if (!strcmp(var, "format.outputdirectory")) return git_config_string(_output_directory, var, value); + if (!strcmp(var, "format.base")){ + if (value && !strcasecmp(value, "auto")) { + config_base_commit = 1; + return 0; + } + } return git_log_config(var, value, cb); } @@ -1215,7 +1222,12 @@ static void prepare_bases(struct base_tree_info *bases, DIFF_OPT_SET(, RECURSIVE); diff_setup_done(); - if (!strcmp(base_commit, "auto")) { + if (base_commit && strcmp(base_commit, "auto")) { + base = lookup_commit_reference_by_name(base_commit); + if (!base) + die(_("Unknown commit %s"), base_commit); + oidcpy(>base_commit, >object.oid); + } else if ((base_commit && !strcmp(base_commit, "auto")) || config_base_commit) { curr_branch = branch_get(NULL); upstream = branch_get_upstream(curr_branch, NULL); if (upstream) { @@ -1234,11 +1246,6 @@ static void prepare_bases(struct base_tree_info *bases, "please use git branch --set-upstream-to to track a remote branch.\n" "Or you could specify base commit by --base= manually.")); } - } else { - base = lookup_commit_reference_by_name(base_commit); - if (!base) - die(_("Unknown commit %s"), base_commit); - oidcpy(>base_commit, >object.oid); } init_revisions(, NULL); @@ -1622,7 +1629,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } memset(, 0, sizeof(bases)); - if (base_commit) { + if (base_commit || config_base_commit) { reset_revision_walk(); prepare_bases(, base_commit, list, nr); } diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 4603915..6005b7c 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -1489,4 +1489,23 @@ test_expect_success 'format-patch --base=auto' ' echo "base-commit: $(git rev-parse master)" >expected && test_cmp expected actual ' + +test_expect_success 'format-patch format.base option' ' + test_when_finished "git config --unset format.base" && + git config format.base auto && + git format-patch --stdout -1 >patch && + grep -e "^base-commit:" patch >actual && + echo "base-commit: $(git rev-parse master)" >expected && + test_cmp expected actual +' + +test_expect_success 'format-patch --base overrides format.base' ' + test_when_finished "git config --unset format.base" && + git config format.base auto && + git format-patch --stdout --base=HEAD~ -1 >patch && + grep -e "^base-commit:" patch >actual && + echo "base-commit: $(git rev-parse HEAD~)" >expected && + test_cmp expected actual +' + test_done -- 2.8.1.120.g24d6b3f -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 3/4] format-patch: introduce --base=auto option
Introduce --base=auto to record the base commit info automatically, the base_commit will be the merge base of tip commit of the upstream branch and revision-range specified in cmdline. Helped-by: Junio C Hamano <gits...@pobox.com> Helped-by: Wu Fengguang <fengguang...@intel.com> Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- Documentation/git-format-patch.txt | 4 builtin/log.c | 32 t/t4014-format-patch.sh| 14 ++ 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 2a4c293..8283eea 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -577,6 +577,10 @@ The submitter could also use `git format-patch --base=P -3 C` to generate patches for A, B and C, and the identifiers for P, X, Y, Z are appended at the end of the _first_ message. +If set `--base=auto` in cmdline, it will track base commit automatically, +the base commit will be the merge base of tip commit of the remote-tracking +branch and revision-range specified in cmdline. + EXAMPLES diff --git a/builtin/log.c b/builtin/log.c index 73bc36d..510a427 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1205,6 +1205,9 @@ static void prepare_bases(struct base_tree_info *bases, struct commit *base = NULL, *commit; struct rev_info revs; struct diff_options diffopt; + struct branch *curr_branch; + struct commit_list *base_list; + const char *upstream; unsigned char sha1[20]; int i; @@ -1212,10 +1215,31 @@ static void prepare_bases(struct base_tree_info *bases, DIFF_OPT_SET(, RECURSIVE); diff_setup_done(); - base = lookup_commit_reference_by_name(base_commit); - if (!base) - die(_("Unknown commit %s"), base_commit); - oidcpy(>base_commit, >object.oid); + if (!strcmp(base_commit, "auto")) { + curr_branch = branch_get(NULL); + upstream = branch_get_upstream(curr_branch, NULL); + if (upstream) { + if (get_sha1(upstream, sha1)) + die(_("Failed to resolve '%s' as a valid ref."), upstream); + commit = lookup_commit_or_die(sha1, "upstream base"); + base_list = get_merge_bases_many(commit, total, list); + /* There should be one and only one merge base. */ + if (!base_list || base_list->next) + die(_("Could not find exact merge base.")); + base = base_list->item; + free_commit_list(base_list); + oidcpy(>base_commit, >object.oid); + } else { + die(_("Failed to get upstream, if you want to record base commit automatically,\n" + "please use git branch --set-upstream-to to track a remote branch.\n" + "Or you could specify base commit by --base= manually.")); + } + } else { + base = lookup_commit_reference_by_name(base_commit); + if (!base) + die(_("Unknown commit %s"), base_commit); + oidcpy(>base_commit, >object.oid); + } init_revisions(, NULL); revs.max_parents = 1; diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index a6ce727..4603915 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -1475,4 +1475,18 @@ test_expect_success 'format-patch --base error handling' ' ! git format-patch --base=HEAD~ -3 ' +test_expect_success 'format-patch --base=auto' ' + git checkout -b new master && + git branch --set-upstream-to=master && + echo "A" >>file && + git add file && + git commit -m "New change #A" && + echo "B" >>file && + git add file && + git commit -m "New change #B" && + git format-patch --stdout --base=auto -2 >patch && + grep -e "^base-commit:" patch >actual && + echo "base-commit: $(git rev-parse master)" >expected && + test_cmp expected actual +' test_done -- 2.8.1.120.g24d6b3f -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 1/4] patch-ids: make commit_patch_id() a public helper function
Make commit_patch_id() available to other builtins. Helped-by: Junio C Hamano <gits...@pobox.com> Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- patch-ids.c | 2 +- patch-ids.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/patch-ids.c b/patch-ids.c index b7b3e5a..a4d0016 100644 --- a/patch-ids.c +++ b/patch-ids.c @@ -4,7 +4,7 @@ #include "sha1-lookup.h" #include "patch-ids.h" -static int commit_patch_id(struct commit *commit, struct diff_options *options, +int commit_patch_id(struct commit *commit, struct diff_options *options, unsigned char *sha1) { if (commit->parents) diff --git a/patch-ids.h b/patch-ids.h index c8c7ca1..eeb56b3 100644 --- a/patch-ids.h +++ b/patch-ids.h @@ -13,6 +13,8 @@ struct patch_ids { struct patch_id_bucket *patches; }; +int commit_patch_id(struct commit *commit, struct diff_options *options, + unsigned char *sha1); int init_patch_ids(struct patch_ids *); int free_patch_ids(struct patch_ids *); struct patch_id *add_commit_patch_id(struct commit *, struct patch_ids *); -- 2.8.1.120.g24d6b3f -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 2/4] format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree the patch series applies to. Teach git format-patch a '--base' option to record the base tree info and append it at the end of the_first_ message(either the cover letter or the first patch in the series). The base tree info consists of the "base commit", which is a well-known commit that is part of the stable part of the project history everybody else works off of, and zero or more "prerequisite patches", which are well-known patches in flight that is not yet part of the "base commit" that need to be applied on top of "base commit" in topological order before the patches can be applied. The "base commit" is shown as "base-commit: " followed by the 40-hex of the commit object name. A "prerequisite patch" is shown as "prerequisite-patch-id: " followed by the 40-hex "patch id", which is a sum of SHA-1 of the file diffs associated with a patch, with whitespace and line numbers ignored, it's reasonably stable and unique. For example, we have history where base is Z, with three prerequisites X-Y-Z, before the patch series A-B-C, i.e. P---X---Y---Z---A---B---C We could say "git format-patch --base=P -3 C"(or variants thereof, e.g. with "--cover-letter" of using "Z..C" instead of "-3 C" to specify the range), then we could get base tree information block showing at the end of _first_ message as below: base-commit: P prerequisite-patch-id: X prerequisite-patch-id: Y prerequisite-patch-id: Z Helped-by: Junio C Hamano <gits...@pobox.com> Helped-by: Wu Fengguang <fengguang...@intel.com> Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- Documentation/git-format-patch.txt | 56 +++ builtin/log.c | 92 ++ t/t4014-format-patch.sh| 15 +++ 3 files changed, 163 insertions(+) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 6821441..2a4c293 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -265,6 +265,11 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`. Output an all-zero hash in each patch's From header instead of the hash of the commit. +--base=:: + Record the base tree information to identify the state the + patch series applies to. See the BASE TREE INFORMATION section + below for details. + --root:: Treat the revision argument as a , even if it is just a single commit (that would normally be treated as a @@ -520,6 +525,57 @@ This should help you to submit patches inline using KMail. 5. Back in the compose window: add whatever other text you wish to the message, complete the addressing and subject fields, and press send. +BASE TREE INFORMATION +- + +The base tree information block is used for maintainers or third party +testers to know the exact state the patch series applies to. It consists +of the 'base commit', which is a well-known commit that is part of the +stable part of the project history everybody else works off of, and zero +or more 'prerequisite patches', which are well-known patches in flight +that is not yet part of the 'base commit' that need to be applied on top +of 'base commit' in topological order before the patches can be applied. + +The 'base commit' is shown as "base-commit: " followed by the 40-hex of +the commit object name. A 'prerequisite patch' is shown as +"prerequisite-patch-id: " followed by the 40-hex 'patch id', which is a +sum of SHA-1 of the file diffs associated with a patch, with whitespace +and line numbers ignored, it's reasonably stable and unique. + +For example, the patch submitter has a commit history of this shape: + + +---P---X---Y---Z---A---B---C + + +where 'P' is the well-known public commit (e.g. one in Linus's tree), +'X', 'Y', 'Z' are prerequisite patches in flight, and 'A', 'B', 'C' +are the work being sent out, the submitter could say `git format-patch +--base=P -3 C` (or variants thereof, e.g. with `--cover` or using +`Z..C` instead of `-3 C` to specify the range), and the identifiers +for P, X, Y, Z are appended at the end of the _first_ message (either +the cover letter or the first patch in the series). Then we could get +base tree information block showing at the end of _first_ message as +below: + + +base-commit: P +prerequisite-patch-id: X +prerequisite-patch-id: Y +prerequisite-patch-id: Z + + +For non-linear topology, such as + + +---P---X---A---M---C +\ / + Y---Z---B +..
[PATCH v4 0/4] Add --base option to git-format-patch to record base tree info
V4 mainly addresses Junio's comments on V3, Changes include: - Polish up the documentation to make output files git-format-patch.1 and git-format-patch.html more sensible. - Add error handling when base commit is not ancestor of revision list specified in cmdline. - Specify topo order to do the traverse work, and show the base tree info block in a more natural sequence. - If --base=auto is set and there is more than one best merge base, instead of picking up a random one, it will error out for they may be complicated situation such as criss-cross merges. - Add tests for the --base option and format.base configuration. - Fix a segfault error due to bases structure hasn't been initialized when --base option is not set, Thanks for Ramsay's report. Xiaolong Ye (4): patch-ids: make commit_patch_id() a public helper function format-patch: add '--base' option to record base tree info format-patch: introduce --base=auto option format-patch: introduce format.base configuration Documentation/git-format-patch.txt | 64 +++ builtin/log.c | 123 + patch-ids.c| 2 +- patch-ids.h| 2 + t/t4014-format-patch.sh| 48 +++ 5 files changed, 238 insertions(+), 1 deletion(-) -- 2.8.1.120.g24d6b3f base-commit: 7b0d47b3b6b5b64e02a5aa06b0452cadcdb18355 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 1/4] patch-ids: make commit_patch_id() a public helper function
Make commit_patch_id() available to other builtins. Helped-by: Junio C Hamano <gits...@pobox.com> Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- patch-ids.c | 2 +- patch-ids.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/patch-ids.c b/patch-ids.c index b7b3e5a..a4d0016 100644 --- a/patch-ids.c +++ b/patch-ids.c @@ -4,7 +4,7 @@ #include "sha1-lookup.h" #include "patch-ids.h" -static int commit_patch_id(struct commit *commit, struct diff_options *options, +int commit_patch_id(struct commit *commit, struct diff_options *options, unsigned char *sha1) { if (commit->parents) diff --git a/patch-ids.h b/patch-ids.h index c8c7ca1..eeb56b3 100644 --- a/patch-ids.h +++ b/patch-ids.h @@ -13,6 +13,8 @@ struct patch_ids { struct patch_id_bucket *patches; }; +int commit_patch_id(struct commit *commit, struct diff_options *options, + unsigned char *sha1); int init_patch_ids(struct patch_ids *); int free_patch_ids(struct patch_ids *); struct patch_id *add_commit_patch_id(struct commit *, struct patch_ids *); -- 2.8.0.4.gcb5a9af -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 4/4] format-patch: introduce format.base configuration
We can set format.base=auto to record the base commit info automatically, it is equivalent to set --base=auto in cmdline. The format.base has lower priority than command line option, so if user set format.base=auto and pass the command line option in the meantime, base_commit will be the one passed to command line option. Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- Documentation/git-format-patch.txt | 2 ++ builtin/log.c | 21 ++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index d8fe651..10149ab 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -293,6 +293,8 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`. If set '--base=auto' in cmdline, it will track base commit automatically, the base commit will be the merge base of tip commit of the remote-tracking branch and revision-range specified in cmdline. + If 'format.base=auto' is set in configuration file, it is equivalent + to set '--base=auto' in cmdline. --root:: Treat the revision argument as a , even if it diff --git a/builtin/log.c b/builtin/log.c index c5efe73..821a778 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -699,6 +699,7 @@ static int do_signoff; static const char *signature = git_version_string; static const char *signature_file; static int config_cover_letter; +static int config_base_commit; static const char *config_output_directory; enum { @@ -780,6 +781,12 @@ static int git_format_config(const char *var, const char *value, void *cb) } if (!strcmp(var, "format.outputdirectory")) return git_config_string(_output_directory, var, value); + if (!strcmp(var, "format.base")){ + if (value && !strcasecmp(value, "auto")) { + config_base_commit = 1; + return 0; + } + } return git_log_config(var, value, cb); } @@ -1210,7 +1217,12 @@ static void prepare_bases(struct base_tree_info *bases, DIFF_OPT_SET(, RECURSIVE); diff_setup_done(); - if (!strcmp(base_commit, "auto")) { + if (base_commit && strcmp(base_commit, "auto")) { + base = lookup_commit_reference_by_name(base_commit); + if (!base) + die(_("Unknown commit %s"), base_commit); + oidcpy(>base_commit, >object.oid); + } else if ((base_commit && !strcmp(base_commit, "auto")) || config_base_commit) { curr_branch = branch_get(NULL); upstream = branch_get_upstream(curr_branch, NULL); if (upstream) { @@ -1228,11 +1240,6 @@ static void prepare_bases(struct base_tree_info *bases, "please use git branch --set-upstream-to to track a remote branch.\n" "Or you could specify base commit by --base= manually.")); } - } else { - base = lookup_commit_reference_by_name(base_commit); - if (!base) - die(_("Unknown commit %s"), base_commit); - oidcpy(>base_commit, >object.oid); } init_revisions(, NULL); @@ -1611,7 +1618,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) signature = strbuf_detach(, NULL); } - if (base_commit) { + if (base_commit || config_base_commit) { memset(, 0, sizeof(bases)); reset_revision_walk(); prepare_bases(, base_commit, list, nr); -- 2.8.0.4.gcb5a9af -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 3/4] format-patch: introduce --base=auto option
Introduce --base=auto to record the base commit info automatically, the base_commit will be the merge base of tip commit of the upstream branch and revision-range specified in cmdline. Helped-by: Junio C Hamano <gits...@pobox.com> Helped-by: Wu Fengguang <fengguang...@intel.com> Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- Documentation/git-format-patch.txt | 4 builtin/log.c | 31 +++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 067d562..d8fe651 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -290,6 +290,10 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`. patches for A, B and C, and the identifiers for P, X, Y, Z are appended at the end of the _first_ message. + If set '--base=auto' in cmdline, it will track base commit automatically, + the base commit will be the merge base of tip commit of the remote-tracking + branch and revision-range specified in cmdline. + --root:: Treat the revision argument as a , even if it is just a single commit (that would normally be treated as a diff --git a/builtin/log.c b/builtin/log.c index 03cbab0..c5efe73 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1200,6 +1200,9 @@ static void prepare_bases(struct base_tree_info *bases, struct rev_info revs; struct diff_options diffopt; struct object_id *patch_id; + struct branch *curr_branch; + struct commit_list *base_list; + const char *upstream; unsigned char sha1[20]; int i; @@ -1207,10 +1210,30 @@ static void prepare_bases(struct base_tree_info *bases, DIFF_OPT_SET(, RECURSIVE); diff_setup_done(); - base = lookup_commit_reference_by_name(base_commit); - if (!base) - die(_("Unknown commit %s"), base_commit); - oidcpy(>base_commit, >object.oid); + if (!strcmp(base_commit, "auto")) { + curr_branch = branch_get(NULL); + upstream = branch_get_upstream(curr_branch, NULL); + if (upstream) { + if (get_sha1(upstream, sha1)) + die(_("Failed to resolve '%s' as a valid ref."), upstream); + commit = lookup_commit_or_die(sha1, "upstream base"); + base_list = get_merge_bases_many(commit, total, list); + if (!bases) + die(_("Could not find merge base.")); + base = base_list->item; + free_commit_list(base_list); + oidcpy(>base_commit, >object.oid); + } else { + die(_("Failed to get upstream, if you want to record base commit automatically,\n" + "please use git branch --set-upstream-to to track a remote branch.\n" + "Or you could specify base commit by --base= manually.")); + } + } else { + base = lookup_commit_reference_by_name(base_commit); + if (!base) + die(_("Unknown commit %s"), base_commit); + oidcpy(>base_commit, >object.oid); + } init_revisions(, NULL); revs.max_parents = 1; -- 2.8.0.4.gcb5a9af -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 0/4] Add an option to git-format-patch to record base tree info
V3 mainly improves the implementation according to Junio's comments, Changes vs v2 include: - Remove the unnecessary output line "** base-commit-info **". - Improve the traverse logic to handle not only linear topology, but more general cases, it will start revision walk by setting the starting points of the traversal to all elements in the rev list[], and skip the ones in list[], only grab the patch-ids of prerequisite patches. - If --base=auto is set, it will get merge base of upstream and rev range we specified and use it as base commit. If there is no upstream, we just error out and suggest to use set-upstream-to to track a remote branch as upstream. v1 can be found here: http://article.gmane.org/gmane.comp.version-control.git/286873 v2 can be found here: http://article.gmane.org/gmane.comp.version-control.git/289603 Xiaolong Ye (4): patch-ids: make commit_patch_id() a public helper function format-patch: add '--base' option to record base tree info format-patch: introduce --base=auto option format-patch: introduce format.base configuration Documentation/git-format-patch.txt | 31 ++ builtin/log.c | 119 + patch-ids.c| 2 +- patch-ids.h| 2 + 4 files changed, 153 insertions(+), 1 deletion(-) -- 2.8.0.4.gcb5a9af base-commit: 90f7b16b3adc78d4bbabbd426fb69aa78c714f71 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 2/4] format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree the patch series applies to. Teach git format-patch a '--base' option to record the base tree info and append this information at the end of the _first_ message (either the cover letter or the first patch in the series). Helped-by: Junio C Hamano <gits...@pobox.com> Helped-by: Wu Fengguang <fengguang...@intel.com> Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- Documentation/git-format-patch.txt | 25 +++ builtin/log.c | 89 ++ 2 files changed, 114 insertions(+) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 6821441..067d562 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -265,6 +265,31 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`. Output an all-zero hash in each patch's From header instead of the hash of the commit. +--base=:: + Record the base tree information to identify the whole tree + the patch series applies to. For example, the patch submitter + has a commit history of this shape: + + ---P---X---Y---Z---A---B---C + + where "P" is the well-known public commit (e.g. one in Linus's tree), + "X", "Y", "Z" are prerequisite patches in flight, and "A", "B", "C" + are the work being sent out, the submitter could say "git format-patch + --base=P -3 C" (or variants thereof, e.g. with "--cover" or using + "Z..C" instead of "-3 C" to specify the range), and the identifiers + for P, X, Y, Z are appended at the end of the _first_ message (either + the cover letter or the first patch in the series). + + For non-linear topology, such as + + ---P---X---A---M---C + \ / +Y---Z---B + + the submitter could also use "git format-patch --base=P -3 C" to generate + patches for A, B and C, and the identifiers for P, X, Y, Z are appended + at the end of the _first_ message. + --root:: Treat the revision argument as a , even if it is just a single commit (that would normally be treated as a diff --git a/builtin/log.c b/builtin/log.c index 0d738d6..03cbab0 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1185,6 +1185,82 @@ static int from_callback(const struct option *opt, const char *arg, int unset) return 0; } +struct base_tree_info { + struct object_id base_commit; + int nr_patch_id, alloc_patch_id; + struct object_id *patch_id; +}; + +static void prepare_bases(struct base_tree_info *bases, + const char *base_commit, + struct commit **list, + int total) +{ + struct commit *base = NULL, *commit; + struct rev_info revs; + struct diff_options diffopt; + struct object_id *patch_id; + unsigned char sha1[20]; + int i; + + diff_setup(); + DIFF_OPT_SET(, RECURSIVE); + diff_setup_done(); + + base = lookup_commit_reference_by_name(base_commit); + if (!base) + die(_("Unknown commit %s"), base_commit); + oidcpy(>base_commit, >object.oid); + + init_revisions(, NULL); + revs.max_parents = 1; + base->object.flags |= UNINTERESTING; + add_pending_object(, >object, "base"); + for (i = 0; i < total; i++) { + list[i]->object.flags |= 0; + add_pending_object(, [i]->object, "rev_list"); + list[i]->util = (void *)1; + } + + if (prepare_revision_walk()) + die(_("revision walk setup failed")); + /* +* Traverse the prerequisite commits list, +* get the patch ids and stuff them in bases structure. +*/ + while ((commit = get_revision()) != NULL) { + if (commit->util) + continue; + if (commit_patch_id(commit, , sha1)) + die(_("cannot get patch id")); + ALLOC_GROW(bases->patch_id, bases->nr_patch_id + 1, bases->alloc_patch_id); + patch_id = bases->patch_id + bases->nr_patch_id; + hashcpy(patch_id->hash, sha1); + bases->nr_patch_id++; + } +} + +static void print_bases(struct base_tree_info *bases) +{ + int i; + + /* Only do this once, either for the cover or for the first one */ + if (is_null_oid(>base_commit)) + return; + + /* Show the base commit */ + printf("base-commit: %s\n", oid_to_hex(>base_commit)); + + /* Show the prerequisite patches */ + for (i = 0; i < bases-&g
[PATCH v2 2/4] format-patch: add '--base' option to record base tree info
Maintainers or third party testers may want to know the exact base tree the patch series applies to. Teach git format-patch a '--base' option to record the base tree info and append this information at the end of the _first_ message (either the cover letter or the first patch in the series). Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- Documentation/git-format-patch.txt | 15 ++ builtin/log.c | 98 ++ 2 files changed, 113 insertions(+) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 6821441..a5f145e 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -265,6 +265,21 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`. Output an all-zero hash in each patch's From header instead of the hash of the commit. +--base=:: + Record the base tree information to identify the whole tree + the patch series applies to. For example, the patch submitter + has a commit history of this shape: + + ---P---X---Y---Z---A---B---C + + where "P" is the well-known public commit (e.g. one in Linus's tree), + "X", "Y", "Z" are prerequisite patches in flight, and "A", "B", "C" + are the work being sent out, the submitter would say "format-patch + --base=P -3 C" (or variants thereof, e.g. with "--cover" or using + "Z..C" instead of "-3 C" to specify the range), and the identifiers + for P, X, Y, Z are appended at the end of the _first_ message (either + the cover letter or the first patch in the series). + --root:: Treat the revision argument as a , even if it is just a single commit (that would normally be treated as a diff --git a/builtin/log.c b/builtin/log.c index 0d738d6..d3804b3 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1185,6 +1185,88 @@ static int from_callback(const struct option *opt, const char *arg, int unset) return 0; } +struct base_tree_info { + struct object_id base_commit; + int nr_patch_id, alloc_patch_id; + struct object_id *patch_id; +}; + +static void prepare_bases(struct base_tree_info *bases, + const char *base_commit, + struct commit *prerequisite_head) +{ + struct commit *base = NULL, *commit; + struct rev_info revs; + struct diff_options diffopt; + struct object_id *patch_id; + unsigned char sha1[20]; + int pos = 0; + + if (!prerequisite_head) + return; + base = lookup_commit_reference_by_name(base_commit); + if (!base) + die(_("Unknown commit %s"), base_commit); + oidcpy(>base_commit, >object.oid); + + if (base == prerequisite_head) + return; + + if (!in_merge_bases(base, prerequisite_head)) + die(_("base commit should be the ancestor of revs you specified")); + + init_revisions(, NULL); + revs.max_parents = 1; + + base->object.flags |= UNINTERESTING; + add_pending_object(, >object, "base"); + prerequisite_head->object.flags |= 0; + add_pending_object(, _head->object, "prerequisite-head"); + + diff_setup(); + DIFF_OPT_SET(, RECURSIVE); + diff_setup_done(); + + if (prepare_revision_walk()) + die(_("revision walk setup failed")); + /* +* Traverse the commits list between base and prerequisite head, +* get the patch ids and stuff them in bases structure. +*/ + while ((commit = get_revision()) != NULL) { + if (commit_patch_id(commit, , sha1)) + return; + ALLOC_GROW(bases->patch_id, bases->nr_patch_id + 1, bases->alloc_patch_id); + patch_id = bases->patch_id + pos; + hashcpy(patch_id->hash, sha1); + pos++; + bases->nr_patch_id++; + } +} + +static void print_bases(struct base_tree_info *bases) +{ + int i; + + /* Only do this once, either for the cover or for the first one */ + if (is_null_oid(>base_commit)) + return; + + printf("** base-commit-info **\n"); + + /* Show the base commit */ + printf("base-commit: %s\n", oid_to_hex(>base_commit)); + + /* Show the prerequisite patches */ + for (i = 0; i < bases->nr_patch_id; i++) + printf("prerequisite-patch-id: %s\n", oid_to_hex(>patch_id[i])); + + free(bases->patch_id); + bases->nr_patch_id = 0; + bases->alloc_patch_id = 0; + oidclr(>base_commit); +} + int cmd_format_patch(int argc, const char **argv, const
[PATCH v2 3/4] format-patch: introduce --base=auto option
Introduce --base=auto to record the base commit info automatically, the base_commit will be the tip commit of the upstream branch. If upstream branch cannot be determined, it will just record the parent's commit id and patch id. Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- builtin/log.c | 70 +++ 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/builtin/log.c b/builtin/log.c index d3804b3..e8a3964 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1187,6 +1187,8 @@ static int from_callback(const struct option *opt, const char *arg, int unset) struct base_tree_info { struct object_id base_commit; + struct object_id parent_commit; + struct object_id parent_patch_id; int nr_patch_id, alloc_patch_id; struct object_id *patch_id; }; @@ -1199,15 +1201,38 @@ static void prepare_bases(struct base_tree_info *bases, struct rev_info revs; struct diff_options diffopt; struct object_id *patch_id; + struct branch *curr_branch; + const char *upstream; unsigned char sha1[20]; int pos = 0; if (!prerequisite_head) return; - base = lookup_commit_reference_by_name(base_commit); - if (!base) - die(_("Unknown commit %s"), base_commit); - oidcpy(>base_commit, >object.oid); + + diff_setup(); + DIFF_OPT_SET(, RECURSIVE); + diff_setup_done(); + + if (!strcmp(base_commit, "auto")) { + curr_branch = branch_get(NULL); + upstream = branch_get_upstream(curr_branch, NULL); + if (upstream) { + if (get_sha1(upstream, sha1)) + die(_("Failed to resolve '%s' as a valid ref."), upstream); + base = lookup_commit_or_die(sha1, "upstream base"); + oidcpy(>base_commit, >object.oid); + } else { + commit_patch_id(prerequisite_head, , sha1); + oidcpy(>parent_commit, _head->object.oid); + hashcpy(bases->parent_patch_id.hash, sha1); + return; + } + } else { + base = lookup_commit_reference_by_name(base_commit); + if (!base) + die(_("Unknown commit %s"), base_commit); + oidcpy(>base_commit, >object.oid); + } if (base == prerequisite_head) return; @@ -1223,10 +1248,6 @@ static void prepare_bases(struct base_tree_info *bases, prerequisite_head->object.flags |= 0; add_pending_object(, _head->object, "prerequisite-head"); - diff_setup(); - DIFF_OPT_SET(, RECURSIVE); - diff_setup_done(); - if (prepare_revision_walk()) die(_("revision walk setup failed")); /* @@ -1249,22 +1270,33 @@ static void print_bases(struct base_tree_info *bases) int i; /* Only do this once, either for the cover or for the first one */ - if (is_null_oid(>base_commit)) + if (is_null_oid(>base_commit) && is_null_oid(>parent_commit)) return; - printf("** base-commit-info **\n"); + if (!is_null_oid(>base_commit)) { + printf("** base-commit-info **\n"); + + /* Show the base commit */ + printf("base-commit: %s\n", oid_to_hex(>base_commit)); - /* Show the base commit */ - printf("base-commit: %s\n", oid_to_hex(>base_commit)); + /* Show the prerequisite patches */ + for (i = 0; i < bases->nr_patch_id; i++) + printf("prerequisite-patch-id: %s\n", oid_to_hex(>patch_id[i])); - /* Show the prerequisite patches */ - for (i = 0; i < bases->nr_patch_id; i++) - printf("prerequisite-patch-id: %s\n", oid_to_hex(>patch_id[i])); + free(bases->patch_id); + bases->nr_patch_id = 0; + bases->alloc_patch_id = 0; + oidclr(>base_commit); + } else if (!is_null_oid(>parent_commit)) { + printf("** parent-commit-info **\n"); - free(bases->patch_id); - bases->nr_patch_id = 0; - bases->alloc_patch_id = 0; - oidclr(>base_commit); + /* Show the parent commit */ + printf("parent-commit: %s\n", oid_to_hex(>parent_commit)); + /* Show the parent patch id */ + printf("parent-patch-id: %s\n", oid_to_hex(>parent_patch_id)); + + oidclr(>parent_commit); + } } int cmd_format_patch(int argc, const char **argv, const char *prefix) -- 2.8.0.rc4.4.ga41a987 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/4] patch-ids: make commit_patch_id() a public helper function
Make commit_patch_id() available to other builtins. Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- patch-ids.c | 2 +- patch-ids.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/patch-ids.c b/patch-ids.c index b7b3e5a..a4d0016 100644 --- a/patch-ids.c +++ b/patch-ids.c @@ -4,7 +4,7 @@ #include "sha1-lookup.h" #include "patch-ids.h" -static int commit_patch_id(struct commit *commit, struct diff_options *options, +int commit_patch_id(struct commit *commit, struct diff_options *options, unsigned char *sha1) { if (commit->parents) diff --git a/patch-ids.h b/patch-ids.h index c8c7ca1..eeb56b3 100644 --- a/patch-ids.h +++ b/patch-ids.h @@ -13,6 +13,8 @@ struct patch_ids { struct patch_id_bucket *patches; }; +int commit_patch_id(struct commit *commit, struct diff_options *options, + unsigned char *sha1); int init_patch_ids(struct patch_ids *); int free_patch_ids(struct patch_ids *); struct patch_id *add_commit_patch_id(struct commit *, struct patch_ids *); -- 2.8.0.rc4.4.ga41a987 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 4/4] format-patch: introduce format.base configuration
We can set format.base=auto to record the base commit info automatically, it is equivalent to set --base=auto in cmdline. The format.base has lower priority than command line option, so if user set format.base=auto and pass the command line option in the meantime, base_commit will be the one passed to command line option. Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- Documentation/git-format-patch.txt | 5 + builtin/log.c | 21 ++--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index a5f145e..7c7a61a 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -279,6 +279,11 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`. "Z..C" instead of "-3 C" to specify the range), and the identifiers for P, X, Y, Z are appended at the end of the _first_ message (either the cover letter or the first patch in the series). + If 'format.base=auto' is set in configuration file, it is equivalent + to set '--base=auto' in cmdline, it will track the base commit + automatically, the base commit will be the tip commit of upstream + branch, if upstream branch cannot be determined, it will just record + the parent's commit id and patch id. --root:: Treat the revision argument as a , even if it diff --git a/builtin/log.c b/builtin/log.c index e8a3964..fc468ce 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -699,6 +699,7 @@ static int do_signoff; static const char *signature = git_version_string; static const char *signature_file; static int config_cover_letter; +static int config_base_commit; static const char *config_output_directory; enum { @@ -780,6 +781,12 @@ static int git_format_config(const char *var, const char *value, void *cb) } if (!strcmp(var, "format.outputdirectory")) return git_config_string(_output_directory, var, value); + if (!strcmp(var, "format.base")){ + if (value && !strcasecmp(value, "auto")) { + config_base_commit = 1; + return 0; + } + } return git_log_config(var, value, cb); } @@ -1213,7 +1220,12 @@ static void prepare_bases(struct base_tree_info *bases, DIFF_OPT_SET(, RECURSIVE); diff_setup_done(); - if (!strcmp(base_commit, "auto")) { + if (base_commit && strcmp(base_commit, "auto")) { + base = lookup_commit_reference_by_name(base_commit); + if (!base) + die(_("Unknown commit %s"), base_commit); + oidcpy(>base_commit, >object.oid); + } else if ((base_commit && !strcmp(base_commit, "auto")) || config_base_commit) { curr_branch = branch_get(NULL); upstream = branch_get_upstream(curr_branch, NULL); if (upstream) { @@ -1227,11 +1239,6 @@ static void prepare_bases(struct base_tree_info *bases, hashcpy(bases->parent_patch_id.hash, sha1); return; } - } else { - base = lookup_commit_reference_by_name(base_commit); - if (!base) - die(_("Unknown commit %s"), base_commit); - oidcpy(>base_commit, >object.oid); } if (base == prerequisite_head) @@ -1626,7 +1633,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) signature = strbuf_detach(, NULL); } - if (base_commit) { + if (base_commit || config_base_commit) { struct commit *prerequisite_head = NULL; if (list[nr - 1]->parents) prerequisite_head = list[nr - 1]->parents->item; -- 2.8.0.rc4.4.ga41a987 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 0/4] Add an option to git-format-patch to record base tree info
This is a re-roll of http://article.gmane.org/gmane.comp.version-control.git/286873 It is almost a rewrite of v1, Changes include: - Make commit_patch_id() a publib helper function, so it can be available to other modules. - The new option "--base" will not only record the base commit id(a public well-known commit), but also the prerequisite patches's patch ids, then the 0day test robot could get these info, thus to checkout the well-known base tree-ish, apply the prerequisite patches and then the patches being send can be applied to correct tree to be evaluated. (0day catches every patch series to LKML and maintains a patch-id => commit-id database for in-flight patches.) - For developers' convenience, we propose a new format.base configuration to track the base commit automatically, if current branch the developer work on has its remote-tracking branch, the base commit would be the tip commit of the remote branch, if current branch is not tracked with any remote branch(eg. checkout by a local branch or a commit), thus its upstream could not be obtained, it will just record the parent commit-id of the patch series, as well as patch-id for reference. so here is the text UI: 1) for the cases that exact base commit could be obtained(eithor from manual input --base= or from upstream if base=auto is set) ** base-commit-info ** base-commit: ab5d01a29eb7380ceab070f0807c2939849c44bc prerequisite-patch-id: 61400f965fdc0c2fbe8ad9cb5316c3efe6e05c14 prerequisite-patch-id: 063a398ef398647d8d839e6f9090d38ea9e0551c 2) for cases that exact base commit is failed to obtained ** parent-commit-info ** parent-commit: ab5d01a29eb7380ceab070f0807c2939849c44bc parent-patch-id: caf2dae24db5b4c49a6c4134dd6d9908e898424b Thanks for fengguang and junio's suggestions and prototype of implementation. Thanks, Xiaolong. Xiaolong Ye (4): patch-ids: make commit_patch_id() a public helper function format-patch: add '--base' option to record base tree info format-patch: introduce --base=auto option format-patch: introduce format.base configuration Documentation/git-format-patch.txt | 20 ++ builtin/log.c | 137 + patch-ids.c| 2 +- patch-ids.h| 2 + 4 files changed, 160 insertions(+), 1 deletion(-) -- 2.8.0.rc4.4.ga41a987 ** base-commit-info ** base-commit: 808ecd4cca75acac5e4868f15d3e647fc73698d3 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC/PATCH 1/1] format-patch: add an option to record base tree info
It would be helpful for maintainers or reviewers to know the base tree info of the patches created by git format-patch. Teach git format-patch a --base-tree-info option to record these info. Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- builtin/log.c | 18 ++ diff.c| 4 diff.h| 3 ++- revision.h| 1 + 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/builtin/log.c b/builtin/log.c index 0d738d6..bec7aee 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1189,6 +1189,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) { struct commit *commit; struct commit **list = NULL; + struct commit_list *parents = NULL; struct rev_info rev; struct setup_revision_opt s_r_opt; int nr = 0, total, i; @@ -1200,6 +1201,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int boundary_count = 0; int no_binary_diff = 0; int zero_commit = 0; + int base_tree_info = 0; struct commit *origin = NULL; const char *in_reply_to = NULL; struct patch_ids ids; @@ -1242,6 +1244,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) N_("don't output binary diffs")), OPT_BOOL(0, "zero-commit", _commit, N_("output all-zero hash in From header")), + OPT_BOOL(0, "base-tree-info", _tree_info, +N_("Add base tree info")), OPT_BOOL(0, "ignore-if-in-upstream", _if_in_upstream, N_("don't include a patch matching a commit upstream")), { OPTION_SET_INT, 'p', "no-stat", _patch_format, NULL, @@ -1387,6 +1391,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.diffopt.output_format |= DIFF_FORMAT_PATCH; rev.zero_commit = zero_commit; + rev.base_tree_info = base_tree_info; if (!DIFF_OPT_TST(, TEXT) && !no_binary_diff) DIFF_OPT_SET(, BINARY); @@ -1484,6 +1489,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) /* nothing to do */ return 0; total = nr; + parents = get_saved_parents(, list[nr-1]); + if (rev.base_tree_info && parents) { + struct commit *base_commit = parents->item; + sha1_to_hex_r(rev.diffopt.base_commit_id, base_commit->object.oid.hash); + } + if (!keep_subject && auto_number && total > 1) numbered = 1; if (numbered) @@ -1516,6 +1527,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.numbered_files = just_numbers; rev.patch_suffix = fmt_patch_suffix; if (cover_letter) { + if (rev.base_tree_info) + DIFF_OPT_SET(, BASE_TREE_INFO); if (thread) gen_message_id(, "cover"); make_cover_letter(, use_stdout, @@ -1528,6 +1541,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int shown; commit = list[nr]; rev.nr = total - nr + (start_number - 1); + if (!cover_letter && rev.nr == 1 && rev.base_tree_info) + DIFF_OPT_SET(, BASE_TREE_INFO); + else + DIFF_OPT_CLR(, BASE_TREE_INFO); + /* Make the second and subsequent mails replies to the first */ if (thread) { /* Have we already had a message ID? */ diff --git a/diff.c b/diff.c index 2136b69..a23d5a5 100644 --- a/diff.c +++ b/diff.c @@ -4650,6 +4650,7 @@ void diff_flush(struct diff_options *options) separator++; } + if (output_format & DIFF_FORMAT_NO_OUTPUT && DIFF_OPT_TST(options, EXIT_WITH_STATUS) && DIFF_OPT_TST(options, DIFF_FROM_CONTENTS)) { @@ -4673,6 +4674,9 @@ void diff_flush(struct diff_options *options) } } + if (DIFF_OPT_TST(options, BASE_TREE_INFO)) + fprintf(options->file, "\nbase commit: %s\n", options->base_commit_id); + if (output_format & DIFF_FORMAT_PATCH) { if (separator) { fprintf(options->file, "%s%c", diff --git a/diff.h b/diff.h index 70b2d70..0e62f63 100644 --- a/diff.h +++ b/diff.h @@ -69,7 +69,7 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data) #define DIFF_OPT_FIND_COPIES_HARDER (1 << 6) #define DIFF_OPT_FOLLOW_RENAMES (1 << 7) #define DIFF_OPT_RENAME_EMPTY(1 << 8) -/* (1 << 9) unused */ +
[RFC/PATCH 0/1] Add an option to git-format-patch to record base tree info
Hi, I am a developer of 0-Day kernel test infrastructure(It is a service and test framework for automated regression-testing that intercepts linux kernel development at its early stages [1]), and as proposed by developers in ksummit-discuss, we have implemented a framework to test all patches sent to LKML, it could help us to find out potential build/boot/regression errors as early as possible. In order to test LKML patches on their correct trees, we need to know the corresponding base tree info, such as git url, branch, base commit id, etc, currently we did some guess works and it may apply patches to the wrong base trees, leading to undesirable false positives. The only clean solution is for the developers to include these base tree info in their first [PATCH] email, so we propose to add an option "--base-tree-info" to git-format-patch to record these info in cover letter or the first patch (put it between the "---" marker line and the actual diff), we believe it would also be useful for maintainers who use git to manage their projects. The initial implementation only record the base(parent) commit SHA1 of the first patch. Here is the example: 1) with cover letter you could see the commit id at the bottom of the message. 2) without cover letter Signed-off-by: Xiaolong Ye <xiaolong...@intel.com> --- builtin/log.c | 17 + diff.c| 4 diff.h| 3 ++- revision.h| 1 + 4 files changed, 24 insertions(+), 1 deletion(-) base commit: 0233b800c838ddda41db318ee396320b3c21a560 diff --git a/builtin/log.c b/builtin/log.c index 0d738d6..49fe8c2 100644 --- a/builtin/log.c +++ b/builtin/log.c What do you think? Any review comments about this patch or any suggestions to us would be greatly appreciated. [1] https://01.org/lkp/documentation/0-day-test-service Thanks, Xiaolong. Xiaolong Ye (1): format-patch: add an option to record base tree info builtin/log.c | 18 ++ diff.c| 4 diff.h| 3 ++- revision.h| 1 + 4 files changed, 25 insertions(+), 1 deletion(-) base commit: 0233b800c838ddda41db318ee396320b3c21a560 -- 2.7.1.340.gf1cebb4 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html