Re: [BUG] Segfault with rev-list --bisect

2015-03-04 Thread Junio C Hamano
Troy Moure troy.mo...@gmail.com writes:

 git rev-list --bisect --first-parent --parents HEAD --not HEAD~1

Hmm, as rev-list --bisect is not end-user facing command (it is
purely an implementation detail for git bisect) and we never call
it with --first-parent, I am not sure if it is worth labelling it as
a BUG.  Surely, the command can refuse to operate when it sees both
options given, but that would be a fairly low priority.

Of course, if you are planning to do git bisect --first-parent, it
is one of the things that needs to be addressed, together with
counting the rounds and bisecting the linear set of commits on the
first-parent chain correctly.

--
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


Re: [BUG] Segfault with rev-list --bisect

2015-03-04 Thread Troy Moure
On Wed, Mar 4, 2015 at 6:44 PM, Junio C Hamano gits...@pobox.com wrote:
 Troy Moure troy.mo...@gmail.com writes:

 git rev-list --bisect --first-parent --parents HEAD --not HEAD~1

 Hmm, as rev-list --bisect is not end-user facing command (it is
 purely an implementation detail for git bisect) and we never call
 it with --first-parent, I am not sure if it is worth labelling it as
 a BUG.  Surely, the command can refuse to operate when it sees both
 options given, but that would be a fairly low priority.

Hrm, ok. I didn't realize --bisect is only intended to be used by git-bisect
(although I suppose the fact that it treats ref/bisect/* specially should have
been a hint). If uses of --bisect other than by git-bisect are considered
unsupported, IMO it would be good to say that in the documentation - right now
it looks like just another rev-list parameter. (I realize rev-list itself is
plumbing, but that's not the same as not user facing, is it?)

If you're curious, I ran into this because I am working on a script that can be
run repeatedly to process commits, and uses git notes to mark commits that have
been processed.  Parents are always processed before their children, so if a
commit has a note, it means all its ancestors also have notes. I want to
quickly find the set of commits that have not yet been processed. I am thinking
of finding the boundary commits (commits that have a note and at least one
child that does not) by using a binary search to find the boundary commit on
the first-parent chain, and then recursively doing the same thing starting from
each non-first parent of each merge commit between the boundary commit and the
starting point.

Upon further thought, it's probably better to just read the whole first-parent
chain and do the binary search in the script, since git rev-list --bisect
would have generate the chain each time it's called. But I'd already run into
the segfault, so I thought I'd report it.

Of course, I'd appreciate any thoughts or comments on the problem I'm trying to
solve as well.

Thanks,
Troy
--
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


Re: [BUG] Segfault with rev-list --bisect

2015-03-03 Thread Jeff King
On Tue, Mar 03, 2015 at 09:19:14AM -0500, Troy Moure wrote:

 I've found a case where git rev-list --bisect segfaults reproducibly
 (git version is 2.3.1). This is the commit topology (A2 is the first
 parent of M):
 
 I - A1 - A2
   \\
 - B1 -- M  (HEAD)

Thanks for finding a simple history which shows the problem. I recreated
this with:

git init repo  cd repo 
echo I I  git add I  git commit -m I 
echo A1 A  git add A  git commit -m A1 
echo A2 A  git add A  git commit -m A2 
git checkout -b side HEAD~2 
echo B1 B  git add B  git commit -m B1 
git checkout master 
GIT_EDITOR=: git merge side

and was able to reproduce the segfault with:

git rev-list --bisect --first-parent HEAD --not HEAD~1

(it drops --parents from your command, which is not relevant to the
segfault). The segfault itself happens because we try to access the
weight() of B1, even though we never called weight_set() on it.

And that, I think, is related to --first-parent. We do not set a weight
because B1 is not an interesting commit to us (it is accessible only as
a second parent). I am not too familiar with the bisect code, but it
looks like it is not really ready to handle --first-parent. There are
several spots where it enumerates the parent list, which is going to
examine parents other than the first.

Below is a fairly hacky patch to respect --first-parent through the
bisection code. Like I said, I'm not very familiar with this code, so I
basically just blindly limited any traversal of commit-parents. It does
solve this particular segfault, but I have no clue if it is fixing other
bugs introducing them. :) E.g., it's changing count_distance(), so
perhaps our bisection counts were all off with --first-parent, even when
it didn't segfault?

diff --git a/bisect.c b/bisect.c
index 8c6d843..c51f37a 100644
--- a/bisect.c
+++ b/bisect.c
@@ -31,7 +31,7 @@ static const char *argv_update_ref[] = {update-ref, 
--no-deref, BISECT_HEAD
  * We care just barely enough to avoid recursing for
  * non-merge entries.
  */
-static int count_distance(struct commit_list *entry)
+static int count_distance(struct commit_list *entry, int max_parents)
 {
int nr = 0;
 
@@ -47,9 +47,10 @@ static int count_distance(struct commit_list *entry)
p = commit-parents;
entry = p;
if (p) {
+   int n = max_parents - 1;
p = p-next;
-   while (p) {
-   nr += count_distance(p);
+   while (p  n--  0) {
+   nr += count_distance(p, max_parents);
p = p-next;
}
}
@@ -79,12 +80,12 @@ static inline void weight_set(struct commit_list *elem, int 
weight)
*((int*)(elem-item-util)) = weight;
 }
 
-static int count_interesting_parents(struct commit *commit)
+static int count_interesting_parents(struct commit *commit, int max_parents)
 {
struct commit_list *p;
int count;
 
-   for (count = 0, p = commit-parents; p; p = p-next) {
+   for (count = 0, p = commit-parents; p  max_parents--  0; p = 
p-next) {
if (p-item-object.flags  UNINTERESTING)
continue;
count++;
@@ -117,7 +118,7 @@ static inline int halfway(struct commit_list *p, int nr)
 #define show_list(a,b,c,d) do { ; } while (0)
 #else
 static void show_list(const char *debug, int counted, int nr,
- struct commit_list *list)
+ struct commit_list *list, int max_parents)
 {
struct commit_list *p;
 
@@ -132,6 +133,7 @@ static void show_list(const char *debug, int counted, int 
nr,
char *buf = read_sha1_file(commit-object.sha1, type, size);
const char *subject_start;
int subject_len;
+   int n = max_parents;
 
fprintf(stderr, %c%c%c ,
(flags  TREESAME) ? ' ' : 'T',
@@ -142,7 +144,7 @@ static void show_list(const char *debug, int counted, int 
nr,
else
fprintf(stderr, ---);
fprintf(stderr,  %.*s, 8, sha1_to_hex(commit-object.sha1));
-   for (pp = commit-parents; pp; pp = pp-next)
+   for (pp = commit-parents; pp  n--  0; pp = pp-next)
fprintf(stderr,  %.*s, 8,
sha1_to_hex(pp-item-object.sha1));
 
@@ -245,7 +247,7 @@ static struct commit_list *best_bisection_sorted(struct 
commit_list *list, int n
  */
 static struct commit_list *do_find_bisection(struct commit_list *list,
 int nr, int *weights,
-int find_all)
+int find_all, int max_parents)
 {
int n, counted;
struct commit_list *p;
@@ -257,7 +259,7 @@ static struct 

[BUG] Segfault with rev-list --bisect

2015-03-03 Thread Troy Moure
Hi,

I've found a case where git rev-list --bisect segfaults reproducibly
(git version is 2.3.1). This is the commit topology (A2 is the first
parent of M):

I - A1 - A2
  \\
- B1 -- M  (HEAD)

And this is an example of a command that segfaults:

git rev-list --bisect --first-parent --parents HEAD --not HEAD~1

I tried a couple of variations quickly: It does not segfault if a
non-merge commit is made on top of M (so HEAD is no longer pointing
directly to M). It also does not segfault if 'HEAD~1' is changed to
'HEAD~2'.

Thanks,
Troy
--
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