Re: Splitting a rev list into 2 sets

2013-06-25 Thread Francis Moreau
Hello Thomas,

On Mon, Jun 24, 2013 at 11:59 AM, Thomas Rast tr...@inf.ethz.ch wrote:
 Francis Moreau francis.m...@gmail.com writes:

 On Thu, Jun 20, 2013 at 3:20 PM, Thomas Rast tr...@inf.ethz.ch wrote:
   positive=$(git rev-parse $@ | grep -v '^\^')
   negative=$(git rev-parse $@ | grep '^\^')
   boundary=$(git rev-list --boundary $positive ^master | sed -n 's/^-//p')
   # the intersection is
   git rev-list $boundary $negative

 I think there's a minor issue here, when boundary is empty. Please
 correct me if I'm wrong but I think it can only happen if positive is
 simply master or a subset of master. In that case I think the solution
 is just make boundary equal to positive:

  # the intersection is
  git rev-list ${boundary:-$positive} $negative

 Now I'm going to see if that solution is faster than the initial one.

 Jan jast Krüger pointed out on #git that

   git log $(git merge-base --all A B)

 is exactly the set of commits reachable from both A and B; so there's
 your intersection operator :-)

nice :)


 So it would seem that a much simpler approach is

   git rev-list $(git merge-base --all master $positive) --not $negative

 avoiding the boundary handling and special-case.  It relies on the
 (weird?) property that $(git merge-base --all A B1 B2 ...) shows the
 merge bases of A with a hypothetical merge of B1, B2, ..., which is just
 what you need here.

Thank you Thomas, that's exactly what I was asking for :)

--
Francis
--
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: Splitting a rev list into 2 sets

2013-06-24 Thread Thomas Rast
Francis Moreau francis.m...@gmail.com writes:

 On Thu, Jun 20, 2013 at 3:20 PM, Thomas Rast tr...@inf.ethz.ch wrote:
   positive=$(git rev-parse $@ | grep -v '^\^')
   negative=$(git rev-parse $@ | grep '^\^')
   boundary=$(git rev-list --boundary $positive ^master | sed -n 's/^-//p')
   # the intersection is
   git rev-list $boundary $negative

 I think there's a minor issue here, when boundary is empty. Please
 correct me if I'm wrong but I think it can only happen if positive is
 simply master or a subset of master. In that case I think the solution
 is just make boundary equal to positive:

  # the intersection is
  git rev-list ${boundary:-$positive} $negative

 Now I'm going to see if that solution is faster than the initial one.

Jan jast Krüger pointed out on #git that

  git log $(git merge-base --all A B)

is exactly the set of commits reachable from both A and B; so there's
your intersection operator :-)

So it would seem that a much simpler approach is

  git rev-list $(git merge-base --all master $positive) --not $negative

avoiding the boundary handling and special-case.  It relies on the
(weird?) property that $(git merge-base --all A B1 B2 ...) shows the
merge bases of A with a hypothetical merge of B1, B2, ..., which is just
what you need here.

-- 
Thomas Rast
trast@{inf,student}.ethz.ch
--
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: Splitting a rev list into 2 sets

2013-06-21 Thread Francis Moreau
Hi,

On Thu, Jun 20, 2013 at 3:47 PM, Ramkumar Ramachandra
artag...@gmail.com wrote:
 Francis Moreau wrote:
 Basically I have an initial set (or can be several different sets)
 expressed as a revision specification described by git-rev-list man
 page. I just want to find the common set of commit which are part of
 the initial sets *and* is reachable by master.

 That's just a generic list intersection between

   [a, b, c] and [d, e, f]

 no?  [a, b, c] is a list you built up somehow, and [d, e, f] comes
 from $(git rev-list master), right?

yes.


 You could go about determining the revision walk boundaries and
 combine them to set up a revision walk to splice the master line, but
 what is the point of that?

Well, that seems to me a more elegant solution and I was curious about
doing this with git-rev-list only if possible.

  You'll only be painting yourself into a
 design-corner (you won't be able to do other kinds of filtering), and
 going around your head to touch your nose.

I think what Thomas proposed is fine.

  You precisely want list
 intersection: so write an efficient list intersection in the language
 of your choice.  Why is it a poor man's solution?

Sorry my wording was poor. I just meant that it was the obvious
solution that I don't find nice. But your implementation was good.

  If anything, your
 convoluted rev-list solution will probably be more complicated,
 slower, and bug-ridden.

Slower ? why do you think Thomas' solution is slower than the obvious one ?

Thanks
--
Francis
--
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: Splitting a rev list into 2 sets

2013-06-21 Thread Ramkumar Ramachandra
Francis Moreau wrote:
 Slower ? why do you think Thomas' solution is slower than the obvious one ?

There's really only one way to find out: try it and see. YMMV
depending on your data.
--
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


Splitting a rev list into 2 sets

2013-06-20 Thread Francis Moreau
Hello,

I'd like to write a script that would parse commits in one of my repo.
Ideally this script should accept any revision ranges that
git-rev-list would accept.

This script should consider commits in master differently than the
ones in others branches.

To get the commit set which can't be reached by master (ie commits
which are specific to branches other than master) I would do:

  # $@ is the range spec passed to the script
  git rev-list $@ ^master | check_other_commit

But I don't know if it's possible to use a different git-rev-list
command to get the rest of the commits, ie the ones that are reachable
by the specified range and master.

One way to do that is to record the first commit set got by the first
rev-list command and check that the ones returned by git rev-list $@
are not in the record.

But I'm wondering if someone can see another solution more elegant ?

Thanks
--
Francis
--
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: Splitting a rev list into 2 sets

2013-06-20 Thread Phil Hord
On Thu, Jun 20, 2013 at 6:14 AM, Francis Moreau francis.m...@gmail.com wrote:
 I'd like to write a script that would parse commits in one of my repo.
 Ideally this script should accept any revision ranges that
 git-rev-list would accept.

 This script should consider commits in master differently than the
 ones in others branches.

 To get the commit set which can't be reached by master (ie commits
 which are specific to branches other than master) I would do:

   # $@ is the range spec passed to the script
   git rev-list $@ ^master | check_other_commit

 But I don't know if it's possible to use a different git-rev-list
 command to get the rest of the commits, ie the ones that are reachable
 by the specified range and master.

 One way to do that is to record the first commit set got by the first
 rev-list command and check that the ones returned by git rev-list $@
 are not in the record.

 But I'm wondering if someone can see another solution more elegant ?

I do not know if I would call this elegant, but I think this
codification of your One way to do that is at least small and mostly
readable:

   git rev-list $@ |grep -v -f (git rev-list $@ ^master)

Phil
--
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: Splitting a rev list into 2 sets

2013-06-20 Thread Francis Moreau
On Thu, Jun 20, 2013 at 1:26 PM, Ramkumar Ramachandra
artag...@gmail.com wrote:
 Francis Moreau wrote:
 To get the commit set which can't be reached by master (ie commits
 which are specific to branches other than master) I would do:

   # $@ is the range spec passed to the script
   git rev-list $@ ^master | check_other_commit

 But I don't know if it's possible to use a different git-rev-list
 command to get the rest of the commits, ie the ones that are reachable
 by the specified range and master.

 One way to do that is to record the first commit set got by the first
 rev-list command and check that the ones returned by git rev-list $@
 are not in the record.

 I don't fully understand your query, because almost anything is
 possible with rev-list:

   $ git rev-list foo..bar master # reachable from master, bar, not foo

 What I _suspect_ you're asking is for help when you can't construct
 this foo..bar master programmatically (or when you cannot express
 your criterion as arguments to rev-list).  You want an initial commit
 set, and filter it at various points in your program using various
 criteria, right?

Yes, I would like to be sure that I haven't missed some magic syntax
for rev-list before going further in my poor man solution :)

Basically I have an initial set (or can be several different sets)
expressed as a revision specification described by git-rev-list man
page. I just want to find the common set of commit which are part of
the initial sets *and* is reachable by master.

I would write it:

 git rev-list $@ --and master

 In that case, I'd suggest something like this:

Thanks for the details example.

--
Francis
--
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: Splitting a rev list into 2 sets

2013-06-20 Thread Francis Moreau
Hi,

On Thu, Jun 20, 2013 at 3:04 PM, Phil Hord phil.h...@gmail.com wrote:
 On Thu, Jun 20, 2013 at 6:14 AM, Francis Moreau francis.m...@gmail.com 
 wrote:
 I'd like to write a script that would parse commits in one of my repo.
 Ideally this script should accept any revision ranges that
 git-rev-list would accept.

 This script should consider commits in master differently than the
 ones in others branches.

 To get the commit set which can't be reached by master (ie commits
 which are specific to branches other than master) I would do:

   # $@ is the range spec passed to the script
   git rev-list $@ ^master | check_other_commit

 But I don't know if it's possible to use a different git-rev-list
 command to get the rest of the commits, ie the ones that are reachable
 by the specified range and master.

 One way to do that is to record the first commit set got by the first
 rev-list command and check that the ones returned by git rev-list $@
 are not in the record.

 But I'm wondering if someone can see another solution more elegant ?

 I do not know if I would call this elegant, but I think this
 codification of your One way to do that is at least small and mostly
 readable:

git rev-list $@ |grep -v -f (git rev-list $@ ^master)


Yes, thanks.

But I wanted to be sure that git-rev-list can't display the
intersection of several sets before going forward.

--
Francis
--
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: Splitting a rev list into 2 sets

2013-06-20 Thread Thomas Rast
Francis Moreau francis.m...@gmail.com writes:

 Hello,

 I'd like to write a script that would parse commits in one of my repo.
 Ideally this script should accept any revision ranges that
 git-rev-list would accept.

 This script should consider commits in master differently than the
 ones in others branches.

 To get the commit set which can't be reached by master (ie commits
 which are specific to branches other than master) I would do:

   # $@ is the range spec passed to the script
   git rev-list $@ ^master | check_other_commit

 But I don't know if it's possible to use a different git-rev-list
 command to get the rest of the commits, ie the ones that are reachable
 by the specified range and master.

 One way to do that is to record the first commit set got by the first
 rev-list command and check that the ones returned by git rev-list $@
 are not in the record.

 But I'm wondering if someone can see another solution more elegant ?

I think there's a cute way.  Suppose your arguments are of the form

  p1 p2 ... --not n1 n2 ...

that is each pX is positive, and each nX is negative.  Then as you
observed, building the difference with master is easy: just add it to
the negative args.

Intersecting with master is harder, because you don't know what parts of
it (if any) are in the range.  But the --boundary option can help: these
are the commits where the positive and negative ranges first met, and
prevented the walk from continuing.

So the part of master reachable from p1, p2, etc. is exactly the set of
boundary commits of 'p1 p2 ... ^master'.  And on top of that, excluding
the parts reachable from the n's is easy.  So you can do:

  positive=$(git rev-parse $@ | grep -v '^\^')
  negative=$(git rev-parse $@ | grep '^\^')
  boundary=$(git rev-list --boundary $positive ^master | sed -n 's/^-//p')
  # the intersection is
  git rev-list $boundary $negative

I haven't tested it much, however.

-- 
Thomas Rast
trast@{inf,student}.ethz.ch
--
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: Splitting a rev list into 2 sets

2013-06-20 Thread Ramkumar Ramachandra
Francis Moreau wrote:
 Basically I have an initial set (or can be several different sets)
 expressed as a revision specification described by git-rev-list man
 page. I just want to find the common set of commit which are part of
 the initial sets *and* is reachable by master.

That's just a generic list intersection between

  [a, b, c] and [d, e, f]

no?  [a, b, c] is a list you built up somehow, and [d, e, f] comes
from $(git rev-list master), right?

You could go about determining the revision walk boundaries and
combine them to set up a revision walk to splice the master line, but
what is the point of that?  You'll only be painting yourself into a
design-corner (you won't be able to do other kinds of filtering), and
going around your head to touch your nose.  You precisely want list
intersection: so write an efficient list intersection in the language
of your choice.  Why is it a poor man's solution?  If anything, your
convoluted rev-list solution will probably be more complicated,
slower, and bug-ridden.
--
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: Splitting a rev list into 2 sets

2013-06-20 Thread Francis Moreau
Hi,

On Thu, Jun 20, 2013 at 3:20 PM, Thomas Rast tr...@inf.ethz.ch wrote:
 Francis Moreau francis.m...@gmail.com writes:

 But I'm wondering if someone can see another solution more elegant ?

 I think there's a cute way.  Suppose your arguments are of the form

Really nice !


   p1 p2 ... --not n1 n2 ...

 that is each pX is positive, and each nX is negative.  Then as you
 observed, building the difference with master is easy: just add it to
 the negative args.

I didn't know that git-rev-parse could be used to transform any range
specification into that form (p1 p2 .. -not n1 n2..)


 Intersecting with master is harder, because you don't know what parts of
 it (if any) are in the range.  But the --boundary option can help: these
 are the commits where the positive and negative ranges first met, and
 prevented the walk from continuing.

 So the part of master reachable from p1, p2, etc. is exactly the set of
 boundary commits of 'p1 p2 ... ^master'.  And on top of that, excluding
 the parts reachable from the n's is easy.  So you can do:

Really clever.


   positive=$(git rev-parse $@ | grep -v '^\^')
   negative=$(git rev-parse $@ | grep '^\^')
   boundary=$(git rev-list --boundary $positive ^master | sed -n 's/^-//p')
   # the intersection is
   git rev-list $boundary $negative

I think there's a minor issue here, when boundary is empty. Please
correct me if I'm wrong but I think it can only happen if positive is
simply master or a subset of master. In that case I think the solution
is just make boundary equal to positive:

 # the intersection is
 git rev-list ${boundary:-$positive} $negative

Now I'm going to see if that solution is faster than the initial one.

Great Thanks
--
Francis
--
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