* Re: setting up tracking on push
From: Jay Soffian @ 2009-03-12 1:16 UTC (permalink / raw)
To: Junio C Hamano; +Cc: John M. Dlugosz, git
In-Reply-To: <7vprgnlf3f.fsf@gitster.siamese.dyndns.org>
On Wed, Mar 11, 2009 at 9:11 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> http://article.gmane.org/gmane.comp.version-control.git/54822/
>
> I do not think the description of remote-tracking in that article is
> correct. We use the word to call remote/origin/<name> that keeps copies
> of what we saw over there when we last observed.
>
> The way to mark local branches to merge with/rebase onto something else
> by default is --track option to "git branch" and "git checkout -b", and
> that is often used to mark them to --track remote-tracking branches but
> they do not have to --track remote-tracking branches. They can --track
> local branches as well.
Yes, I noticed this as I re-read the thread. --track and --no-track
are unfortunately poorly named, but that's ancient history. I've
summarized the thread just before you sent this message. I'll update
my summary to note this point. :-)
j.
^ permalink raw reply
* Re: setting up tracking on push
From: Jay Soffian @ 2009-03-12 1:21 UTC (permalink / raw)
To: John M. Dlugosz; +Cc: git
In-Reply-To: <76718490903111814t1ab90a39h9252d0ccf8af05c4@mail.gmail.com>
On Wed, Mar 11, 2009 at 9:14 PM, Jay Soffian <jaysoffian@gmail.com> wrote:
> - Local branches can be associated with remote tracking branches in
> the repo's config (.git/config). This association is done
> automatically in current git when creating a new local branch based on
> a remote tracking branch (e.g, git checkout -b topic origin/master or
> git branch topic origin/master). (You can use --track and --no-track
> to be explicit about whether or not you want the association to
> happen.)
>
> The association itself is simply an entry in the repo's .git/config. e.g.:
>
> [branch "topic"]
> remote = origin
> merge = refs/heads/master
As Junio points out, a local branch can be associated with another
local branch, not just a remote-tracking branch. In the config, this
looks like:
[branch "topic"]
remote = .
merge = refs/heads/master
So now "topic" is associated with *local* branch master, not
remote-tracking branch master, and this is because "remote = ." means
"this repo right here".
But, when making a new branch based on a local branch via git branch
and git checkout, adding this association in the config is not the
default. You have to explicitly ask for it with --track.
Also, the default of whether or not to add the association can itself
be changed. See the entry for branch.autosetupmerge (and related
branch.autosetuprebase, which I didn't go into) in "git help config".
j.
^ permalink raw reply
* Re: Google Summer of Code 2009: GIT
From: thestar @ 2009-03-12 1:57 UTC (permalink / raw)
To: Junio C Hamano; +Cc: david, Johannes Schindelin, saurabh gupta, git
In-Reply-To: <7veix33f5e.fsf@gitster.siamese.dyndns.org>
<Entire conversation snipped>
Guys, I'm sure you're only using OpenOffice.org documents as an
example to facilitate discussing merge helpers, but I feel the need to
point out that one can already merge OpenOffice documents using
OpenOffice to do so. (And I have done so in the past while reconciling
differences between some spreadsheets).
However, the interface OpenOffice provides for that is awful and very
confusing, but it is there. :)
The document merge provided by Microsoft Office 2003 is vastly
superior imho, however it only provides 'change markers' - and doesn't
help you do the actual merge - one must do a merge to get the change
annotations, and then manually modify a new copy with those updates
you feel are neccessary.
- This is one feature that does not appear to be present in
Microsoft Office 2007, by the way...
^ permalink raw reply
* Re: [RFC/PATCH] git push usability improvements and default change
From: Nanako Shiraishi @ 2009-03-12 3:01 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Finn Arne Gangstad, git
In-Reply-To: <7v7i2v4x2v.fsf@gitster.siamese.dyndns.org>
Quoting Junio C Hamano <gitster@pobox.com>:
> Finn Arne Gangstad <finnag@pvv.org> writes:
>
>> On Mon, Mar 09, 2009 at 05:07:08PM -0700, Junio C Hamano wrote:
>> ...
>>> * What's the point of having --current option, when you can already
>>> say HEAD, i.e. $ git push origin HEAD
>>
>> It does something very different. Maybe --tracking would be a better name.
>> --current does basically this:
>> ...
>> The goal here is to be able to:
>>
>> git checkout -b junios-next origin/next
>> git push --current <=> git push origin junios-next:next
>>
>> git push origin HEAD would do git push origin junios-next:junios-next,
>> which was not the intention.
>
> Ok, now that sort of makes sense, and is very different from people would
> expect from --current, which I think most people would associate with
> HEAD. "tracking" or "track back" would be a better name.
I think this proposal has deeper problems than just that.
There can be two reasons you may want to give the branch a name other than 'next':
1. Because you also have dschos-next that tracks remotes/dscho/next; or
2. Because you also have junios-next2 that also tracks remotes/origin/next.
The first case indicates that the project is using a workflow where each developer has his own publishing repository [1], and it is very unlikely that Finn Arne has push access to either your or Johannes'es public repositories.
The second case of tracking a single branch with more than one is unnecessarily confusing. If you are on junios-next and you push (and we assume that you are Junio and have push access to the remote repository), after such a push you need to update junios-next2 somehow, either by rebasing or by merging. The reason junios-next2 branch needs updating is because it has changes unrelated to what you pushed out from your junios-next branch to the outside world as 'next'.
In such a case, wouldn't it be much easier to understand and manage if you had a single 'next' branch that has changes ready to be shown to the remote 'next', and make other topic branches fork from and track your local 'next' instead?
Your changes based on the public 'next' that everybody else sees need to get first integrated and tested in your local repository before getting pushed out to the remote 'next' branch in any case.
You certainly could switch between junios-next and junios-next2 branches that both track the public 'next' branch, and make sure you will integrate everything you need to send to the public repository no matter what branch you are currently working on. Unless you do so, 'git push' will refuse to accept an update that isn't a fast-forward anyway, so it certainly possible to work with more than one local branches that track a single remote branch.
But in order to do this correctly, you need to be aware what each branch is meant to contain, and for which public branch you are developing your changes on it. I think that way of working leads to the confusion and perceived need for the "--current" option: "I don't know which remote branch the changes I made on the current branch should be pushed to, and --current option remembers it for me, so I don't have to". That new option may be solving "where to push to" part but I'm afraid the option not just leaves "I still need to know for which public branch I am supposed to make changes while on this branch" unsolved, but by making people rely on the option I think it makes the latter problem much worse.
Dedicating your local 'next' for the integration purpose to prepare what you push to your public 'next' is much easier to understand and explain to new people. Once a topic that is meant to be published on your 'next' becomes ready, you merge the branch locally to your own 'next', and you have a chance to review that you didn't accidentally included changes inappropriate for 'next' when you create the merge. You push the result out after you are happy.
And I think the above discussion holds true if the public 'next' isn't your 'next', but a branch shared with others in a central repository.
I don't understand how the new "--current" makes "sort-of" sense. It looks like it is making the command more complex and the only thing it does is to encourage a confused workflow.
[1] Your http://gitster.livejournal.com/30645.html showed different ways to collaborate very nicely. I think this is the third approach in your article.
--
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/
^ permalink raw reply
* Re: [EGIT RFC PATCH(was Re: egit problem with sym linked eclipse project dirs)] Add some support for symlinked projects.
From: Stephen Bannasch @ 2009-03-12 2:57 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: Shawn O. Pearce, git
In-Reply-To: <200903112317.41380.robin.rosenberg.lists@dewire.com>
OK ... I'm a bit confused now because I no longer have Git listed as
a repository type for Team Sharing.
I deleted the existing org.spearce.* eclipse plugins
[eclipse]$ rm -f plugins/org.spearce.*
pulled from git://repo.or.cz/egit.git
created a new branch for this test and applied your patch
[egit.git (linksbranch)]$ git log
commit 2b86cd4e27a9d9158092305271d6fb25ab27846e
Author: Stephen Bannasch <stephen.bannasch@gmail.com>
Date: Wed Mar 11 22:29:26 2009 -0400
check through links for repositories
Robin Rosenberg's patch
see: http://marc.info/?l=git&m=123681033214178&w=2
and: http://code.google.com/p/egit/issues/detail?id=52
commit 341b9c1abadd2ac0ec9ecc7c597990070612e058
Author: Ruth Alkema <ruth@diasoft.nl>
Date: Wed Mar 11 16:42:45 2009 +0100
Better fix for 'negative position' error on large pack files
If position is really big and the window size is fairly small, id can
be negative. Instead of producing a negative position by extending
id to a long, mask out the low bits from the original position value
to compute the window start.
[sp: message by me, as I had already applied v1 of the patch
and pushed it (see immediate parent)]
Signed-off-by: Ruth Alkema <ruth@diasoft.nl>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
...
Opened Eclipse and switched to the egit workspace. Refreshed the egit
projects and exported the org.spearce.* packages as deployable
plugins and fragments to the Eclipse dir.
The new plugins are there:
[eclipse]$ ls plugins/org.spearce.*
plugins/org.spearce.egit.core.test_0.4.0.200903112237.jar
plugins/org.spearce.egit_0.4.0.200903112237.jar
plugins/org.spearce.egit.core_0.4.0.200903112237.jar
plugins/org.spearce.jgit_0.4.0.200903112237.jar
plugins/org.spearce.egit.ui_0.4.0.200903112237.jar
Quit and restarted Eclipse.
When I select a project with an existing git repository and try to
enable team/sharing only CVS and SVN are listed.
^ permalink raw reply
* Re: [PATCH v2] git-clone: Add option --branch to override initial branch
From: Miles Bader @ 2009-03-12 4:18 UTC (permalink / raw)
To: Paolo Ciarrocchi
Cc: Felipe Contreras, git, torarnv, Junio C Hamano,
Johannes Schindelin
In-Reply-To: <4d8e3fd30903110152m1b52de30ge630d6b9f6a4c7fe@mail.gmail.com>
Paolo Ciarrocchi <paolo.ciarrocchi@gmail.com> writes:
> $ git clone -n URL
> $ git checkout -b foo origin/bar
>
> That being said, I see the following command as an improvement over
> the actual GIT UI:
>
> $ git clone git://URI -b bar
Note that in your original advice, foo and bar can be different, and
it's not clear to me what "-b bar" should do...
Personally I frequently use foo == bar (no local master branch), but I
think another common pattern is foo != bar, but foo or bar == "master".
Maybe a syntax similar to push, like "-b LOCAL_BR:REMOTE_BR",
with "-b BR" being shorthand for "-b BR:BR"?
-Miles
--
Happiness, n. An agreeable sensation arising from contemplating the misery of
another.
^ permalink raw reply
* Re: [BUG] - git-read-tree segfaults
From: Junio C Hamano @ 2009-03-12 5:57 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Jiri Olsa, git
In-Reply-To: <alpine.DEB.1.00.0903111300330.10279@pacific.mpi-cbg.de>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> On Wed, 11 Mar 2009, Jiri Olsa wrote:
>
>> On Tue, Mar 10, 2009 at 9:21 PM, Johannes Schindelin
>> <Johannes.Schindelin@gmx.de> wrote:
>>
>> > On Tue, 10 Mar 2009, Jiri Olsa wrote:
>> >
>> >> mb=$($GIT merge-base HEAD yyy)
>> >> $GIT read-tree $mb HEAD yyy
>> >
>> > While I agree that it is a bad thing for Git to segfault, I think this
>> > here is a pilot error. You try to read 3 trees at the same time, but
>> > not perform a merge. IMHO you want to add -m at least.
>>
>> agreed, I've already said I executed it like this by an accident...
>
> Hey, you did the right thing! And you even provided a script to recreate,
> so that it was really easy to see what is happening.
>
>> it was easy to recreate so I shared... I'm not saying it is a show
>> stopper :)
>
> Well, Git should not crash. But read-tree is real low-level, so I am
> torn. OTOH, something like this may be the correct thing to do:
That's a bogus "fix".
"git read-tree" without "-m" is supposed to behave as an overlay of the
given trees. Try it with any git older than 1.5.5 and you should see one
entry for xxx and yyy each from Jiri's example. Somewhere between 1.5.4
and 1.5.5 we seem to have broken it.
Having said that, I do not think "read-tree A B C" to overlay these trees
has never worked reliably. For one thing, I do not think the code never
tried to avoid D/F conflicts in the index, and because of that, you can
end up with a bogus index that looks like this:
$ git ls-files -s
100644 58b2ca10b6b032c114cb934c012c3743e34e0e7a 0 xxx
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 xxx/zzz
100644 363a9e8d3b0b423eab41fd12ebed489004ab3c2e 0 yyy
and trying to write it out as a tree object will produce an even more
bogus result.
I think the attached patch fixes the segfault, and also fixes the
longstanding lack of D/F conflict detection, but it needs a bit of
commentary.
The first hunk fixes the D/F conflict issue. After reading three trees
that has (xxx), (xxx, yyy) and (xxx/zzz, yyy) in this order, the resulting
index should look like this with this patch, instead of the broken index
depicted above:
$ git ls-files -s
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 xxx/zzz
100644 363a9e8d3b0b423eab41fd12ebed489004ab3c2e 0 yyy
I suspect that the reason add_entry() passed SKIP_DFCHECK was to work
around an old bug in add_index_entry() that considered it a D/F conflict
if you have a file D at stage N and a file D/F at stage M when N and M are
different. I think such a bug has been fixed long time ago, and there is
no reason for such a workaround. Besides, OK_TO_REPLACE only makes sense
when you do check D/F conflict ("replace" in the name of the flag means
"If you want to add 'xxx/zzz' when the index has 'xxx', it is Ok to drop
the existing 'xxx' in order to add your 'xxx/zzz''); it makes no sense to
give it if you are giving SKIP_DFCHECK at the same time.
The second hunk removes a noop increment of n with o->merge (at this point
we know o->merge is zero) and then makes sure we only send an existing
entry taken from the tree to add_entry().
A NULL src[i] entry is obviously a missing entry from i-th tree, and an
entry that is o->df_conflict_entry is just a stand-in phantom entry the
unpack machinery uses when i-th tree has "xxx/zzz" (hence it cannot have
"xxx") and the unpacker is looking at path "xxx". In either case, i-th
tree does not have an entry "xxx" and we should skip add_entry() for
such a src[i].
unpack-trees.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/unpack-trees.c b/unpack-trees.c
index e547282..5820ce4 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -49,7 +49,7 @@ static void add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
memcpy(new, ce, size);
new->next = NULL;
new->ce_flags = (new->ce_flags & ~clear) | set;
- add_index_entry(&o->result, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE|ADD_CACHE_SKIP_DFCHECK);
+ add_index_entry(&o->result, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
}
/* Unlink the last component and attempt to remove leading
@@ -286,9 +286,9 @@ static int unpack_nondirectories(int n, unsigned long mask,
if (o->merge)
return call_unpack_fn(src, o);
- n += o->merge;
for (i = 0; i < n; i++)
- add_entry(o, src[i], 0, 0);
+ if (src[i] && src[i] != o->df_conflict_entry)
+ add_entry(o, src[i], 0, 0);
return 0;
}
^ permalink raw reply related
* [PATCH 1/2] [TopGit] Portability: Use tr instead of sed for translating spaces to newlines
From: Brian Campbell @ 2009-03-12 5:56 UTC (permalink / raw)
To: Uwe Kleine-König; +Cc: git, Petr Baudis, Brian Campbell
It is not portable to use \n in the replacement of a sed substitute
command. On Mac OS X (and presumably FreeBSD, as Mac OS X uses
sed from FreeBSD), \n in the replacement of a substitution gives a
literal "n" instead of a newline.
This patch replaces the sed command with tr, which should be more
portable.
Signed-off-by: Brian Campbell <brian.p.campbell@dartmouth.edu>
---
tg-create.sh | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/tg-create.sh b/tg-create.sh
index 2edd537..ef9a955 100644
--- a/tg-create.sh
+++ b/tg-create.sh
@@ -116,7 +116,7 @@ done
git update-ref "refs/top-bases/$name" "HEAD" ""
git checkout -b "$name"
-echo "$deps" | sed 's/ /\n/g' >"$root_dir/.topdeps"
+echo "$deps" | tr ' ' '\n' >"$root_dir/.topdeps"
git add -f "$root_dir/.topdeps"
author="$(git var GIT_AUTHOR_IDENT)"
--
1.6.2.185.g8b635.dirty
^ permalink raw reply related
* [PATCH 2/2] [TopGit] Portability: Don't use alternation ("|") in sed regular expressions
From: Brian Campbell @ 2009-03-12 5:56 UTC (permalink / raw)
To: Uwe Kleine-König; +Cc: git, Petr Baudis, Brian Campbell
In-Reply-To: <1236837389-35687-1-git-send-email-brian.p.campbell@dartmouth.edu>
There is no portable way in sed to express alternation (the "|"
operator). POSIX does not specify any way of expressing alternation;
according to POSIX, sed uses basic regular expressions which do not
support alternation. GNU sed allows "\|" to express alternation,
and BSD sed (as tested on Mac OS X) allows for the use of extended
regular expressions with the -E flag, but there appears to be no
portable way to express this.
This patch works around the problem by changing a single sed
expression into two. This patch also factors out all the call
sites that were doing this, to determing the current branch,
into a single function current_branch in tg.sh.
Signed-off-by: Brian Campbell <brian.p.campbell@dartmouth.edu>
---
tg-info.sh | 2 +-
tg-patch.sh | 2 +-
tg-summary.sh | 2 +-
tg-update.sh | 2 +-
tg.sh | 5 +++++
5 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/tg-info.sh b/tg-info.sh
index 7d6a34c..25c753c 100644
--- a/tg-info.sh
+++ b/tg-info.sh
@@ -20,7 +20,7 @@ while [ -n "$1" ]; do
esac
done
-[ -n "$name" ] || name="$(git symbolic-ref HEAD | sed 's#^refs/\(heads\|top-bases\)/##')"
+[ -n "$name" ] || name="$(current_branch)"
base_rev="$(git rev-parse --short --verify "refs/top-bases/$name" 2>/dev/null)" ||
die "not a TopGit-controlled branch"
diff --git a/tg-patch.sh b/tg-patch.sh
index d701c54..ba788c8 100644
--- a/tg-patch.sh
+++ b/tg-patch.sh
@@ -35,7 +35,7 @@ done
[ -n "$name" -a -z "$diff_committed_only" ] &&
die "-i/-w are mutually exclusive with NAME"
-[ -n "$name" ] || name="$(git symbolic-ref HEAD | sed 's#^refs/\(heads\|top-bases\)/##')"
+[ -n "$name" ] || name="$(current_branch)"
base_rev="$(git rev-parse --short --verify "refs/top-bases/$name" 2>/dev/null)" ||
die "not a TopGit-controlled branch"
diff --git a/tg-summary.sh b/tg-summary.sh
index 50ee883..62b499e 100644
--- a/tg-summary.sh
+++ b/tg-summary.sh
@@ -22,7 +22,7 @@ while [ -n "$1" ]; do
esac
done
-curname="$(git symbolic-ref HEAD | sed 's#^refs/\(heads\|top-bases\)/##')"
+curname="$(current_branch)"
! [ -n "$terse" -a -n "$graphviz" ] ||
die "-t and --graphviz options are mutual exclusive"
diff --git a/tg-update.sh b/tg-update.sh
index 288ec14..0cff0ac 100644
--- a/tg-update.sh
+++ b/tg-update.sh
@@ -14,7 +14,7 @@ if [ -n "$1" ]; then
fi
-name="$(git symbolic-ref HEAD | sed 's#^refs/\(heads\|top-bases\)/##')"
+name="$(current_branch)"
base_rev="$(git rev-parse --short --verify "refs/top-bases/$name" 2>/dev/null)" ||
die "not a TopGit-controlled branch"
diff --git a/tg.sh b/tg.sh
index 43d1c9f..232a8b7 100644
--- a/tg.sh
+++ b/tg.sh
@@ -18,6 +18,11 @@ die()
exit 1
}
+current_branch()
+{
+ echo "$(git symbolic-ref HEAD | sed -e 's#^refs/heads/##' -e 's#^refs/top-bases/##')"
+}
+
# cat_file "topic:file"
# Like `git cat-file blob $1`, but topics '(i)' and '(w)' means index and worktree
cat_file()
--
1.6.2.185.g8b635.dirty
^ permalink raw reply related
* Re: Generalised bisection
From: John Tapsell @ 2009-03-12 6:45 UTC (permalink / raw)
To: Ealdwulf Wuffinga; +Cc: Christian Couder, Git List, Ingo Molnar
In-Reply-To: <efe2b6d70903111515p2b9f656bp186d0b3cc7ae483d@mail.gmail.com>
2009/3/11 Ealdwulf Wuffinga <ealdwulf@googlemail.com>:
> [John will get this twice, sorry; not used to this mail interface yet.]
>
> On Wed, Mar 11, 2009 at 9:35 AM, John Tapsell <johnflux@gmail.com> wrote:
>
>> mpmath might be the more annoying dependency - what functions do you
>> use from it? Could they trivially be reimplemented?
>
> What I use is the multiprecision floating point number class. doubles
> don't seem to be long enough.
Hmm, really really? Sometimes this sort of thing can be fixed by just
readjusting the formulas. What formulas are you using that require
more precision than doubles?
> The reason for using mpmath rather than the more widespread GMP (and
> its python wrapper gmpy) is that the latter only supports
> integer powers, whereas BBChop needs fractional powers.
>
> So, it might be possible to switch to gmpy, or some other widespread
> library, by implementing a pow() which supports fractional powers.
> I think I only use the normal arithmetic operators, log, and pow, so
> in principle those could be reimplemented, to eliminate the dependency
> altogether.
> It seems a little bit of a waste of time, though.
A little bit of math trickery helps here :-)
y = x^b
log(y) = log(x^b) = b * log(x)
e^log(y) = e^(b log(x))
y = exp(b * log(x))
So as long as you have 'exp' and 'log' functions, you can raise x to
the power of b, even if b is fractional.
Just to prove it, square root of 2 is:
$ echo "e(0.5*l(2))" | bc -l
1.41421356237309504878
John
^ permalink raw reply
* Re: [PATCH 2/2] [TopGit] Portability: Don't use alternation ("|") in sed regular expressions
From: Junio C Hamano @ 2009-03-12 6:55 UTC (permalink / raw)
To: Brian Campbell; +Cc: Uwe Kleine-König, git, Petr Baudis
In-Reply-To: <1236837389-35687-2-git-send-email-brian.p.campbell@dartmouth.edu>
Brian Campbell <brian.p.campbell@dartmouth.edu> writes:
> +current_branch()
> +{
> + echo "$(git symbolic-ref HEAD | sed -e 's#^refs/heads/##' -e 's#^refs/top-bases/##')"
> +}
Two micronits.
- what happens when you are on a detached HEAD?
- You will be utterly confused by a local branch whose name is
"refs/top-bases/foo"
To fix these, you might want to do something like:
if head_=$(git symbolic-ref HEAD)
then
case "$head_" in
refs/heads/*)
echo "${head_#refs/heads/}"
;;
refs/top-bases/*)
echo "${head_#refs/top-bases/}"
;;
*)
echo "$head_"
;;
esac
else
whatever you want to do on a detached HEAD
fi
^ permalink raw reply
* Re: [EGIT RFC PATCH(was Re: egit problem with sym linked eclipse project dirs)] Add some support for symlinked projects.
From: Robin Rosenberg @ 2009-03-12 6:56 UTC (permalink / raw)
To: Stephen Bannasch; +Cc: Shawn O. Pearce, git
In-Reply-To: <p06240814c5de27cbf520@[63.138.152.192]>
torsdag 12 mars 2009 03:57:09 skrev Stephen Bannasch <stephen.bannasch@deanbrook.org>:
> OK ... I'm a bit confused now because I no longer have Git listed as
> a repository type for Team Sharing.
>
> I deleted the existing org.spearce.* eclipse plugins
>
> [eclipse]$ rm -f plugins/org.spearce.*
>
> pulled from git://repo.or.cz/egit.git
>
> created a new branch for this test and applied your patch
>
> [egit.git (linksbranch)]$ git log
> commit 2b86cd4e27a9d9158092305271d6fb25ab27846e
> Author: Stephen Bannasch <stephen.bannasch@gmail.com>
> Date: Wed Mar 11 22:29:26 2009 -0400
>
> check through links for repositories
> Robin Rosenberg's patch
> see: http://marc.info/?l=git&m=123681033214178&w=2
> and: http://code.google.com/p/egit/issues/detail?id=52
>
> commit 341b9c1abadd2ac0ec9ecc7c597990070612e058
> Author: Ruth Alkema <ruth@diasoft.nl>
> Date: Wed Mar 11 16:42:45 2009 +0100
>
> Better fix for 'negative position' error on large pack files
>
> If position is really big and the window size is fairly small, id can
> be negative. Instead of producing a negative position by extending
> id to a long, mask out the low bits from the original position value
> to compute the window start.
>
> [sp: message by me, as I had already applied v1 of the patch
> and pushed it (see immediate parent)]
>
> Signed-off-by: Ruth Alkema <ruth@diasoft.nl>
> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
>
> ...
>
> Opened Eclipse and switched to the egit workspace. Refreshed the egit
> projects and exported the org.spearce.* packages as deployable
> plugins and fragments to the Eclipse dir.
>
> The new plugins are there:
>
> [eclipse]$ ls plugins/org.spearce.*
> plugins/org.spearce.egit.core.test_0.4.0.200903112237.jar
> plugins/org.spearce.egit_0.4.0.200903112237.jar
> plugins/org.spearce.egit.core_0.4.0.200903112237.jar
> plugins/org.spearce.jgit_0.4.0.200903112237.jar
> plugins/org.spearce.egit.ui_0.4.0.200903112237.jar
>
> Quit and restarted Eclipse.
>
> When I select a project with an existing git repository and try to
> enable team/sharing only CVS and SVN are listed.
You don't have the a matching feature. That could be it, but I'm not sure.
You can also try starting eclipse witth the -clean switch. Looking at the
<workspace>/.metadata/.log could also give you some hints.
For debugging/testing in general it is often easier to launch Eclipse from
eclipse (Run As) without reinstalling.
-- robin
^ permalink raw reply
* Re: [BUG] - git-read-tree segfaults
From: Junio C Hamano @ 2009-03-12 7:01 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Jiri Olsa, git
In-Reply-To: <7vtz5zjnai.fsf@gitster.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> I suspect that the reason add_entry() passed SKIP_DFCHECK was to work
> around an old bug in add_index_entry() that considered it a D/F conflict
> if you have a file D at stage N and a file D/F at stage M when N and M are
> different. I think such a bug has been fixed long time ago, and there is
> no reason for such a workaround. Besides, OK_TO_REPLACE only makes sense
> when you do check D/F conflict ("replace" in the name of the flag means
> "If you want to add 'xxx/zzz' when the index has 'xxx', it is Ok to drop
> the existing 'xxx' in order to add your 'xxx/zzz''); it makes no sense to
> give it if you are giving SKIP_DFCHECK at the same time.
The ancient D/F conflict detection bug in add_cache_entry() I had in mind
was fixed by b155725 ([PATCH] Fix oversimplified optimization for
add_cache_entry()., 2005-06-25). The use of SKIP_DFCHECK turns out to
have nothing to do with working that ancient bug around.
The real culprit seems to be 34110cd (Make 'unpack_trees()' have a
separate source and destination index, 2008-03-06).
Before that commit:
* merge_entry() that records the final tree-level 3-way merge decision
used to pass OK_TO_REPLACE without SKIP_DFCHECK.
* unpack_nondirectories() codepath for non-merge multi-tree read-tree
(the one under discussion in this thread) used to pass SKIP_DFCHECK but
did not pass OK_TO_REPLACE.
The fact that even merge_entry() side passes SKIP_DFCHECK these days does
not appear to be a workaround for an old bug in D/F conflict detection
code after all; it simply is a bug in the refactoring done with the said
commit.
The unpack_nondirectories() codepath passed SKIP_DFCHECK from ee6566e
(Rewrite read-tree, 2005-09-05), which is the very original implementation
of the modern "read-tree A B C" code. The ancient bug in the D/F conflict
detection code was killed way before that commit, and SKIP_DFCHECK in the
commit is not a workaround either; it also simply is a bug.
Side note: I was somewhat surprised that "make test" of that old
commit dates from September 2005 runs _much_ faster than the test
suite we have these days.
The only sane use of SKIP_DFCHECK is when the caller knows the addition is
not introducing D/F conflict in the index to avoid the overhead.
^ permalink raw reply
* [PATCH] read-tree A B C: do not create a bogus index and do not segfault
From: Junio C Hamano @ 2009-03-12 7:29 UTC (permalink / raw)
To: git; +Cc: Jiri Olsa, Johannes Schindelin, Linus Torvalds, Daniel Barkalow
In-Reply-To: <7vfxhjjkcm.fsf@gitster.siamese.dyndns.org>
"git read-tree A B C..." without the "-m" (merge) option is a way to read
these trees on top of each other to get an overlay of them.
An ancient commit ee6566e (Rewrite read-tree, 2005-09-05) passed the
ADD_CACHE_SKIP_DFCHECK flag when calling add_index_entry() to add the
paths obtained from these trees to the index, but it is an incorrect use
of the flag. The flag is meant to be used by callers who know the
addition of the entry does not introduce a D/F conflict to the index in
order to avoid the overhead of checking.
This bug resulted in a bogus index that records both "x" and "x/z" as a
blob after reading three trees that have paths ("x"), ("x", "y"), and
("x/z", "y") respectively. 34110cd (Make 'unpack_trees()' have a separate
source and destination index, 2008-03-06) refactored the callsites of
add_index_entry() incorrectly and added more codepaths that use this flag
when it shouldn't be used.
Also, 0190457 (Move 'unpack_trees()' over to 'traverse_trees()' interface,
2008-03-05) introduced a bug to call add_index_entry() for the tree that
does not have the path in it, passing NULL as a cache entry. This caused
reading multiple trees, one of which has path "x" but another doesn't, to
segfault.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
* I suspect that we can probably remove SKIP_DFCHECK option by fixing
tree.c::read_tree(); the only caller the big comment at the beginning
of it talks about is overlay_tree_on_cache() in builtin-ls-files.c and
we haven't gained any new callers of the function.
It is a bit sad that a very good looking refactoring and rewriting
patch introduced this kind of regression that has gone unnoticed for a
long time. I managed to point three fingers and they turn out to be
all ancient commits before v1.5.5.
unpack-trees.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/unpack-trees.c b/unpack-trees.c
index cba0aca..5b0a8c1 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -49,7 +49,7 @@ static void add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
memcpy(new, ce, size);
new->next = NULL;
new->ce_flags = (new->ce_flags & ~clear) | set;
- add_index_entry(&o->result, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE|ADD_CACHE_SKIP_DFCHECK);
+ add_index_entry(&o->result, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
}
/* Unlink the last component and attempt to remove leading
@@ -283,9 +283,9 @@ static int unpack_nondirectories(int n, unsigned long mask, unsigned long dirmas
if (o->merge)
return call_unpack_fn(src, o);
- n += o->merge;
for (i = 0; i < n; i++)
- add_entry(o, src[i], 0, 0);
+ if (src[i] && src[i] != o->df_conflict_entry)
+ add_entry(o, src[i], 0, 0);
return 0;
}
--
1.6.2.249.g770a0
^ permalink raw reply related
* Re: Google Summer of Code 2009: GIT
From: Junio C Hamano @ 2009-03-12 7:40 UTC (permalink / raw)
To: thestar; +Cc: david, Johannes Schindelin, saurabh gupta, git
In-Reply-To: <20090312125709.qnfnw7glc4ko8soo@webmail.fussycoder.id.au>
thestar@fussycoder.id.au writes:
> <Entire conversation snipped>
Which is not appreciated at all.
> Guys, I'm sure you're only using OpenOffice.org documents as an
> example to facilitate discussing merge helpers, but I feel the need to
> point out that one can already merge OpenOffice documents using
> OpenOffice to do so. (And I have done so in the past while reconciling
> differences between some spreadsheets).
It sounds like OOo itself can be counted as a "domain specific merge
helper" in the second sense of the word---it wouldn't work as a merge
driver but the end user can use it to merge the forked documents.
Which is good to know ;-)
^ permalink raw reply
* Re: [PATCH 2/2] [TopGit] Portability: Don't use alternation ("|") in sed regular expressions
From: Uwe Kleine-König @ 2009-03-12 7:45 UTC (permalink / raw)
To: Brian Campbell, Junio C Hamano; +Cc: git, Petr Baudis
In-Reply-To: <7viqmfjklm.fsf@gitster.siamese.dyndns.org>
Hello Brian, hello Junio,
On Wed, Mar 11, 2009 at 11:55:49PM -0700, Junio C Hamano wrote:
> Brian Campbell <brian.p.campbell@dartmouth.edu> writes:
>
> > +current_branch()
> > +{
> > + echo "$(git symbolic-ref HEAD | sed -e 's#^refs/heads/##' -e 's#^refs/top-bases/##')"
> > +}
>
> Two micronits.
>
> - what happens when you are on a detached HEAD?
The original code had this problem, too, so I would not take this as a
stopper for the patch. There are some other locations that suffer from
the same problem. That's already on my todo list. So I don't care much
here.
> - You will be utterly confused by a local branch whose name is
> "refs/top-bases/foo"
You mean a branch that has the full name refs/heads/refs/top-bases/foo?
Well OK, valid concern.
> To fix these, you might want to do something like:
>
> if head_=$(git symbolic-ref HEAD)
> then
> case "$head_" in
> refs/heads/*)
> echo "${head_#refs/heads/}"
> ;;
> refs/top-bases/*)
> echo "${head_#refs/top-bases/}"
> ;;
> *)
> echo "$head_"
> ;;
> esac
> else
> whatever you want to do on a detached HEAD
> fi
Thanks Junio and Brian.
Brian, do you update the series?
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* [PATCH 1/7] strbuf: add "include_delim" parameter to "strbuf_split"
From: Christian Couder @ 2009-03-12 7:51 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Ingo Molnar, John Tapsell, Johannes Schindelin,
Pierre Habouzit
The "strbuf_split" function used to include the delimiter character
at the end of the splited strbufs it produced.
This behavior is not wanted in many cases, so this patch adds a new
"include_delim" parameter to the function to let us switch it on or
off as we want.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin-mailinfo.c | 2 +-
imap-send.c | 2 +-
strbuf.c | 8 +++++---
strbuf.h | 2 +-
4 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
index 2789ccd..b96ea1a 100644
--- a/builtin-mailinfo.c
+++ b/builtin-mailinfo.c
@@ -814,7 +814,7 @@ static void handle_body(void)
* multiple new lines. Pass only one chunk
* at a time to handle_filter()
*/
- lines = strbuf_split(&line, '\n');
+ lines = strbuf_split(&line, '\n', 1);
for (it = lines; (sb = *it); it++) {
if (*(it + 1) == NULL) /* The last line */
if (sb->buf[sb->len - 1] != '\n') {
diff --git a/imap-send.c b/imap-send.c
index cb518eb..a27f744 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -1289,7 +1289,7 @@ static void wrap_in_html(struct msg_data *msg)
int added_header = 0;
strbuf_attach(&buf, msg->data, msg->len, msg->len);
- lines = strbuf_split(&buf, '\n');
+ lines = strbuf_split(&buf, '\n', 1);
strbuf_release(&buf);
for (p = lines; *p; p++) {
if (! added_header) {
diff --git a/strbuf.c b/strbuf.c
index 6ed0684..4ef9084 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -97,7 +97,9 @@ void strbuf_tolower(struct strbuf *sb)
sb->buf[i] = tolower(sb->buf[i]);
}
-struct strbuf **strbuf_split(const struct strbuf *sb, int delim)
+struct strbuf **strbuf_split(const struct strbuf *sb,
+ int delim,
+ int include_delim)
{
int alloc = 2, pos = 0;
char *n, *p;
@@ -114,8 +116,8 @@ struct strbuf **strbuf_split(const struct strbuf *sb, int delim)
ret = xrealloc(ret, sizeof(struct strbuf *) * alloc);
}
if (!n)
- n = sb->buf + sb->len - 1;
- len = n - p + 1;
+ n = sb->buf + sb->len - (include_delim ? 1 : 0);
+ len = n - p + (include_delim ? 1 : 0);
t = xmalloc(sizeof(struct strbuf));
strbuf_init(t, len);
strbuf_add(t, p, len);
diff --git a/strbuf.h b/strbuf.h
index 89bd36e..2202d28 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -83,7 +83,7 @@ extern void strbuf_ltrim(struct strbuf *);
extern int strbuf_cmp(const struct strbuf *, const struct strbuf *);
extern void strbuf_tolower(struct strbuf *);
-extern struct strbuf **strbuf_split(const struct strbuf *, int delim);
+extern struct strbuf **strbuf_split(const struct strbuf *, int delim, int include_delim);
extern void strbuf_list_free(struct strbuf **);
/*----- add data in your buffer -----*/
--
1.6.2.83.g012a16.dirty
^ permalink raw reply related
* [PATCH 2/7] rev-list: make "bisect_list" variable local to "cmd_rev_list"
From: Christian Couder @ 2009-03-12 7:51 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Ingo Molnar, John Tapsell, Johannes Schindelin
The "bisect_list" variable was static for no reason as it is only used
in the "cmd_rev_list" function.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin-rev-list.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index 40d5fcb..28fe2dc 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -52,7 +52,6 @@ static const char rev_list_usage[] =
static struct rev_info revs;
-static int bisect_list;
static int show_timestamp;
static int hdr_termination;
static const char *header_prefix;
@@ -618,6 +617,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
struct commit_list *list;
int i;
int read_from_stdin = 0;
+ int bisect_list = 0;
int bisect_show_vars = 0;
int bisect_find_all = 0;
int quiet = 0;
--
1.6.2.83.g012a16.dirty
^ permalink raw reply related
* [PATCH 3/7] rev-list: move bisect related code into its own file
From: Christian Couder @ 2009-03-12 7:51 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Ingo Molnar, John Tapsell, Johannes Schindelin
This patch creates new "bisect.c" and "bisect.h" files and move
bisect related code into these files.
While at it, we also remove some include directives that are not
needed any more from the beginning of "builtin-rev-list.c".
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
Makefile | 1 +
bisect.c | 388 ++++++++++++++++++++++++++++++++++++++++++++++++++++
bisect.h | 8 +
builtin-rev-list.c | 388 +---------------------------------------------------
4 files changed, 398 insertions(+), 387 deletions(-)
create mode 100644 bisect.c
create mode 100644 bisect.h
diff --git a/Makefile b/Makefile
index 0675c43..9500c5e 100644
--- a/Makefile
+++ b/Makefile
@@ -414,6 +414,7 @@ LIB_OBJS += archive-tar.o
LIB_OBJS += archive-zip.o
LIB_OBJS += attr.o
LIB_OBJS += base85.o
+LIB_OBJS += bisect.o
LIB_OBJS += blob.o
LIB_OBJS += branch.o
LIB_OBJS += bundle.o
diff --git a/bisect.c b/bisect.c
new file mode 100644
index 0000000..27def7d
--- /dev/null
+++ b/bisect.c
@@ -0,0 +1,388 @@
+#include "cache.h"
+#include "commit.h"
+#include "diff.h"
+#include "revision.h"
+#include "bisect.h"
+
+/* bits #0-15 in revision.h */
+
+#define COUNTED (1u<<16)
+
+/*
+ * This is a truly stupid algorithm, but it's only
+ * used for bisection, and we just don't care enough.
+ *
+ * We care just barely enough to avoid recursing for
+ * non-merge entries.
+ */
+static int count_distance(struct commit_list *entry)
+{
+ int nr = 0;
+
+ while (entry) {
+ struct commit *commit = entry->item;
+ struct commit_list *p;
+
+ if (commit->object.flags & (UNINTERESTING | COUNTED))
+ break;
+ if (!(commit->object.flags & TREESAME))
+ nr++;
+ commit->object.flags |= COUNTED;
+ p = commit->parents;
+ entry = p;
+ if (p) {
+ p = p->next;
+ while (p) {
+ nr += count_distance(p);
+ p = p->next;
+ }
+ }
+ }
+
+ return nr;
+}
+
+static void clear_distance(struct commit_list *list)
+{
+ while (list) {
+ struct commit *commit = list->item;
+ commit->object.flags &= ~COUNTED;
+ list = list->next;
+ }
+}
+
+#define DEBUG_BISECT 0
+
+static inline int weight(struct commit_list *elem)
+{
+ return *((int*)(elem->item->util));
+}
+
+static inline void weight_set(struct commit_list *elem, int weight)
+{
+ *((int*)(elem->item->util)) = weight;
+}
+
+static int count_interesting_parents(struct commit *commit)
+{
+ struct commit_list *p;
+ int count;
+
+ for (count = 0, p = commit->parents; p; p = p->next) {
+ if (p->item->object.flags & UNINTERESTING)
+ continue;
+ count++;
+ }
+ return count;
+}
+
+static inline int halfway(struct commit_list *p, int nr)
+{
+ /*
+ * Don't short-cut something we are not going to return!
+ */
+ if (p->item->object.flags & TREESAME)
+ return 0;
+ if (DEBUG_BISECT)
+ return 0;
+ /*
+ * 2 and 3 are halfway of 5.
+ * 3 is halfway of 6 but 2 and 4 are not.
+ */
+ switch (2 * weight(p) - nr) {
+ case -1: case 0: case 1:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+#if !DEBUG_BISECT
+#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 *p;
+
+ fprintf(stderr, "%s (%d/%d)\n", debug, counted, nr);
+
+ for (p = list; p; p = p->next) {
+ struct commit_list *pp;
+ struct commit *commit = p->item;
+ unsigned flags = commit->object.flags;
+ enum object_type type;
+ unsigned long size;
+ char *buf = read_sha1_file(commit->object.sha1, &type, &size);
+ char *ep, *sp;
+
+ fprintf(stderr, "%c%c%c ",
+ (flags & TREESAME) ? ' ' : 'T',
+ (flags & UNINTERESTING) ? 'U' : ' ',
+ (flags & COUNTED) ? 'C' : ' ');
+ if (commit->util)
+ fprintf(stderr, "%3d", weight(p));
+ else
+ fprintf(stderr, "---");
+ fprintf(stderr, " %.*s", 8, sha1_to_hex(commit->object.sha1));
+ for (pp = commit->parents; pp; pp = pp->next)
+ fprintf(stderr, " %.*s", 8,
+ sha1_to_hex(pp->item->object.sha1));
+
+ sp = strstr(buf, "\n\n");
+ if (sp) {
+ sp += 2;
+ for (ep = sp; *ep && *ep != '\n'; ep++)
+ ;
+ fprintf(stderr, " %.*s", (int)(ep - sp), sp);
+ }
+ fprintf(stderr, "\n");
+ }
+}
+#endif /* DEBUG_BISECT */
+
+static struct commit_list *best_bisection(struct commit_list *list, int nr)
+{
+ struct commit_list *p, *best;
+ int best_distance = -1;
+
+ best = list;
+ for (p = list; p; p = p->next) {
+ int distance;
+ unsigned flags = p->item->object.flags;
+
+ if (flags & TREESAME)
+ continue;
+ distance = weight(p);
+ if (nr - distance < distance)
+ distance = nr - distance;
+ if (distance > best_distance) {
+ best = p;
+ best_distance = distance;
+ }
+ }
+
+ return best;
+}
+
+struct commit_dist {
+ struct commit *commit;
+ int distance;
+};
+
+static int compare_commit_dist(const void *a_, const void *b_)
+{
+ struct commit_dist *a, *b;
+
+ a = (struct commit_dist *)a_;
+ b = (struct commit_dist *)b_;
+ if (a->distance != b->distance)
+ return b->distance - a->distance; /* desc sort */
+ return hashcmp(a->commit->object.sha1, b->commit->object.sha1);
+}
+
+static struct commit_list *best_bisection_sorted(struct commit_list *list, int nr)
+{
+ struct commit_list *p;
+ struct commit_dist *array = xcalloc(nr, sizeof(*array));
+ int cnt, i;
+
+ for (p = list, cnt = 0; p; p = p->next) {
+ int distance;
+ unsigned flags = p->item->object.flags;
+
+ if (flags & TREESAME)
+ continue;
+ distance = weight(p);
+ if (nr - distance < distance)
+ distance = nr - distance;
+ array[cnt].commit = p->item;
+ array[cnt].distance = distance;
+ cnt++;
+ }
+ qsort(array, cnt, sizeof(*array), compare_commit_dist);
+ for (p = list, i = 0; i < cnt; i++) {
+ struct name_decoration *r = xmalloc(sizeof(*r) + 100);
+ struct object *obj = &(array[i].commit->object);
+
+ sprintf(r->name, "dist=%d", array[i].distance);
+ r->next = add_decoration(&name_decoration, obj, r);
+ p->item = array[i].commit;
+ p = p->next;
+ }
+ if (p)
+ p->next = NULL;
+ free(array);
+ return list;
+}
+
+/*
+ * zero or positive weight is the number of interesting commits it can
+ * reach, including itself. Especially, weight = 0 means it does not
+ * reach any tree-changing commits (e.g. just above uninteresting one
+ * but traversal is with pathspec).
+ *
+ * weight = -1 means it has one parent and its distance is yet to
+ * be computed.
+ *
+ * weight = -2 means it has more than one parent and its distance is
+ * unknown. After running count_distance() first, they will get zero
+ * or positive distance.
+ */
+static struct commit_list *do_find_bisection(struct commit_list *list,
+ int nr, int *weights,
+ int find_all)
+{
+ int n, counted;
+ struct commit_list *p;
+
+ counted = 0;
+
+ for (n = 0, p = list; p; p = p->next) {
+ struct commit *commit = p->item;
+ unsigned flags = commit->object.flags;
+
+ p->item->util = &weights[n++];
+ switch (count_interesting_parents(commit)) {
+ case 0:
+ if (!(flags & TREESAME)) {
+ weight_set(p, 1);
+ counted++;
+ show_list("bisection 2 count one",
+ counted, nr, list);
+ }
+ /*
+ * otherwise, it is known not to reach any
+ * tree-changing commit and gets weight 0.
+ */
+ break;
+ case 1:
+ weight_set(p, -1);
+ break;
+ default:
+ weight_set(p, -2);
+ break;
+ }
+ }
+
+ show_list("bisection 2 initialize", counted, nr, list);
+
+ /*
+ * If you have only one parent in the resulting set
+ * then you can reach one commit more than that parent
+ * can reach. So we do not have to run the expensive
+ * count_distance() for single strand of pearls.
+ *
+ * However, if you have more than one parents, you cannot
+ * just add their distance and one for yourself, since
+ * they usually reach the same ancestor and you would
+ * end up counting them twice that way.
+ *
+ * So we will first count distance of merges the usual
+ * way, and then fill the blanks using cheaper algorithm.
+ */
+ for (p = list; p; p = p->next) {
+ if (p->item->object.flags & UNINTERESTING)
+ continue;
+ if (weight(p) != -2)
+ continue;
+ weight_set(p, count_distance(p));
+ clear_distance(list);
+
+ /* Does it happen to be at exactly half-way? */
+ if (!find_all && halfway(p, nr))
+ return p;
+ counted++;
+ }
+
+ show_list("bisection 2 count_distance", counted, nr, list);
+
+ while (counted < nr) {
+ for (p = list; p; p = p->next) {
+ struct commit_list *q;
+ unsigned flags = p->item->object.flags;
+
+ if (0 <= weight(p))
+ continue;
+ for (q = p->item->parents; q; q = q->next) {
+ if (q->item->object.flags & UNINTERESTING)
+ continue;
+ if (0 <= weight(q))
+ break;
+ }
+ if (!q)
+ continue;
+
+ /*
+ * weight for p is unknown but q is known.
+ * add one for p itself if p is to be counted,
+ * otherwise inherit it from q directly.
+ */
+ if (!(flags & TREESAME)) {
+ weight_set(p, weight(q)+1);
+ counted++;
+ show_list("bisection 2 count one",
+ counted, nr, list);
+ }
+ else
+ weight_set(p, weight(q));
+
+ /* Does it happen to be at exactly half-way? */
+ if (!find_all && halfway(p, nr))
+ return p;
+ }
+ }
+
+ show_list("bisection 2 counted all", counted, nr, list);
+
+ if (!find_all)
+ return best_bisection(list, nr);
+ else
+ return best_bisection_sorted(list, nr);
+}
+
+struct commit_list *find_bisection(struct commit_list *list,
+ int *reaches, int *all,
+ int find_all)
+{
+ int nr, on_list;
+ struct commit_list *p, *best, *next, *last;
+ int *weights;
+
+ show_list("bisection 2 entry", 0, 0, list);
+
+ /*
+ * Count the number of total and tree-changing items on the
+ * list, while reversing the list.
+ */
+ for (nr = on_list = 0, last = NULL, p = list;
+ p;
+ p = next) {
+ unsigned flags = p->item->object.flags;
+
+ next = p->next;
+ if (flags & UNINTERESTING)
+ continue;
+ p->next = last;
+ last = p;
+ if (!(flags & TREESAME))
+ nr++;
+ on_list++;
+ }
+ list = last;
+ show_list("bisection 2 sorted", 0, nr, list);
+
+ *all = nr;
+ weights = xcalloc(on_list, sizeof(*weights));
+
+ /* Do the real work of finding bisection commit. */
+ best = do_find_bisection(list, nr, weights, find_all);
+ if (best) {
+ if (!find_all)
+ best->next = NULL;
+ *reaches = weight(best);
+ }
+ free(weights);
+ return best;
+}
+
diff --git a/bisect.h b/bisect.h
new file mode 100644
index 0000000..cce268d
--- /dev/null
+++ b/bisect.h
@@ -0,0 +1,8 @@
+#ifndef BISECT_H
+#define BISECT_H
+
+struct commit_list *find_bisection(struct commit_list *list,
+ int *reaches, int *all,
+ int find_all);
+
+#endif
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index 28fe2dc..b1e8200 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -1,20 +1,12 @@
#include "cache.h"
-#include "refs.h"
-#include "tag.h"
#include "commit.h"
-#include "tree.h"
-#include "blob.h"
-#include "tree-walk.h"
#include "diff.h"
#include "revision.h"
#include "list-objects.h"
#include "builtin.h"
#include "log-tree.h"
#include "graph.h"
-
-/* bits #0-15 in revision.h */
-
-#define COUNTED (1u<<16)
+#include "bisect.h"
static const char rev_list_usage[] =
"git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
@@ -195,384 +187,6 @@ static void show_edge(struct commit *commit)
printf("-%s\n", sha1_to_hex(commit->object.sha1));
}
-/*
- * This is a truly stupid algorithm, but it's only
- * used for bisection, and we just don't care enough.
- *
- * We care just barely enough to avoid recursing for
- * non-merge entries.
- */
-static int count_distance(struct commit_list *entry)
-{
- int nr = 0;
-
- while (entry) {
- struct commit *commit = entry->item;
- struct commit_list *p;
-
- if (commit->object.flags & (UNINTERESTING | COUNTED))
- break;
- if (!(commit->object.flags & TREESAME))
- nr++;
- commit->object.flags |= COUNTED;
- p = commit->parents;
- entry = p;
- if (p) {
- p = p->next;
- while (p) {
- nr += count_distance(p);
- p = p->next;
- }
- }
- }
-
- return nr;
-}
-
-static void clear_distance(struct commit_list *list)
-{
- while (list) {
- struct commit *commit = list->item;
- commit->object.flags &= ~COUNTED;
- list = list->next;
- }
-}
-
-#define DEBUG_BISECT 0
-
-static inline int weight(struct commit_list *elem)
-{
- return *((int*)(elem->item->util));
-}
-
-static inline void weight_set(struct commit_list *elem, int weight)
-{
- *((int*)(elem->item->util)) = weight;
-}
-
-static int count_interesting_parents(struct commit *commit)
-{
- struct commit_list *p;
- int count;
-
- for (count = 0, p = commit->parents; p; p = p->next) {
- if (p->item->object.flags & UNINTERESTING)
- continue;
- count++;
- }
- return count;
-}
-
-static inline int halfway(struct commit_list *p, int nr)
-{
- /*
- * Don't short-cut something we are not going to return!
- */
- if (p->item->object.flags & TREESAME)
- return 0;
- if (DEBUG_BISECT)
- return 0;
- /*
- * 2 and 3 are halfway of 5.
- * 3 is halfway of 6 but 2 and 4 are not.
- */
- switch (2 * weight(p) - nr) {
- case -1: case 0: case 1:
- return 1;
- default:
- return 0;
- }
-}
-
-#if !DEBUG_BISECT
-#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 *p;
-
- fprintf(stderr, "%s (%d/%d)\n", debug, counted, nr);
-
- for (p = list; p; p = p->next) {
- struct commit_list *pp;
- struct commit *commit = p->item;
- unsigned flags = commit->object.flags;
- enum object_type type;
- unsigned long size;
- char *buf = read_sha1_file(commit->object.sha1, &type, &size);
- char *ep, *sp;
-
- fprintf(stderr, "%c%c%c ",
- (flags & TREESAME) ? ' ' : 'T',
- (flags & UNINTERESTING) ? 'U' : ' ',
- (flags & COUNTED) ? 'C' : ' ');
- if (commit->util)
- fprintf(stderr, "%3d", weight(p));
- else
- fprintf(stderr, "---");
- fprintf(stderr, " %.*s", 8, sha1_to_hex(commit->object.sha1));
- for (pp = commit->parents; pp; pp = pp->next)
- fprintf(stderr, " %.*s", 8,
- sha1_to_hex(pp->item->object.sha1));
-
- sp = strstr(buf, "\n\n");
- if (sp) {
- sp += 2;
- for (ep = sp; *ep && *ep != '\n'; ep++)
- ;
- fprintf(stderr, " %.*s", (int)(ep - sp), sp);
- }
- fprintf(stderr, "\n");
- }
-}
-#endif /* DEBUG_BISECT */
-
-static struct commit_list *best_bisection(struct commit_list *list, int nr)
-{
- struct commit_list *p, *best;
- int best_distance = -1;
-
- best = list;
- for (p = list; p; p = p->next) {
- int distance;
- unsigned flags = p->item->object.flags;
-
- if (flags & TREESAME)
- continue;
- distance = weight(p);
- if (nr - distance < distance)
- distance = nr - distance;
- if (distance > best_distance) {
- best = p;
- best_distance = distance;
- }
- }
-
- return best;
-}
-
-struct commit_dist {
- struct commit *commit;
- int distance;
-};
-
-static int compare_commit_dist(const void *a_, const void *b_)
-{
- struct commit_dist *a, *b;
-
- a = (struct commit_dist *)a_;
- b = (struct commit_dist *)b_;
- if (a->distance != b->distance)
- return b->distance - a->distance; /* desc sort */
- return hashcmp(a->commit->object.sha1, b->commit->object.sha1);
-}
-
-static struct commit_list *best_bisection_sorted(struct commit_list *list, int nr)
-{
- struct commit_list *p;
- struct commit_dist *array = xcalloc(nr, sizeof(*array));
- int cnt, i;
-
- for (p = list, cnt = 0; p; p = p->next) {
- int distance;
- unsigned flags = p->item->object.flags;
-
- if (flags & TREESAME)
- continue;
- distance = weight(p);
- if (nr - distance < distance)
- distance = nr - distance;
- array[cnt].commit = p->item;
- array[cnt].distance = distance;
- cnt++;
- }
- qsort(array, cnt, sizeof(*array), compare_commit_dist);
- for (p = list, i = 0; i < cnt; i++) {
- struct name_decoration *r = xmalloc(sizeof(*r) + 100);
- struct object *obj = &(array[i].commit->object);
-
- sprintf(r->name, "dist=%d", array[i].distance);
- r->next = add_decoration(&name_decoration, obj, r);
- p->item = array[i].commit;
- p = p->next;
- }
- if (p)
- p->next = NULL;
- free(array);
- return list;
-}
-
-/*
- * zero or positive weight is the number of interesting commits it can
- * reach, including itself. Especially, weight = 0 means it does not
- * reach any tree-changing commits (e.g. just above uninteresting one
- * but traversal is with pathspec).
- *
- * weight = -1 means it has one parent and its distance is yet to
- * be computed.
- *
- * weight = -2 means it has more than one parent and its distance is
- * unknown. After running count_distance() first, they will get zero
- * or positive distance.
- */
-static struct commit_list *do_find_bisection(struct commit_list *list,
- int nr, int *weights,
- int find_all)
-{
- int n, counted;
- struct commit_list *p;
-
- counted = 0;
-
- for (n = 0, p = list; p; p = p->next) {
- struct commit *commit = p->item;
- unsigned flags = commit->object.flags;
-
- p->item->util = &weights[n++];
- switch (count_interesting_parents(commit)) {
- case 0:
- if (!(flags & TREESAME)) {
- weight_set(p, 1);
- counted++;
- show_list("bisection 2 count one",
- counted, nr, list);
- }
- /*
- * otherwise, it is known not to reach any
- * tree-changing commit and gets weight 0.
- */
- break;
- case 1:
- weight_set(p, -1);
- break;
- default:
- weight_set(p, -2);
- break;
- }
- }
-
- show_list("bisection 2 initialize", counted, nr, list);
-
- /*
- * If you have only one parent in the resulting set
- * then you can reach one commit more than that parent
- * can reach. So we do not have to run the expensive
- * count_distance() for single strand of pearls.
- *
- * However, if you have more than one parents, you cannot
- * just add their distance and one for yourself, since
- * they usually reach the same ancestor and you would
- * end up counting them twice that way.
- *
- * So we will first count distance of merges the usual
- * way, and then fill the blanks using cheaper algorithm.
- */
- for (p = list; p; p = p->next) {
- if (p->item->object.flags & UNINTERESTING)
- continue;
- if (weight(p) != -2)
- continue;
- weight_set(p, count_distance(p));
- clear_distance(list);
-
- /* Does it happen to be at exactly half-way? */
- if (!find_all && halfway(p, nr))
- return p;
- counted++;
- }
-
- show_list("bisection 2 count_distance", counted, nr, list);
-
- while (counted < nr) {
- for (p = list; p; p = p->next) {
- struct commit_list *q;
- unsigned flags = p->item->object.flags;
-
- if (0 <= weight(p))
- continue;
- for (q = p->item->parents; q; q = q->next) {
- if (q->item->object.flags & UNINTERESTING)
- continue;
- if (0 <= weight(q))
- break;
- }
- if (!q)
- continue;
-
- /*
- * weight for p is unknown but q is known.
- * add one for p itself if p is to be counted,
- * otherwise inherit it from q directly.
- */
- if (!(flags & TREESAME)) {
- weight_set(p, weight(q)+1);
- counted++;
- show_list("bisection 2 count one",
- counted, nr, list);
- }
- else
- weight_set(p, weight(q));
-
- /* Does it happen to be at exactly half-way? */
- if (!find_all && halfway(p, nr))
- return p;
- }
- }
-
- show_list("bisection 2 counted all", counted, nr, list);
-
- if (!find_all)
- return best_bisection(list, nr);
- else
- return best_bisection_sorted(list, nr);
-}
-
-static struct commit_list *find_bisection(struct commit_list *list,
- int *reaches, int *all,
- int find_all)
-{
- int nr, on_list;
- struct commit_list *p, *best, *next, *last;
- int *weights;
-
- show_list("bisection 2 entry", 0, 0, list);
-
- /*
- * Count the number of total and tree-changing items on the
- * list, while reversing the list.
- */
- for (nr = on_list = 0, last = NULL, p = list;
- p;
- p = next) {
- unsigned flags = p->item->object.flags;
-
- next = p->next;
- if (flags & UNINTERESTING)
- continue;
- p->next = last;
- last = p;
- if (!(flags & TREESAME))
- nr++;
- on_list++;
- }
- list = last;
- show_list("bisection 2 sorted", 0, nr, list);
-
- *all = nr;
- weights = xcalloc(on_list, sizeof(*weights));
-
- /* Do the real work of finding bisection commit. */
- best = do_find_bisection(list, nr, weights, find_all);
- if (best) {
- if (!find_all)
- best->next = NULL;
- *reaches = weight(best);
- }
- free(weights);
- return best;
-}
-
static inline int log2i(int n)
{
int log2 = 0;
--
1.6.2.83.g012a16.dirty
^ permalink raw reply related
* [PATCH 4/7] rev-list: implement "--bisect-skip" option
From: Christian Couder @ 2009-03-12 7:51 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Ingo Molnar, John Tapsell, Johannes Schindelin
When bisecting, skipped revisions used to be filtered by the
"filter_skipped" function in "git-bisect.sh". This was not very
efficient and error prone, and it made it difficult to implement
new behaviors when skipping commits.
This patch moves the logic from the "filter_skipped" shell function
into a new "bisect-skip.c" file. And a new "--bisect-skip" option is
implemented in "builtin-rev-list.c" to use this logic.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
Makefile | 1 +
bisect-skip.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++
bisect.h | 5 +++
builtin-rev-list.c | 40 +++++++++++++++++++++--
4 files changed, 132 insertions(+), 4 deletions(-)
create mode 100644 bisect-skip.c
I know that there is no documentation along with this, but I am
working on it and hope to send it soon.
diff --git a/Makefile b/Makefile
index 9500c5e..126a06d 100644
--- a/Makefile
+++ b/Makefile
@@ -415,6 +415,7 @@ LIB_OBJS += archive-zip.o
LIB_OBJS += attr.o
LIB_OBJS += base85.o
LIB_OBJS += bisect.o
+LIB_OBJS += bisect-skip.o
LIB_OBJS += blob.o
LIB_OBJS += branch.o
LIB_OBJS += bundle.o
diff --git a/bisect-skip.c b/bisect-skip.c
new file mode 100644
index 0000000..9228465
--- /dev/null
+++ b/bisect-skip.c
@@ -0,0 +1,90 @@
+#include "cache.h"
+#include "commit.h"
+#include "strbuf.h"
+#include "bisect.h"
+
+static unsigned char (*skipped_sha1)[20];
+static int skipped_sha1_nr;
+static int skipped_sha1_alloc;
+
+void register_skipped(const char *skipped)
+{
+ struct strbuf sb, **list, **it, *cur;
+ int len = strlen(skipped);
+
+ strbuf_init(&sb, len);
+ strbuf_add(&sb, skipped, len);
+
+ list = strbuf_split(&sb, ',', 0);
+
+ for (it = list; (cur = *it); it++) {
+ ALLOC_GROW(skipped_sha1, skipped_sha1_nr + 1,
+ skipped_sha1_alloc);
+ if (get_sha1(cur->buf, skipped_sha1[skipped_sha1_nr++]))
+ die("Bad bisect skip ref: %s", cur->buf);
+ }
+
+ strbuf_list_free(list);
+ strbuf_release(&sb);
+}
+
+static int skipcmp(const void *a, const void *b)
+{
+ return hashcmp(a, b);
+}
+
+static void prepare_skipped(void)
+{
+ qsort(skipped_sha1, skipped_sha1_nr, sizeof(*skipped_sha1), skipcmp);
+}
+
+static int lookup_skipped(unsigned char *sha1)
+{
+ int lo, hi;
+ lo = 0;
+ hi = skipped_sha1_nr;
+ while (lo < hi) {
+ int mi = (lo + hi) / 2;
+ int cmp = hashcmp(sha1, skipped_sha1[mi]);
+ if (!cmp)
+ return mi;
+ if (cmp < 0)
+ hi = mi;
+ else
+ lo = mi + 1;
+ }
+ return -lo - 1;
+}
+
+struct commit_list *filter_skipped(struct commit_list *list,
+ struct commit_list **tried,
+ int show_all)
+{
+ struct commit_list *filtered = NULL, **f = &filtered;
+
+ *tried = NULL;
+
+ if (!skipped_sha1_nr)
+ return list;
+
+ prepare_skipped();
+
+ while (list) {
+ struct commit_list *next = list->next;
+ list->next = NULL;
+ if (0 <= lookup_skipped(list->item->object.sha1)) {
+ /* Move current to tried list */
+ *tried = list;
+ tried = &list->next;
+ } else {
+ if (!show_all)
+ return list;
+ /* Move current to filtered list */
+ *f = list;
+ f = &list->next;
+ }
+ list = next;
+ }
+
+ return filtered;
+}
diff --git a/bisect.h b/bisect.h
index cce268d..c5f9fe1 100644
--- a/bisect.h
+++ b/bisect.h
@@ -1,6 +1,11 @@
#ifndef BISECT_H
#define BISECT_H
+void register_skipped(const char *skipped);
+struct commit_list *filter_skipped(struct commit_list *list,
+ struct commit_list **tried,
+ int show_all);
+
struct commit_list *find_bisection(struct commit_list *list,
int *reaches, int *all,
int find_all);
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index b1e8200..b50d304 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -39,7 +39,8 @@ static const char rev_list_usage[] =
" special purpose:\n"
" --bisect\n"
" --bisect-vars\n"
-" --bisect-all"
+" --bisect-all\n"
+" --bisect-skip"
;
static struct rev_info revs;
@@ -226,6 +227,16 @@ static int estimate_bisect_steps(int all)
return (e < 3 * x) ? n : n - 1;
}
+static void show_tried(struct commit_list *tried)
+{
+ printf("bisect_tried='");
+ for (;tried; tried = tried->next) {
+ char *format = tried->next ? "%s|" : "%s";
+ printf(format, sha1_to_hex(tried->item->object.sha1));
+ }
+ printf("'\n");
+}
+
int cmd_rev_list(int argc, const char **argv, const char *prefix)
{
struct commit_list *list;
@@ -234,6 +245,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
int bisect_list = 0;
int bisect_show_vars = 0;
int bisect_find_all = 0;
+ int bisect_show_all = 0;
+ int bisect_skip = 0;
int quiet = 0;
git_config(git_default_config, NULL);
@@ -261,6 +274,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
if (!strcmp(arg, "--bisect-all")) {
bisect_list = 1;
bisect_find_all = 1;
+ bisect_show_all = 1;
revs.show_decorations = 1;
continue;
}
@@ -269,6 +283,14 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
bisect_show_vars = 1;
continue;
}
+ if (!prefixcmp(arg, "--bisect-skip=")) {
+ bisect_list = 1;
+ bisect_show_vars = 1;
+ bisect_find_all = 1;
+ bisect_skip = 1;
+ register_skipped(arg + 14);
+ continue;
+ }
if (!strcmp(arg, "--stdin")) {
if (read_from_stdin++)
die("--stdin given twice?");
@@ -310,13 +332,18 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
if (bisect_list) {
int reaches = reaches, all = all;
+ struct commit_list *tried;
revs.commits = find_bisection(revs.commits, &reaches, &all,
bisect_find_all);
+
+ revs.commits = filter_skipped(revs.commits, &tried,
+ bisect_show_all);
+
if (bisect_show_vars) {
int cnt;
char hex[41];
- if (!revs.commits)
+ if (!revs.commits && !bisect_skip)
return 1;
/*
* revs.commits can reach "reaches" commits among
@@ -330,13 +357,18 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
cnt = all - reaches;
if (cnt < reaches)
cnt = reaches;
- strcpy(hex, sha1_to_hex(revs.commits->item->object.sha1));
+ if (revs.commits)
+ strcpy(hex, sha1_to_hex(revs.commits->item->object.sha1));
+ else
+ hex[0] = '\0';
- if (bisect_find_all) {
+ if (bisect_show_all) {
traverse_commit_list(&revs, show_commit, show_object);
printf("------\n");
}
+ if (bisect_skip)
+ show_tried(tried);
printf("bisect_rev=%s\n"
"bisect_nr=%d\n"
"bisect_good=%d\n"
--
1.6.2.83.g012a16.dirty
^ permalink raw reply related
* [PATCH 5/7] rev-list: move code to show bisect vars into its own function
From: Christian Couder @ 2009-03-12 7:51 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Ingo Molnar, John Tapsell, Johannes Schindelin
This is a straightforward clean up to make "cmd_rev_list" function
smaller.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin-rev-list.c | 101 ++++++++++++++++++++++++++++------------------------
1 files changed, 54 insertions(+), 47 deletions(-)
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index b50d304..6e0466e 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -237,6 +237,57 @@ static void show_tried(struct commit_list *tried)
printf("'\n");
}
+static int show_bisect_vars(int reaches, int all, int show_all, int skip)
+{
+ int cnt;
+ char hex[41];
+ struct commit_list *tried;
+
+ revs.commits = filter_skipped(revs.commits, &tried, show_all);
+
+ if (!revs.commits && !skip)
+ return 1;
+
+ /*
+ * revs.commits can reach "reaches" commits among
+ * "all" commits. If it is good, then there are
+ * (all-reaches) commits left to be bisected.
+ * On the other hand, if it is bad, then the set
+ * to bisect is "reaches".
+ * A bisect set of size N has (N-1) commits further
+ * to test, as we already know one bad one.
+ */
+ cnt = all - reaches;
+ if (cnt < reaches)
+ cnt = reaches;
+ if (revs.commits)
+ strcpy(hex, sha1_to_hex(revs.commits->item->object.sha1));
+ else
+ hex[0] = '\0';
+
+ if (show_all) {
+ traverse_commit_list(&revs, show_commit, show_object);
+ printf("------\n");
+ }
+
+ if (skip)
+ show_tried(tried);
+ printf("bisect_rev=%s\n"
+ "bisect_nr=%d\n"
+ "bisect_good=%d\n"
+ "bisect_bad=%d\n"
+ "bisect_all=%d\n"
+ "bisect_steps=%d\n",
+ hex,
+ cnt - 1,
+ all - reaches - 1,
+ reaches - 1,
+ all,
+ estimate_bisect_steps(all));
+
+ return 0;
+}
+
int cmd_rev_list(int argc, const char **argv, const char *prefix)
{
struct commit_list *list;
@@ -332,57 +383,13 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
if (bisect_list) {
int reaches = reaches, all = all;
- struct commit_list *tried;
revs.commits = find_bisection(revs.commits, &reaches, &all,
bisect_find_all);
- revs.commits = filter_skipped(revs.commits, &tried,
- bisect_show_all);
-
- if (bisect_show_vars) {
- int cnt;
- char hex[41];
- if (!revs.commits && !bisect_skip)
- return 1;
- /*
- * revs.commits can reach "reaches" commits among
- * "all" commits. If it is good, then there are
- * (all-reaches) commits left to be bisected.
- * On the other hand, if it is bad, then the set
- * to bisect is "reaches".
- * A bisect set of size N has (N-1) commits further
- * to test, as we already know one bad one.
- */
- cnt = all - reaches;
- if (cnt < reaches)
- cnt = reaches;
- if (revs.commits)
- strcpy(hex, sha1_to_hex(revs.commits->item->object.sha1));
- else
- hex[0] = '\0';
-
- if (bisect_show_all) {
- traverse_commit_list(&revs, show_commit, show_object);
- printf("------\n");
- }
-
- if (bisect_skip)
- show_tried(tried);
- printf("bisect_rev=%s\n"
- "bisect_nr=%d\n"
- "bisect_good=%d\n"
- "bisect_bad=%d\n"
- "bisect_all=%d\n"
- "bisect_steps=%d\n",
- hex,
- cnt - 1,
- all - reaches - 1,
- reaches - 1,
- all,
- estimate_bisect_steps(all));
- return 0;
- }
+ if (bisect_show_vars)
+ return show_bisect_vars(reaches, all,
+ bisect_show_all, bisect_skip);
}
traverse_commit_list(&revs,
--
1.6.2.83.g012a16.dirty
^ permalink raw reply related
* [PATCH 7/7] bisect: use "rev-list --bisect-skip" and remove "filter_skipped" function
From: Christian Couder @ 2009-03-12 7:51 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Ingo Molnar, John Tapsell, Johannes Schindelin
Use the new "--bisect-skip" option of "git rev-list" that should be
faster and safer instead of the old "filter_skipped" shell function.
As the output is a little bit different we have to change the code
that interpret the results. But these changes improve code clarity.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
git-bisect.sh | 89 ++++++++------------------------------------------------
1 files changed, 13 insertions(+), 76 deletions(-)
diff --git a/git-bisect.sh b/git-bisect.sh
index e313bde..31e7cff 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -279,76 +279,13 @@ bisect_auto_next() {
bisect_next_check && bisect_next || :
}
-filter_skipped() {
+eval_and_string_together() {
_eval="$1"
- _skip="$2"
-
- if [ -z "$_skip" ]; then
- eval "$_eval" | {
- while read line
- do
- echo "$line &&"
- done
- echo ':'
- }
- return
- fi
- # Let's parse the output of:
- # "git rev-list --bisect-vars --bisect-all ..."
eval "$_eval" | {
- VARS= FOUND= TRIED=
- while read hash line
+ while read line
do
- case "$VARS,$FOUND,$TRIED,$hash" in
- 1,*,*,*)
- # "bisect_foo=bar" read from rev-list output.
- echo "$hash &&"
- ;;
- ,*,*,---*)
- # Separator
- ;;
- ,,,bisect_rev*)
- # We had nothing to search.
- echo "bisect_rev= &&"
- VARS=1
- ;;
- ,,*,bisect_rev*)
- # We did not find a good bisect rev.
- # This should happen only if the "bad"
- # commit is also a "skip" commit.
- echo "bisect_rev='$TRIED' &&"
- VARS=1
- ;;
- ,,*,*)
- # We are searching.
- TRIED="${TRIED:+$TRIED|}$hash"
- case "$_skip" in
- *$hash*) ;;
- *)
- echo "bisect_rev=$hash &&"
- echo "bisect_tried='$TRIED' &&"
- FOUND=1
- ;;
- esac
- ;;
- ,1,*,bisect_rev*)
- # We have already found a rev to be tested.
- VARS=1
- ;;
- ,1,*,*)
- ;;
- *)
- # Unexpected input
- echo "die 'filter_skipped error'"
- die "filter_skipped error " \
- "VARS: '$VARS' " \
- "FOUND: '$FOUND' " \
- "TRIED: '$TRIED' " \
- "hash: '$hash' " \
- "line: '$line'"
- ;;
- esac
+ echo "$line &&"
done
echo ':'
}
@@ -356,10 +293,12 @@ filter_skipped() {
exit_if_skipped_commits () {
_tried=$1
- if expr "$_tried" : ".*[|].*" > /dev/null ; then
+ _bad=$2
+ if test -n "$_tried" ; then
echo "There are only 'skip'ped commit left to test."
echo "The first bad commit could be any of:"
echo "$_tried" | tr '[|]' '[\012]'
+ test -n "$_bad" && echo "$_bad"
echo "We cannot bisect more!"
exit 2
fi
@@ -490,28 +429,26 @@ bisect_next() {
test "$?" -eq "1" && return
# Get bisection information
- BISECT_OPT=''
- test -n "$skip" && BISECT_OPT='--bisect-all'
- eval="git rev-list --bisect-vars $BISECT_OPT $good $bad --" &&
+ skip=$(echo $skip | tr ' ' ',')
+ eval="git rev-list --bisect-skip=$skip $good $bad --" &&
eval="$eval $(cat "$GIT_DIR/BISECT_NAMES")" &&
- eval=$(filter_skipped "$eval" "$skip") &&
+ eval=$(eval_and_string_together "$eval") &&
eval "$eval" || exit
if [ -z "$bisect_rev" ]; then
+ # We should exit here only if the "bad"
+ # commit is also a "skip" commit (see above).
+ exit_if_skipped_commits "$bisect_tried"
echo "$bad was both good and bad"
exit 1
fi
if [ "$bisect_rev" = "$bad" ]; then
- exit_if_skipped_commits "$bisect_tried"
+ exit_if_skipped_commits "$bisect_tried" "$bad"
echo "$bisect_rev is first bad commit"
git diff-tree --pretty $bisect_rev
exit 0
fi
- # We should exit here only if the "bad"
- # commit is also a "skip" commit (see above).
- exit_if_skipped_commits "$bisect_rev"
-
bisect_checkout "$bisect_rev" "$bisect_nr revisions left to test after this (roughly $bisect_steps steps)"
}
--
1.6.2.83.g012a16.dirty
^ permalink raw reply related
* [PATCH 6/7] rev-list: don't find all bisect commits if there are no skipped commits
From: Christian Couder @ 2009-03-12 7:51 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Ingo Molnar, John Tapsell, Johannes Schindelin
This patch optimizes the behavior of the "--bisect-skip" option of
"git rev-list", so that it does not try to find all possible bisection
points when only one is needed because there are no skipped commits.
This makes the behavior of "git rev-list --bisect-skip" similar as
what is done in "git-bisect.sh" to choose if it should pass the
"--bisect-all" option to "git rev-list". So this has the added
benefit that it will make the test suite pass as is when we will
use "--bisect-skip" in "git-bisect.sh" in a later patch.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
bisect-skip.c | 5 +++++
bisect.h | 1 +
builtin-rev-list.c | 4 +++-
3 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/bisect-skip.c b/bisect-skip.c
index 9228465..789ee09 100644
--- a/bisect-skip.c
+++ b/bisect-skip.c
@@ -28,6 +28,11 @@ void register_skipped(const char *skipped)
strbuf_release(&sb);
}
+int skipped_nr(void)
+{
+ return skipped_sha1_nr;
+}
+
static int skipcmp(const void *a, const void *b)
{
return hashcmp(a, b);
diff --git a/bisect.h b/bisect.h
index c5f9fe1..ff9c781 100644
--- a/bisect.h
+++ b/bisect.h
@@ -2,6 +2,7 @@
#define BISECT_H
void register_skipped(const char *skipped);
+int skipped_nr(void);
struct commit_list *filter_skipped(struct commit_list *list,
struct commit_list **tried,
int show_all);
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index 6e0466e..4af70d7 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -337,7 +337,6 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
if (!prefixcmp(arg, "--bisect-skip=")) {
bisect_list = 1;
bisect_show_vars = 1;
- bisect_find_all = 1;
bisect_skip = 1;
register_skipped(arg + 14);
continue;
@@ -384,6 +383,9 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
if (bisect_list) {
int reaches = reaches, all = all;
+ if (bisect_skip && !bisect_find_all)
+ bisect_find_all = !!skipped_nr();
+
revs.commits = find_bisection(revs.commits, &reaches, &all,
bisect_find_all);
--
1.6.2.83.g012a16.dirty
^ permalink raw reply related
* [PATCH JGIT] Allow writeObject() write to OutputStream
From: Daniel Cheng (aka SDiZ) @ 2009-03-12 8:02 UTC (permalink / raw)
To: git; +Cc: Daniel Cheng (aka SDiZ)
Signed-off-by: Daniel Cheng (aka SDiZ) <j16sdiz+freenet@gmail.com>
---
This patch make factor out the object writing code in ObjectWriter,
allow it to write to any OutputStream.
Subclass class may then override
writeObject(final int type, long len, InputStream is, boolean store)
to make it write to alternative locations.
There are some discussion on devl@freenetproject.org to use raw
(uncompressed) object to freenet. This patch allow the testing.
.../src/org/spearce/jgit/lib/ObjectWriter.java | 93 +++++++++++---------
1 files changed, 50 insertions(+), 43 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectWriter.java b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectWriter.java
index 546cc68..97acae4 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectWriter.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectWriter.java
@@ -45,6 +45,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.security.MessageDigest;
import java.util.zip.Deflater;
@@ -297,8 +298,52 @@ public ObjectId computeBlobSha1(final long len, final InputStream is)
return writeObject(Constants.OBJ_BLOB, len, is, false);
}
- ObjectId writeObject(final int type, long len, final InputStream is,
- boolean store) throws IOException {
+ protected ObjectId writeObject(final int type, long len,
+ final InputStream is, final OutputStream deflateStream)
+ throws IOException {
+ md.reset();
+
+ byte[] header;
+ int n;
+
+ header = Constants.encodedTypeString(type);
+ md.update(header);
+ if (deflateStream != null)
+ deflateStream.write(header);
+
+ md.update((byte) ' ');
+ if (deflateStream != null)
+ deflateStream.write((byte) ' ');
+
+ header = Constants.encodeASCII(len);
+ md.update(header);
+ if (deflateStream != null)
+ deflateStream.write(header);
+
+ md.update((byte) 0);
+ if (deflateStream != null)
+ deflateStream.write((byte) 0);
+
+ while (len > 0
+ && (n = is.read(buf, 0, (int) Math.min(len, buf.length))) > 0) {
+ md.update(buf, 0, n);
+ if (deflateStream != null)
+ deflateStream.write(buf, 0, n);
+ len -= n;
+ }
+
+ if (len != 0)
+ throw new IOException("Input did not match supplied length. " + len
+ + " bytes are missing.");
+
+ if (deflateStream != null)
+ deflateStream.close();
+
+ return ObjectId.fromRaw(md.digest());
+ }
+
+ protected ObjectId writeObject(final int type, long len,
+ final InputStream is, boolean store) throws IOException {
final File t;
final DeflaterOutputStream deflateStream;
final FileOutputStream fileStream;
@@ -312,7 +357,6 @@ ObjectId writeObject(final int type, long len, final InputStream is,
fileStream = null;
}
- md.reset();
if (store) {
def.reset();
deflateStream = new DeflaterOutputStream(fileStream, def);
@@ -320,46 +364,9 @@ ObjectId writeObject(final int type, long len, final InputStream is,
deflateStream = null;
try {
- byte[] header;
- int n;
-
- header = Constants.encodedTypeString(type);
- md.update(header);
- if (deflateStream != null)
- deflateStream.write(header);
-
- md.update((byte) ' ');
- if (deflateStream != null)
- deflateStream.write((byte) ' ');
-
- header = Constants.encodeASCII(len);
- md.update(header);
- if (deflateStream != null)
- deflateStream.write(header);
-
- md.update((byte) 0);
- if (deflateStream != null)
- deflateStream.write((byte) 0);
-
- while (len > 0
- && (n = is.read(buf, 0, (int) Math.min(len, buf.length))) > 0) {
- md.update(buf, 0, n);
- if (deflateStream != null)
- deflateStream.write(buf, 0, n);
- len -= n;
- }
-
- if (len != 0)
- throw new IOException("Input did not match supplied length. "
- + len + " bytes are missing.");
-
- if (deflateStream != null ) {
- deflateStream.close();
- if (t != null)
- t.setReadOnly();
- }
-
- id = ObjectId.fromRaw(md.digest());
+ id = writeObject(type, len, is, deflateStream);
+ if (t != null)
+ t.setReadOnly();
} finally {
if (id == null && deflateStream != null) {
try {
--
1.6.2
^ permalink raw reply related
* Re: [PATCH 7/7] bisect: use "rev-list --bisect-skip" and remove "filter_skipped" function
From: Junio C Hamano @ 2009-03-12 8:26 UTC (permalink / raw)
To: Christian Couder; +Cc: git, Ingo Molnar, John Tapsell, Johannes Schindelin
In-Reply-To: <20090312085140.c22cd336.chriscool@tuxfamily.org>
These (except for the first one which I do not think belongs to the
series) look more or less straightforward changes.
One worrysome thing that the series introduces is that you used to hold
all the skipped ones in a shell variable $skip and fed it internally to
the filter_skipped shell function, but now you give them from the command
line. When you have tons of skipped commits, this can easily bust the
command line length limit on some system, while the shell may still be Ok
with such a large string variable.
Because the operations in rev-list related to bisect are very closely tied
to the implementation of the bisect Porcelain anyway, I am wondering if it
makes more sense to just feed the name of the toplevel refname hierarchy,
i.e. "refs/bisect", as a rev-list parameter and let rev-list enumerate
what is skipped, which commits are good and which ones are bad.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox