[PATCH] format-patch: clear UNINTERESTING flag before prepare_bases

2018-06-04 Thread Xiaolong Ye
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

2016-04-26 Thread Xiaolong Ye
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

2016-04-26 Thread Xiaolong Ye
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

2016-04-26 Thread Xiaolong Ye
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

2016-04-26 Thread Xiaolong Ye
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

2016-04-26 Thread Xiaolong Ye
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

2016-04-21 Thread Xiaolong Ye
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

2016-04-21 Thread Xiaolong Ye
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

2016-04-21 Thread Xiaolong Ye
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

2016-04-21 Thread Xiaolong Ye
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

2016-04-21 Thread Xiaolong Ye
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

2016-04-10 Thread Xiaolong Ye
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

2016-04-10 Thread Xiaolong Ye
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

2016-04-10 Thread Xiaolong Ye
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

2016-04-10 Thread Xiaolong Ye
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

2016-04-10 Thread Xiaolong Ye
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

2016-03-30 Thread Xiaolong Ye
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

2016-03-30 Thread Xiaolong Ye
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

2016-03-30 Thread Xiaolong Ye
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

2016-03-30 Thread Xiaolong Ye
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

2016-03-30 Thread Xiaolong Ye
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

2016-03-23 Thread Xiaolong Ye
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

2016-03-23 Thread Xiaolong Ye
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

2016-03-23 Thread Xiaolong Ye
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

2016-03-23 Thread Xiaolong Ye
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

2016-03-23 Thread Xiaolong Ye
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

2016-02-21 Thread Xiaolong Ye
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

2016-02-21 Thread Xiaolong Ye
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