* Re: merge ignores --no-commit in fast-forward case
From: Björn Steinbrink @ 2009-09-19 8:09 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Tomas Carnecky, git mailing list
In-Reply-To: <7vocpfz4gm.fsf@alter.siamese.dyndns.org>
On 2009.09.13 00:30:49 -0700, Junio C Hamano wrote:
> Tomas Carnecky <tom@dbservice.com> writes:
> > Three possible solutions that I see:
> >
> > 2) Refuse to do anything if user gives --no-commit and merge is fast-
> > forward
> > 3) Document this behavior in the manpage
> > 4) Quietly set deny_non_fast_forward when --no-commit was given
>
> Heh, this is new. People laugh at me when I number my bullets starting
> from zero, like all good computer scientists do ;-)
>
> Seriously, we should at least do #3, and as a backward incompatible change
> at least _consider_ doing #2 (I think #4 is merely an implementation detail
> of #2), and if list reaches concensus in favor of such a change, come up
> with a transition plan and do so in the 1.7.0 release.
Hm, I always treated --no-commit as a way of saying: I think this merge
might cause semantic problems, please let me fix those directly, instead
of having to deal with 'commit --amend' and 'diff HEAD^ HEAD'.
Obviously, in case of a fast-forward such semantic problems aren't to be
expected, and I've just been wrong in my expectations. And then I'm
happy with the fast-forward. I'd _not_ be happy if a merge commit would
be forced (that's what #4 was about, right? deny_non_fast_forward only
appears in builtin-receive-pack.c, so I guess allow_fast_forward=0
was meant...).
#2 would be ok with me, I guess. I expected the wrong thing from the
merge, so git may complain, though it means more typing ;-)
Björn
^ permalink raw reply
* Re: Cygwin git dies silently
From: Clemens Buchacher @ 2009-09-19 8:19 UTC (permalink / raw)
To: John Ousterhout; +Cc: git
In-Reply-To: <A80C2B4F6C34430FA32A24BF94647076@ouster>
On Fri, Sep 18, 2009 at 04:48:42PM -0700, John Ousterhout wrote:
> "echo $?" says that git is exiting with status 53.
Git never returns 53. Googling for exit status 53 turns up some hits [1].
Clemens
[1] http://www.google.com/search?&q=exit+code+53
^ permalink raw reply
* SmartGit, a new GUI front-end for Git
From: Thomas Singer @ 2009-09-19 7:54 UTC (permalink / raw)
To: git
In-Reply-To: <4AB38D64.9010903@syntevo.com>
Hi all,
We would like to announce a new milestone build of our Git client "SmartGit"
(don't be offended by the name, it's historically based) which we feel is
ready now for a broader audience. SmartGit is quite stable and we want to
invite everyone who is interested in giving it a try:
http://www.syntevo.com/smartgit/index.html
Please don't expect all Git features and options implemented. We have
tried to first concentrate on the most important ones - from our rather
novice Git perspective.
SmartGit runs on all operating systems which support a full Java 1.5
implementation, including virtually all Linux versions, OS X 10.4 - 10.6 and
Windows 2000 or newer. It requires a Git installation, although a couple of
time-critical operations are handled by the JGit library.
We appreciate your feed-back in our mailing list
http://www.syntevo.com/smartgit/community.html
or directly to us (smartgit@syntevo.com). SmartGit 1.0 is planned to be
released free of charge for non-commercial use or to active members of the
Open Source community. Each pre-release build expires 3 months after the
build-date.
At this occasion I would also like to express my appreciation to the
community for this great DVCS you have built. Approx. a 3/4 year ago I've
started to use Git. Although I had some starting problems with it using the
Git command line (mostly on Windows), I need to say that over time I really
fell in love with Git and its elaborate foundations and feature set.
--
Best regards,
Thomas Singer
=============
syntevo GmbH
http://www.syntevo.com
http://blog.syntevo.com
^ permalink raw reply
* Re: SmartGit, a new GUI front-end for Git
From: James Sadler @ 2009-09-19 8:58 UTC (permalink / raw)
To: Thomas Singer; +Cc: git
In-Reply-To: <4AB48E25.8020504@syntevo.com>
Hi Thomas,
I just launched SmartGit, and it ate my ~/.gitconfig. Luckily I had a
backup (full of my own aliases and colour settings etc.).
SmartGit replaced mine with a ~/.gitconfig containing _only_ my name
and email settings. Not good. I would bet that 99% of all people on
this list have their own customized version of ~/.gitconfig and
SmartGit is probably going to eat it. If it helps, I am running OS X.
James.
2009/9/19 Thomas Singer <thomas.singer@syntevo.com>:
> Hi all,
>
> We would like to announce a new milestone build of our Git client "SmartGit"
> (don't be offended by the name, it's historically based) which we feel is
> ready now for a broader audience. SmartGit is quite stable and we want to
> invite everyone who is interested in giving it a try:
>
> http://www.syntevo.com/smartgit/index.html
>
> Please don't expect all Git features and options implemented. We have
> tried to first concentrate on the most important ones - from our rather
> novice Git perspective.
>
> SmartGit runs on all operating systems which support a full Java 1.5
> implementation, including virtually all Linux versions, OS X 10.4 - 10.6 and
> Windows 2000 or newer. It requires a Git installation, although a couple of
> time-critical operations are handled by the JGit library.
>
> We appreciate your feed-back in our mailing list
>
> http://www.syntevo.com/smartgit/community.html
>
> or directly to us (smartgit@syntevo.com). SmartGit 1.0 is planned to be
> released free of charge for non-commercial use or to active members of the
> Open Source community. Each pre-release build expires 3 months after the
> build-date.
>
> At this occasion I would also like to express my appreciation to the
> community for this great DVCS you have built. Approx. a 3/4 year ago I've
> started to use Git. Although I had some starting problems with it using the
> Git command line (mostly on Windows), I need to say that over time I really
> fell in love with Git and its elaborate foundations and feature set.
>
> --
> Best regards,
> Thomas Singer
> =============
> syntevo GmbH
> http://www.syntevo.com
> http://blog.syntevo.com
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
James
^ permalink raw reply
* Re: SmartGit, a new GUI front-end for Git
From: Jakub Narebski @ 2009-09-19 8:54 UTC (permalink / raw)
To: Thomas Singer; +Cc: git
In-Reply-To: <4AB48E25.8020504@syntevo.com>
Thomas Singer <thomas.singer@syntevo.com> writes:
> We would like to announce a new milestone build of our Git client "SmartGit"
> (don't be offended by the name, it's historically based) which we feel is
> ready now for a broader audience. SmartGit is quite stable and we want to
> invite everyone who is interested in giving it a try:
>
> http://www.syntevo.com/smartgit/index.html
>
> Please don't expect all Git features and options implemented. We have
> tried to first concentrate on the most important ones - from our rather
> novice Git perspective.
[...]
Could you please add information about this Git client (Git GUI?)
to the http://git.or.cz/gitwiki/InterfacesFrontendsAndTools wiki
page?
Thanks in advance.
--
Jakub Narebski
Poland
ShadeHawk on #git
^ permalink raw reply
* Re: SmartGit, a new GUI front-end for Git
From: Thomas Singer @ 2009-09-19 9:54 UTC (permalink / raw)
To: git
In-Reply-To: <e5e204700909190158y48b9c162ncea29f4b1635dc18@mail.gmail.com>
Hi James,
Thanks for reporting this serious error. I will try to fix this in the next
hour and upload a new build.
--
Best regards,
Thomas Singer
=============
syntevo GmbH
http://www.syntevo.com
http://blog.syntevo.com
James Sadler wrote:
> Hi Thomas,
>
> I just launched SmartGit, and it ate my ~/.gitconfig. Luckily I had a
> backup (full of my own aliases and colour settings etc.).
>
> SmartGit replaced mine with a ~/.gitconfig containing _only_ my name
> and email settings. Not good. I would bet that 99% of all people on
> this list have their own customized version of ~/.gitconfig and
> SmartGit is probably going to eat it. If it helps, I am running OS X.
>
> James.
>
> 2009/9/19 Thomas Singer <thomas.singer@syntevo.com>:
>> Hi all,
>>
>> We would like to announce a new milestone build of our Git client "SmartGit"
>> (don't be offended by the name, it's historically based) which we feel is
>> ready now for a broader audience. SmartGit is quite stable and we want to
>> invite everyone who is interested in giving it a try:
>>
>> http://www.syntevo.com/smartgit/index.html
>>
>> Please don't expect all Git features and options implemented. We have
>> tried to first concentrate on the most important ones - from our rather
>> novice Git perspective.
>>
>> SmartGit runs on all operating systems which support a full Java 1.5
>> implementation, including virtually all Linux versions, OS X 10.4 - 10.6 and
>> Windows 2000 or newer. It requires a Git installation, although a couple of
>> time-critical operations are handled by the JGit library.
>>
>> We appreciate your feed-back in our mailing list
>>
>> http://www.syntevo.com/smartgit/community.html
>>
>> or directly to us (smartgit@syntevo.com). SmartGit 1.0 is planned to be
>> released free of charge for non-commercial use or to active members of the
>> Open Source community. Each pre-release build expires 3 months after the
>> build-date.
>>
>> At this occasion I would also like to express my appreciation to the
>> community for this great DVCS you have built. Approx. a 3/4 year ago I've
>> started to use Git. Although I had some starting problems with it using the
>> Git command line (mostly on Windows), I need to say that over time I really
>> fell in love with Git and its elaborate foundations and feature set.
>>
>> --
>> Best regards,
>> Thomas Singer
>> =============
>> syntevo GmbH
>> http://www.syntevo.com
>> http://blog.syntevo.com
>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe git" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
>
>
>
^ permalink raw reply
* [PATCHv3] git-log --format: Add %B tag with %B(x) option
From: Johannes Gilger @ 2009-09-19 9:58 UTC (permalink / raw)
To: Git Mailing List; +Cc: Junio C Hamano, Johannes Schindelin, Johannes Gilger
In-Reply-To: <7vtyz083tk.fsf@alter.siamese.dyndns.org>
Since one can simply use spaces to indent any other --pretty field we
should have an option to do that with the body too.
Also the %B flag strips the trailing newlines, to enable more compact
display.
Signed-off-by: Johannes Gilger <heipei@hackvalue.de>
---
Changes to PATCHv2:
- Make %B() strict: Only nonnegative integers are allowed between the brackets,
everything else yields the placemark itself as output to indicate a wrong
argument. This also goes for an empty argument.
Documentation/pretty-formats.txt | 2 ++
pretty.c | 29 ++++++++++++++++++++++++-----
2 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index 2a845b1..533bc5e 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -123,6 +123,8 @@ The placeholders are:
- '%s': subject
- '%f': sanitized subject line, suitable for a filename
- '%b': body
+- '%B': body without trailing newline
+- '%B(x)': body indented by x spaces
- '%Cred': switch color to red
- '%Cgreen': switch color to green
- '%Cblue': switch color to blue
diff --git a/pretty.c b/pretty.c
index f5983f8..8970378 100644
--- a/pretty.c
+++ b/pretty.c
@@ -605,13 +605,17 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
int h1, h2;
/* these are independent of the commit */
+
+ const char *body = msg + c->body_off;
+ const char *end = NULL;
+ /* check if we have arguments to the placeholder */
+ if (placeholder[1] == '(')
+ end = strchr(placeholder + 2, ')');
+
switch (placeholder[0]) {
case 'C':
- if (placeholder[1] == '(') {
- const char *end = strchr(placeholder + 2, ')');
+ if (end) {
char color[COLOR_MAXLEN];
- if (!end)
- return 0;
color_parse_mem(placeholder + 2,
end - (placeholder + 2),
"--pretty format", color);
@@ -733,7 +737,20 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
format_sanitized_subject(sb, msg + c->subject_off);
return 1;
case 'b': /* body */
- strbuf_addstr(sb, msg + c->body_off);
+ strbuf_addstr(sb, body);
+ return 1;
+ case 'B': /* body without trailing newline */
+ if (end) {
+ char *endp = NULL;
+ int indent = strtol(placeholder + 2, &endp, 10);
+ if (placeholder + 2 == endp || *endp != ')' || indent < 0)
+ return 0;
+ pp_remainder(CMIT_FMT_MEDIUM, &body, sb, indent);
+ strbuf_rtrim(sb);
+ return end - placeholder + 1;
+ }
+ strbuf_addstr(sb, body);
+ strbuf_rtrim(sb);
return 1;
}
return 0; /* unknown placeholder */
@@ -875,6 +892,8 @@ void pp_remainder(enum cmit_fmt fmt,
}
first = 0;
+ if (indent < 0)
+ indent = 0;
strbuf_grow(sb, linelen + indent + 20);
if (indent) {
memset(sb->buf + sb->len, ' ', indent);
--
1.6.5.rc1.20.geb7d9
^ permalink raw reply related
* Re: SmartGit, a new GUI front-end for Git
From: Thomas Singer @ 2009-09-19 14:11 UTC (permalink / raw)
To: git
In-Reply-To: <4AB4AA4A.4080801@syntevo.com>
Hi all,
The new build is uploaded. The ~/.gitconfig file now should be kept and on
Linux the splash screen hides before showing the initial dialog. Sorry for
any inconveniences.
--
Best regards,
Thomas Singer
=============
syntevo GmbH
http://www.syntevo.com
http://blog.syntevo.com
Thomas Singer wrote:
> Hi James,
>
> Thanks for reporting this serious error. I will try to fix this in the next
> hour and upload a new build.
>
> --
> Best regards,
> Thomas Singer
> =============
> syntevo GmbH
> http://www.syntevo.com
> http://blog.syntevo.com
>
>
> James Sadler wrote:
>> Hi Thomas,
>>
>> I just launched SmartGit, and it ate my ~/.gitconfig. Luckily I had a
>> backup (full of my own aliases and colour settings etc.).
>>
>> SmartGit replaced mine with a ~/.gitconfig containing _only_ my name
>> and email settings. Not good. I would bet that 99% of all people on
>> this list have their own customized version of ~/.gitconfig and
>> SmartGit is probably going to eat it. If it helps, I am running OS X.
>>
>> James.
>>
>> 2009/9/19 Thomas Singer <thomas.singer@syntevo.com>:
>>> Hi all,
>>>
>>> We would like to announce a new milestone build of our Git client "SmartGit"
>>> (don't be offended by the name, it's historically based) which we feel is
>>> ready now for a broader audience. SmartGit is quite stable and we want to
>>> invite everyone who is interested in giving it a try:
>>>
>>> http://www.syntevo.com/smartgit/index.html
>>>
>>> Please don't expect all Git features and options implemented. We have
>>> tried to first concentrate on the most important ones - from our rather
>>> novice Git perspective.
>>>
>>> SmartGit runs on all operating systems which support a full Java 1.5
>>> implementation, including virtually all Linux versions, OS X 10.4 - 10.6 and
>>> Windows 2000 or newer. It requires a Git installation, although a couple of
>>> time-critical operations are handled by the JGit library.
>>>
>>> We appreciate your feed-back in our mailing list
>>>
>>> http://www.syntevo.com/smartgit/community.html
>>>
>>> or directly to us (smartgit@syntevo.com). SmartGit 1.0 is planned to be
>>> released free of charge for non-commercial use or to active members of the
>>> Open Source community. Each pre-release build expires 3 months after the
>>> build-date.
>>>
>>> At this occasion I would also like to express my appreciation to the
>>> community for this great DVCS you have built. Approx. a 3/4 year ago I've
>>> started to use Git. Although I had some starting problems with it using the
>>> Git command line (mostly on Windows), I need to say that over time I really
>>> fell in love with Git and its elaborate foundations and feature set.
>>>
>>> --
>>> Best regards,
>>> Thomas Singer
>>> =============
>>> syntevo GmbH
>>> http://www.syntevo.com
>>> http://blog.syntevo.com
>>>
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe git" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>
>>
>>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>
^ permalink raw reply
* Re: How to host a github?
From: daicoden @ 2009-09-19 21:01 UTC (permalink / raw)
To: git
In-Reply-To: <24713161.post@talk.nabble.com>
jvsrvcs wrote:
>
> I want to share code with a few co-workers and I want to use git.
>
> I installed git (cygwin), created a /project/ and then $cd project
> and then $git init
>
> I have found so much documentation as to what to do next, that
> I'm confused.
>
> Do I have to create an account on github in order to share code with
> a few local developers?
>
> Could I run some sort of server on my laptop in order to share code?
> (we only need to share during office hours). Basically I just
> want to share code but do not want to sign up for an account
> on github.
>
> How do I work this?
>
> thanks
>
> jvsrvcs
>
Hey, assuming you have shell access into your laptop, create a user named
git. You don't have to do this but you want to give everyone access to an
account on the laptop. You could also create a usergroup and add the
project folder to that group and give all your developers access to that
group.
Either-way once everyone is able to log onto the laptop make a new directory
called project.git. Then go into that directory and use git --bare init.
Assuming you created a user named git you can then check the code out via
git clone git@localhost:project.git
to start things off from the source you will be working on you can then use:
git init
touch 'Readme'
git add Readme
git commit -m 'Initial Comit'
git remote add origin git@ip:project.git
git push origin master
--
View this message in context: http://www.nabble.com/How-to-host-a-github--tp24713161p25525401.html
Sent from the git mailing list archive at Nabble.com.
^ permalink raw reply
* shell commands in ReleaseNotes
From: Resul Cetin @ 2009-09-19 21:57 UTC (permalink / raw)
To: git
Hi,
I noticed that there are small part of commands at the end of a not yet
released ReleaseNote-*.txt.
---
exec >/var/tmp/1
O=v1.6.4.1-266-g235db15
echo O=$(git describe master)
git shortlog --no-merges $O..master --not maint
As far as I understand it means that the output is redirected to /var/tmp/1.
Then there is O set to the last it which was used to generate a shortlog.
Then the current desciption (tag+suffix) is printed which can then used to
replace the O= line in the small snipped. Then there will be created a
shortlog from the last point it was created until master without stuff in
maint (or reachable by maint? I am not sure about that one).
Real nice idea to create an overview about changes in a repository for writing
a releasenotes. But how is it real used by the maintainer? My current idea
would be: Open the editor an copy the snipped. Open a terminal, switch to the
repository and go paste the snipped into it. After that the terminal has to be
closed as it isn't really useful anymore. An extra editor will be used to open
/var/tmp/1 and now the first step is to replace "O=v1.6.4.1-266-g235db15" with
a new id at the first line in /var/tmp/1. Now the maintainer has to order all
commits a little bit and write the release notes. After he finished it, he
just commits it to master and is finished for this period of time.
Is this real how it is done in git.git or is there maybe something I don't see
right now?
Best regards,
Resul Cetin
^ permalink raw reply
* Re: shell commands in ReleaseNotes
From: Junio C Hamano @ 2009-09-19 22:30 UTC (permalink / raw)
To: Resul Cetin; +Cc: git
In-Reply-To: <200909192357.32369.Resul-Cetin@gmx.net>
Resul Cetin <Resul-Cetin@gmx.net> writes:
> Real nice idea to create an overview about changes in a repository for writing
> a releasenotes. But how is it real used by the maintainer?
Open the file, go to the beginning of the scriptlet and mark (\C-SP), go
to the end (\M->), feed it to shell (\M-| sh RET), open /var/tmp/1 and
read it over while cutting the updated definition of O=.
Everything done in Emacs, no need for any extra editor.
^ permalink raw reply
* Re: shell commands in ReleaseNotes
From: Resul Cetin @ 2009-09-19 22:40 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7veiq27ekz.fsf@alter.siamese.dyndns.org>
> Resul Cetin <Resul-Cetin@gmx.net> writes:
> > Real nice idea to create an overview about changes in a repository for
> > writing a releasenotes. But how is it real used by the maintainer?
>
> Open the file, go to the beginning of the scriptlet and mark (\C-SP), go
> to the end (\M->), feed it to shell (\M-| sh RET), open /var/tmp/1 and
> read it over while cutting the updated definition of O=.
>
> Everything done in Emacs, no need for any extra editor.
Ah, thanks. Looks like a good workflow.
^ permalink raw reply
* Release candidate period
From: Thiago Farina @ 2009-09-19 23:44 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
Hi Junio, I saw that you committed two of my trivial patches with your changes.
Thank you for committing my patches.
I have one more trivial patch that I want to send, but we are in -rc
freeze, when I can send it?
The release candidate period is not defined, no? The period ends so
when the mailing list reaches an agreement and agrees that the release
candidate is ready?
Thanks!
^ permalink raw reply
* Re: Release candidate period
From: Nicolas Pitre @ 2009-09-20 0:56 UTC (permalink / raw)
To: Thiago Farina; +Cc: git, Junio C Hamano
In-Reply-To: <a4c8a6d00909191644n131667f2uc7e59d0d56749c42@mail.gmail.com>
On Sat, 19 Sep 2009, Thiago Farina wrote:
> Hi Junio, I saw that you committed two of my trivial patches with your changes.
>
> Thank you for committing my patches.
>
> I have one more trivial patch that I want to send, but we are in -rc
> freeze, when I can send it?
> The release candidate period is not defined, no? The period ends so
> when the mailing list reaches an agreement and agrees that the release
> candidate is ready?
This is a benevolent dictatorship. Junio sets the date.
Nicolas
^ permalink raw reply
* Re: Release candidate period
From: Junio C Hamano @ 2009-09-20 1:17 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: Thiago Farina, git, Junio C Hamano
In-Reply-To: <alpine.LFD.2.00.0909192043060.24133@xanadu.home>
Nicolas Pitre <nico@fluxnic.net> writes:
> On Sat, 19 Sep 2009, Thiago Farina wrote:
>
>> Hi Junio, I saw that you committed two of my trivial patches with your changes.
>>
>> Thank you for committing my patches.
>>
>> I have one more trivial patch that I want to send, but we are in -rc
>> freeze, when I can send it?
>> The release candidate period is not defined, no? The period ends so
>> when the mailing list reaches an agreement and agrees that the release
>> candidate is ready?
>
> This is a benevolent dictatorship. Junio sets the date.
True.
And Thiago, don't thank me. It's not "hey I now have N commits in a high
profile project" game. We are all working together to make it better, and
we thank you for your attention of detail.
^ permalink raw reply
* Re: Release candidate period
From: Thiago Farina @ 2009-09-20 1:31 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Nicolas Pitre, git
In-Reply-To: <7vab0q76tq.fsf@alter.siamese.dyndns.org>
On Sat, Sep 19, 2009 at 10:17 PM, Junio C Hamano <gitster@pobox.com> wrote:
> And Thiago, don't thank me. It's not "hey I now have N commits in a high
> profile project" game.
OK, I will remember that.
^ permalink raw reply
* Re: Usability question
From: Rob Barrett @ 2009-09-20 2:21 UTC (permalink / raw)
To: Matthieu Moy; +Cc: git
In-Reply-To: <vpqy6odhn0d.fsf@bauges.imag.fr>
On Thu, Sep 17, 2009 at 8:41 PM, Matthieu Moy
<Matthieu.Moy@grenoble-inp.fr> wrote:
> Well, if you want to get rid of subcommands, why not get rid of
> commands, too?
>
> git --commit
> git --status
> git --svn --rebase
>
Well, granted, that's a sort of heavyweight consistency, but all we
should need to do is to help reduce a _new_ user's confusion about
when the word after a subcommand gets a '--' prefix and when it
doesn't.
And do it in a way that's backwards compatible so it doesn't affect
the usage patterns of seasoned users, existing scripts, crons etc.
Will patch and see how it looks..
Rob
^ permalink raw reply
* [WIP PATCH 0/6] Merging with D/F conflicts
From: Junio C Hamano @ 2009-09-20 5:06 UTC (permalink / raw)
To: git
I have been working on this on-and-off and it still is not finished, but I
thought it would be a good place to stop, especially since this will not
be part of the upcoming 1.6.5 anyway.
The first three patches are preparatory clean-ups.
The fourth patch roughly corresponds to Linus's 880386c (Prepare
'traverse_trees()' for D/F conflict lookahead, 2009-09-06), but it does
implement multi-entry lookahead. It reveals why lookahead on the tree
side alone is not sufficient by breaking a few tests.
The fifth one starts to compensate for the change in the tree side by
preparing the side that walks the index for a similar lookahead mechanism,
but it does not actually implement the lookahead yet.
The last one is a debugging patch.
This change has to break the output order (but not content) of the
diff-index somewhat. If you had this:
Index Tree
b b-2/c
b-2 b/d
the expected output order from diff-index is b, b-2, b-2/c, then b/d. But
if you walk the tree and the index in parallel, we would end up showing b,
b/d, b-2 and then b-2/c. A sad part of the story is that diff-index
always emits D/F conflicted entries as two independent records, so it is
rather a bad match to the unpack_trees() framework to begin with.
The patches are designed to apply on 79b4fde (Merge branch 'maint',
2009-09-03).
Junio C Hamano (6):
diff-lib.c: fix misleading comments on oneway_diff()
unpack-trees: typofix
unpack_callback(): use unpack_failed() consistently
traverse_trees(): handle D/F conflict case sanely
unpack-trees.c: prepare for looking ahead in the index
read-tree --debug-unpack
builtin-read-tree.c | 36 +++++++
cache.h | 2 +
diff-lib.c | 20 +----
tree-walk.c | 277 +++++++++++++++++++++++++++++++++++++++++++--------
unpack-trees.c | 275 ++++++++++++++++++++++++++++++++++++++------------
unpack-trees.h | 3 +-
6 files changed, 484 insertions(+), 129 deletions(-)
^ permalink raw reply
* [WIP PATCH 2/6] unpack-trees: typofix
From: Junio C Hamano @ 2009-09-20 5:06 UTC (permalink / raw)
To: git
In-Reply-To: <1253423175-6339-1-git-send-email-gitster@pobox.com>
I am not good at subject-verb concordance.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
unpack-trees.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/unpack-trees.c b/unpack-trees.c
index 720f7a1..d174fe0 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -617,7 +617,7 @@ static int verify_absent(struct cache_entry *ce, const char *action,
* found "foo/." in the working tree.
* This is tricky -- if we have modified
* files that are in "foo/" we would lose
- * it.
+ * them.
*/
ret = verify_clean_subdirectory(ce, action, o);
if (ret < 0)
--
1.6.5.rc1.90.ga3b1b
^ permalink raw reply related
* [WIP PATCH 1/6] diff-lib.c: fix misleading comments on oneway_diff()
From: Junio C Hamano @ 2009-09-20 5:06 UTC (permalink / raw)
To: git
In-Reply-To: <1253423175-6339-1-git-send-email-gitster@pobox.com>
20a16eb (unpack_trees(): fix diff-index regression., 2008-03-10) adjusted
diff-index to the new world order since 34110cd (Make 'unpack_trees()'
have a separate source and destination index, 2008-03-06). Callbacks are
expected to return anything non-negative as "success", and instead of
reporting how many index entries they have processed, they are expected to
advance o->pos themselves. The code did so, but a stale comment was left
behind.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
diff-lib.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/diff-lib.c b/diff-lib.c
index 0c74ef5..adf1c5f 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -383,7 +383,7 @@ static inline void skip_same_name(struct cache_entry *ce, struct unpack_trees_op
* For diffing, the index is more important, and we only have a
* single tree.
*
- * We're supposed to return how many index entries we want to skip.
+ * We're supposed to advance o->pos to skip what we have already processed.
*
* This wrapper makes it all more readable, and takes care of all
* the fairly complex unpack_trees() semantic requirements, including
--
1.6.5.rc1.90.ga3b1b
^ permalink raw reply related
* [WIP PATCH 3/6] unpack_callback(): use unpack_failed() consistently
From: Junio C Hamano @ 2009-09-20 5:06 UTC (permalink / raw)
To: git
In-Reply-To: <1253423175-6339-1-git-send-email-gitster@pobox.com>
When unpack_index_entry() failed, consistently call unpack_failed(),
instead of silently returning -1.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
unpack-trees.c | 24 ++++++++++++------------
1 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/unpack-trees.c b/unpack-trees.c
index d174fe0..c424bab 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -277,6 +277,17 @@ static int unpack_nondirectories(int n, unsigned long mask,
return 0;
}
+static int unpack_failed(struct unpack_trees_options *o, const char *message)
+{
+ discard_index(&o->result);
+ if (!o->gently) {
+ if (message)
+ return error("%s", message);
+ return -1;
+ }
+ return -1;
+}
+
static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, struct name_entry *names, struct traverse_info *info)
{
struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, };
@@ -294,7 +305,7 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
int cmp = compare_entry(ce, info, p);
if (cmp < 0) {
if (unpack_index_entry(ce, o) < 0)
- return -1;
+ return unpack_failed(o, NULL);
continue;
}
if (!cmp) {
@@ -352,17 +363,6 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
return mask;
}
-static int unpack_failed(struct unpack_trees_options *o, const char *message)
-{
- discard_index(&o->result);
- if (!o->gently) {
- if (message)
- return error("%s", message);
- return -1;
- }
- return -1;
-}
-
/*
* N-way merge "len" trees. Returns 0 on success, -1 on failure to manipulate the
* resulting index, -2 on failure to reflect the changes to the work tree.
--
1.6.5.rc1.90.ga3b1b
^ permalink raw reply related
* [WIP PATCH 4/6] traverse_trees(): handle D/F conflict case sanely
From: Junio C Hamano @ 2009-09-20 5:06 UTC (permalink / raw)
To: git
In-Reply-To: <1253423175-6339-1-git-send-email-gitster@pobox.com>
traverse_trees() is supposed to call its callback with all the matching
entries from the given trees. The current algorithm keeps a pointer to
each of the tree being traversed, and feeds the entry with the earliest
name to the callback.
This breaks down if the trees being traversed looks like this:
A B
t-1 t
t-2 u
t/a v
When we are currently looking at an entry "t-1" in tree A, and tree B has
returned "t", feeding "t" from the B and not feeding anything from A, only
because "t-1" sorts later than "t", will miss an entry for a subtree "t"
behind the current entry in tree A.
This introduces extended_entry_extract() helper function that gives what
name is expected from the tree, and implements a mechanism to look-ahead
in the tree object using it, to make sure such a case is handled sanely.
Traversal in tree A in the above example will first return "t" to match
that of B, and then the next request for an entry to A then returns "t-1".
This roughly corresponds to what Linus's "prepare for one-entry lookahead"
wanted to do, but because this does implement look ahead, t6035 and t7003
reveal that the approach would not work without adjusting the side that
walks the index in unpack_trees() as well.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
tree-walk.c | 277 +++++++++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 234 insertions(+), 43 deletions(-)
diff --git a/tree-walk.c b/tree-walk.c
index 02e2aed..08796c2 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -60,13 +60,6 @@ void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1)
return buf;
}
-static int entry_compare(struct name_entry *a, struct name_entry *b)
-{
- return df_name_compare(
- a->path, tree_entry_len(a->path, a->sha1), a->mode,
- b->path, tree_entry_len(b->path, b->sha1), b->mode);
-}
-
static void entry_clear(struct name_entry *a)
{
memset(a, 0, sizeof(*a));
@@ -138,66 +131,264 @@ char *make_traverse_path(char *path, const struct traverse_info *info, const str
return path;
}
+struct tree_desc_skip {
+ struct tree_desc_skip *prev;
+ const void *ptr;
+};
+
+struct tree_desc_x {
+ struct tree_desc d;
+ struct tree_desc_skip *skip;
+};
+
+static int name_compare(const char *a, int a_len,
+ const char *b, int b_len)
+{
+ int len = (a_len < b_len) ? a_len : b_len;
+ int cmp = memcmp(a, b, len);
+ if (cmp)
+ return cmp;
+ return (a_len - b_len);
+}
+
+static int check_entry_match(const char *a, int a_len, const char *b, int b_len)
+{
+ /*
+ * The caller wants to pick *a* from a tree or nothing.
+ * We are looking at *b* in a tree.
+ *
+ * (0) If a and b are the same name, we are trivially happy.
+ *
+ * There are three possibilities where *a* could be hiding
+ * behind *b*.
+ *
+ * (1) *a* == "t", *b* == "ab" i.e. *b* sorts earlier than *a* no
+ * matter what.
+ * (2) *a* == "t", *b* == "t-2" and "t" is a subtree in the tree;
+ * (3) *a* == "t-2", *b* == "t" and "t-2" is a blob in the tree.
+ *
+ * Otherwise we know *a* won't appear in the tree without
+ * scanning further.
+ */
+
+ int cmp = name_compare(a, a_len, b, b_len);
+
+ /* Most common case first -- reading sync'd trees */
+ if (!cmp)
+ return cmp;
+
+ if (0 < cmp) {
+ /* a comes after b; it does not matter if it is case (3)
+ if (b_len < a_len && !memcmp(a, b, b_len) && a[b_len] < '/')
+ return 1;
+ */
+ return 1; /* keep looking */
+ }
+
+ /* b comes after a; are we looking at case (2)? */
+ if (a_len < b_len && !memcmp(a, b, a_len) && b[a_len] < '/')
+ return 1; /* keep looking */
+
+ return -1; /* a cannot appear in the tree */
+}
+
+/*
+ * From the extended tree_desc, extract the first name entry, while
+ * paying attention to the candidate "first" name. Most importantly,
+ * when looking for an entry, if there are entries that sorts earlier
+ * in the tree object representation than that name, skip them and
+ * process the named entry first. We will remember that we haven't
+ * processed the first entry yet, and in the later call skip the
+ * entry we processed early when update_extended_entry() is called.
+ *
+ * E.g. if the underlying tree object has these entries:
+ *
+ * blob "t-1"
+ * blob "t-2"
+ * tree "t"
+ * blob "t=1"
+ *
+ * and the "first" asks for "t", remember that we still need to
+ * process "t-1" and "t-2" but extract "t". After processing the
+ * entry "t" from this call, the caller will let us know by calling
+ * update_extended_entry() that we can remember "t" has been processed
+ * already.
+ */
+
+static void extended_entry_extract(struct tree_desc_x *t,
+ struct name_entry *a,
+ const char *first,
+ int first_len)
+{
+ const char *path;
+ int len;
+ struct tree_desc probe;
+ struct tree_desc_skip *skip;
+
+ /*
+ * Extract the first entry from the tree_desc, but skip the
+ * ones that we already returned in earlier rounds.
+ */
+ while (1) {
+ if (!t->d.size) {
+ entry_clear(a);
+ break; /* not found */
+ }
+ entry_extract(&t->d, a);
+ for (skip = t->skip; skip; skip = skip->prev)
+ if (a->path == skip->ptr)
+ break; /* found */
+ if (!skip)
+ break;
+ /* We have processed this entry already. */
+ update_tree_entry(&t->d);
+ }
+
+ if (!first || !a->path)
+ return;
+
+ /*
+ * The caller wants "first" from this tree, or nothing.
+ */
+ path = a->path;
+ len = tree_entry_len(a->path, a->sha1);
+ switch (check_entry_match(first, first_len, path, len)) {
+ case -1:
+ entry_clear(a);
+ case 0:
+ return;
+ default:
+ break;
+ }
+
+ /*
+ * We need to look-ahead -- we suspect that a subtree whose
+ * name is "first" may be hiding behind the current entry "path".
+ */
+ probe = t->d;
+ while (probe.size) {
+ entry_extract(&probe, a);
+ path = a->path;
+ len = tree_entry_len(a->path, a->sha1);
+ switch (check_entry_match(first, first_len, path, len)) {
+ case -1:
+ entry_clear(a);
+ case 0:
+ return;
+ default:
+ update_tree_entry(&probe);
+ break;
+ }
+ /* keep looking */
+ }
+ entry_clear(a);
+}
+
+static void update_extended_entry(struct tree_desc_x *t, struct name_entry *a)
+{
+ if (t->d.entry.path == a->path) {
+ update_tree_entry(&t->d);
+ } else {
+ /* we have returned this entry early */
+ struct tree_desc_skip *skip = xmalloc(sizeof(*skip));
+ skip->ptr = a->path;
+ skip->prev = t->skip;
+ t->skip = skip;
+ }
+}
+
+static void free_extended_entry(struct tree_desc_x *t)
+{
+ struct tree_desc_skip *p, *s;
+
+ for (s = t->skip; s; s = p) {
+ p = s->prev;
+ free(s);
+ }
+}
+
int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
{
int ret = 0;
struct name_entry *entry = xmalloc(n*sizeof(*entry));
+ int i;
+ struct tree_desc_x *tx = xcalloc(n, sizeof(*tx));
+
+ for (i = 0; i < n; i++)
+ tx[i].d = t[i];
for (;;) {
- unsigned long mask = 0;
- unsigned long dirmask = 0;
- int i, last;
+ unsigned long mask, dirmask;
+ const char *first = NULL;
+ int first_len = 0;
+ struct name_entry *e;
+ int len;
- last = -1;
for (i = 0; i < n; i++) {
- if (!t[i].size)
+ e = entry + i;
+ extended_entry_extract(tx + i, e, NULL, 0);
+ }
+
+ /*
+ * A tree may have "t-2" at the current location even
+ * though it may have "t" that is a subtree behind it,
+ * and another tree may return "t". We want to grab
+ * all "t" from all trees to match in such a case.
+ */
+ for (i = 0; i < n; i++) {
+ e = entry + i;
+ if (!e->path)
continue;
- entry_extract(t+i, entry+i);
- if (last >= 0) {
- int cmp = entry_compare(entry+i, entry+last);
-
- /*
- * Is the new name bigger than the old one?
- * Ignore it
- */
- if (cmp > 0)
+ len = tree_entry_len(e->path, e->sha1);
+ if (!first) {
+ first = e->path;
+ first_len = len;
+ continue;
+ }
+ if (name_compare(e->path, len, first, first_len) < 0) {
+ first = e->path;
+ first_len = len;
+ }
+ }
+
+ if (first) {
+ for (i = 0; i < n; i++) {
+ e = entry + i;
+ extended_entry_extract(tx + i, e, first, first_len);
+ /* Cull the ones that are not the earliest */
+ if (!e->path)
continue;
- /*
- * Is the new name smaller than the old one?
- * Ignore all old ones
- */
- if (cmp < 0)
- mask = 0;
+ len = tree_entry_len(e->path, e->sha1);
+ if (name_compare(e->path, len, first, first_len))
+ entry_clear(e);
}
+ }
+
+ /* Now we have in entry[i] the earliest name from the trees */
+ mask = 0;
+ dirmask = 0;
+ for (i = 0; i < n; i++) {
+ if (!entry[i].path)
+ continue;
mask |= 1ul << i;
if (S_ISDIR(entry[i].mode))
dirmask |= 1ul << i;
- last = i;
}
if (!mask)
break;
- dirmask &= mask;
-
- /*
- * Clear all the unused name-entries.
- */
- for (i = 0; i < n; i++) {
- if (mask & (1ul << i))
- continue;
- entry_clear(entry + i);
- }
ret = info->fn(n, mask, dirmask, entry, info);
if (ret < 0)
break;
- if (ret)
- mask &= ret;
+ mask &= ret;
ret = 0;
- for (i = 0; i < n; i++) {
+ for (i = 0; i < n; i++)
if (mask & (1ul << i))
- update_tree_entry(t + i);
- }
+ update_extended_entry(tx + i, entry + i);
}
free(entry);
+ for (i = 0; i < n; i++)
+ free_extended_entry(tx + i);
+ free(tx);
return ret;
}
--
1.6.5.rc1.90.ga3b1b
^ permalink raw reply related
* [WIP PATCH 6/6] read-tree --debug-unpack
From: Junio C Hamano @ 2009-09-20 5:06 UTC (permalink / raw)
To: git
In-Reply-To: <1253423175-6339-1-git-send-email-gitster@pobox.com>
Debugging patch.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
builtin-read-tree.c | 36 ++++++++++++++++++++++++++++++++++++
unpack-trees.c | 35 +++++++++++++++++++++++++++++++++++
unpack-trees.h | 1 +
3 files changed, 72 insertions(+), 0 deletions(-)
diff --git a/builtin-read-tree.c b/builtin-read-tree.c
index 14c836b..a9788e5 100644
--- a/builtin-read-tree.c
+++ b/builtin-read-tree.c
@@ -64,6 +64,34 @@ static int exclude_per_directory_cb(const struct option *opt, const char *arg,
return 0;
}
+static void debug_stage(const char *label, struct cache_entry *ce,
+ struct unpack_trees_options *o)
+{
+ printf("%s ", label);
+ if (!ce)
+ printf("(missing)\n");
+ else if (ce == o->df_conflict_entry)
+ printf("(conflict)\n");
+ else
+ printf("%06o #%d %s %.8s\n",
+ ce->ce_mode, ce_stage(ce), ce->name,
+ sha1_to_hex(ce->sha1));
+}
+
+static int debug_merge(struct cache_entry **stages, struct unpack_trees_options *o)
+{
+ int i;
+
+ printf("* %d-way merge\n", o->merge_size);
+ debug_stage("index", stages[0], o);
+ for (i = 1; i <= o->merge_size; i++) {
+ char buf[24];
+ sprintf(buf, "ent#%d", i);
+ debug_stage(buf, stages[i], o);
+ }
+ return 0;
+}
+
static struct lock_file lock_file;
int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
@@ -98,6 +126,8 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
PARSE_OPT_NONEG, exclude_per_directory_cb },
OPT_SET_INT('i', NULL, &opts.index_only,
"don't check the working tree after merging", 1),
+ OPT_SET_INT(0, "debug-unpack", &opts.debug_unpack,
+ "debug unpack-trees", 1),
OPT_END()
};
@@ -165,6 +195,9 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
opts.head_idx = 1;
}
+ if (opts.debug_unpack)
+ opts.fn = debug_merge;
+
cache_tree_free(&active_cache_tree);
for (i = 0; i < nr_trees; i++) {
struct tree *tree = trees[i];
@@ -174,6 +207,9 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
if (unpack_trees(nr_trees, t, &opts))
return 128;
+ if (opts.debug_unpack)
+ return 0; /* do not write the index out */
+
/*
* When reading only one tree (either the most basic form,
* "-m ent" or "--reset ent" form), we can obtain a fully
diff --git a/unpack-trees.c b/unpack-trees.c
index a6f2187..b1ad2d9 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -393,6 +393,38 @@ static int unpack_failed(struct unpack_trees_options *o, const char *message)
return -1;
}
+static void debug_path(struct traverse_info *info)
+{
+ if (info->prev) {
+ debug_path(info->prev);
+ if (*info->prev->name.path)
+ putchar('/');
+ }
+ printf("%s", info->name.path);
+}
+
+static void debug_name_entry(int i, struct name_entry *n)
+{
+ printf("ent#%d %06o %s\n", i,
+ n->path ? n->mode : 0,
+ n->path ? n->path : "(missing)");
+}
+
+static void debug_unpack_callback(int n,
+ unsigned long mask,
+ unsigned long dirmask,
+ struct name_entry *names,
+ struct traverse_info *info)
+{
+ int i;
+ printf("* unpack mask %lu, dirmask %lu, cnt %d ",
+ mask, dirmask, n);
+ debug_path(info);
+ putchar('\n');
+ for (i = 0; i < n; i++)
+ debug_name_entry(i, names + i);
+}
+
static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, struct name_entry *names, struct traverse_info *info)
{
struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, };
@@ -403,6 +435,9 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
while (!p->mode)
p++;
+ if (o->debug_unpack)
+ debug_unpack_callback(n, mask, dirmask, names, info);
+
/* Are we supposed to look at the index too? */
if (o->merge) {
while (1) {
diff --git a/unpack-trees.h b/unpack-trees.h
index 9a0733e..701dca5 100644
--- a/unpack-trees.h
+++ b/unpack-trees.h
@@ -28,6 +28,7 @@ struct unpack_trees_options {
skip_unmerged,
initial_checkout,
diff_index_cached,
+ debug_unpack,
gently;
const char *prefix;
int cache_bottom;
--
1.6.5.rc1.90.ga3b1b
^ permalink raw reply related
* [WIP PATCH 5/6] unpack-trees.c: prepare for looking ahead in the index
From: Junio C Hamano @ 2009-09-20 5:06 UTC (permalink / raw)
To: git
In-Reply-To: <1253423175-6339-1-git-send-email-gitster@pobox.com>
This prepares but does not yet implement a look-ahead in the index entries
when traverse-trees.c decides to give us tree entries in an order that
does not match what is in the index.
A case where a look-ahead in the index is necessary happens when merging
branch B into branch A while the index matches the current branch A, using
a tree O as their common ancestor, and these three trees looks like this:
O A B
t t
t-i t-i t-i
t-j t-j
t/1
t/2
The traverse_trees() function gets "t", "t-i" and "t" from trees O, A and
B first, and notices that A may have a matching "t" behind "t-i" and "t-j"
(indeed it does), and tells A to give that entry instead. After unpacking
blob "t" from tree B (as it hasn't changed since O in B and A removed it,
it will result in its removal), it descends into directory "t/".
The side that walked index in parallel to the tree traversal used to be
implemented with one pointer, o->pos, that points at the next index entry
to be processed. When this happens, the pointer o->pos still points at
"t-i" that is the first entry. We should be able to skip "t-i" and "t-j"
and locate "t/1" from the index while the recursive invocation of
traverse_trees() walks and match entries found there, and later come back
to process "t-i".
While that look-ahead is not implemented yet, this adds a flag bit,
CE_UNPACKED, to mark the entries in the index that has already been
processed. o->pos pointer has been renamed to o->cache_bottom and it
points at the first entry that may still need to be processed.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
* t6035 is still broken with this patch, although t7003 is fixed.
cache.h | 2 +
diff-lib.c | 18 -----
unpack-trees.c | 214 ++++++++++++++++++++++++++++++++++++++++++--------------
unpack-trees.h | 2 +-
4 files changed, 164 insertions(+), 72 deletions(-)
diff --git a/cache.h b/cache.h
index 5fad24c..18a3e13 100644
--- a/cache.h
+++ b/cache.h
@@ -177,6 +177,8 @@ struct cache_entry {
#define CE_HASHED (0x100000)
#define CE_UNHASHED (0x200000)
+#define CE_UNPACKED (0x400000)
+
/*
* Extended on-disk flags
*/
diff --git a/diff-lib.c b/diff-lib.c
index adf1c5f..f759917 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -359,21 +359,6 @@ static void do_oneway_diff(struct unpack_trees_options *o,
show_modified(revs, tree, idx, 1, cached, match_missing);
}
-static inline void skip_same_name(struct cache_entry *ce, struct unpack_trees_options *o)
-{
- int len = ce_namelen(ce);
- const struct index_state *index = o->src_index;
-
- while (o->pos < index->cache_nr) {
- struct cache_entry *next = index->cache[o->pos];
- if (len != ce_namelen(next))
- break;
- if (memcmp(ce->name, next->name, len))
- break;
- o->pos++;
- }
-}
-
/*
* The unpack_trees() interface is designed for merging, so
* the different source entries are designed primarily for
@@ -395,9 +380,6 @@ static int oneway_diff(struct cache_entry **src, struct unpack_trees_options *o)
struct cache_entry *tree = src[1];
struct rev_info *revs = o->unpack_data;
- if (idx && ce_stage(idx))
- skip_same_name(idx, o);
-
/*
* Unpack-trees generates a DF/conflict entry if
* there was a directory in the index and a tree
diff --git a/unpack-trees.c b/unpack-trees.c
index c424bab..a6f2187 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -126,18 +126,109 @@ static inline int call_unpack_fn(struct cache_entry **src, struct unpack_trees_o
return ret;
}
-static int unpack_index_entry(struct cache_entry *ce, struct unpack_trees_options *o)
+static void mark_ce_used(struct cache_entry *ce, struct unpack_trees_options *o)
+{
+ ce->ce_flags |= CE_UNPACKED;
+
+ if (o->cache_bottom < o->src_index->cache_nr &&
+ o->src_index->cache[o->cache_bottom] == ce) {
+ int bottom = o->cache_bottom;
+ while (bottom < o->src_index->cache_nr &&
+ o->src_index->cache[bottom]->ce_flags & CE_UNPACKED)
+ bottom++;
+ o->cache_bottom = bottom;
+ }
+}
+
+static void mark_all_ce_unused(struct index_state *index)
+{
+ int i;
+ for (i = 0; i < index->cache_nr; i++)
+ index->cache[i]->ce_flags &= ~CE_UNPACKED;
+}
+
+static int locate_in_src_index(struct cache_entry *ce,
+ struct unpack_trees_options *o)
+{
+ struct index_state *index = o->src_index;
+ int len = ce_namelen(ce);
+ int pos = index_name_pos(index, ce->name, len);
+ if (pos < 0)
+ pos = -1 - pos;
+ return pos;
+}
+
+/*
+ * We call unpack_index_entry() with an unmerged cache entry
+ * only in diff-index, and it wants a single callback. Skip
+ * the other unmerged entry with the same name.
+ */
+static void mark_ce_used_same_name(struct cache_entry *ce,
+ struct unpack_trees_options *o)
+{
+ struct index_state *index = o->src_index;
+ int len = ce_namelen(ce);
+ int pos;
+
+ for (pos = locate_in_src_index(ce, o); pos < index->cache_nr; pos++) {
+ struct cache_entry *next = index->cache[pos];
+ if (len != ce_namelen(next) ||
+ memcmp(ce->name, next->name, len))
+ break;
+ mark_ce_used(next, o);
+ }
+}
+
+static struct cache_entry *next_cache_entry(struct unpack_trees_options *o)
+{
+ const struct index_state *index = o->src_index;
+ int pos = o->cache_bottom;
+
+ while (pos < index->cache_nr) {
+ struct cache_entry *ce = index->cache[pos];
+ if (!(ce->ce_flags & CE_UNPACKED))
+ return ce;
+ pos++;
+ }
+ return NULL;
+}
+
+static void add_same_unmerged(struct cache_entry *ce,
+ struct unpack_trees_options *o)
+{
+ struct index_state *index = o->src_index;
+ int len = ce_namelen(ce);
+ int pos = index_name_pos(index, ce->name, len);
+
+ if (0 <= pos)
+ die("programming error in a caller of mark_ce_used_same_name");
+ for (pos = -pos - 1; pos < index->cache_nr; pos++) {
+ struct cache_entry *next = index->cache[pos];
+ if (len != ce_namelen(next) ||
+ memcmp(ce->name, next->name, len))
+ break;
+ add_entry(o, next, 0, 0);
+ mark_ce_used(next, o);
+ }
+}
+
+static int unpack_index_entry(struct cache_entry *ce,
+ struct unpack_trees_options *o)
{
struct cache_entry *src[5] = { ce, NULL, };
+ int ret;
- o->pos++;
+ mark_ce_used(ce, o);
if (ce_stage(ce)) {
if (o->skip_unmerged) {
add_entry(o, ce, 0, 0);
return 0;
}
}
- return call_unpack_fn(src, o);
+ ret = call_unpack_fn(src, o);
+ if (ce_stage(ce))
+ mark_ce_used_same_name(ce, o);
+ return ret;
}
static int traverse_trees_recursive(int n, unsigned long dirmask, unsigned long df_conflicts, struct name_entry *names, struct traverse_info *info)
@@ -212,6 +303,20 @@ static int compare_entry(const struct cache_entry *ce, const struct traverse_inf
return ce_namelen(ce) > traverse_path_len(info, n);
}
+static int ce_in_traverse_path(const struct cache_entry *ce,
+ const struct traverse_info *info)
+{
+ if (!info->prev)
+ return 1;
+ if (do_compare_entry(ce, info->prev, &info->name))
+ return 0;
+ /*
+ * If ce (blob) is the same name as the path (which is a tree
+ * we will be descending into), it won't be inside it.
+ */
+ return (info->pathlen < ce_namelen(ce));
+}
+
static struct cache_entry *create_ce_entry(const struct traverse_info *info, const struct name_entry *n, int stage)
{
int len = traverse_path_len(info, n);
@@ -300,23 +405,27 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
/* Are we supposed to look at the index too? */
if (o->merge) {
- while (o->pos < o->src_index->cache_nr) {
- struct cache_entry *ce = o->src_index->cache[o->pos];
- int cmp = compare_entry(ce, info, p);
+ while (1) {
+ struct cache_entry *ce = next_cache_entry(o);
+ int cmp;
+ if (!ce)
+ break;
+ cmp = compare_entry(ce, info, p);
if (cmp < 0) {
if (unpack_index_entry(ce, o) < 0)
return unpack_failed(o, NULL);
continue;
}
if (!cmp) {
- o->pos++;
if (ce_stage(ce)) {
/*
- * If we skip unmerged index entries, we'll skip this
- * entry *and* the tree entries associated with it!
+ * If we skip unmerged index
+ * entries, we'll skip this
+ * entry *and* the tree
+ * entries associated with it!
*/
if (o->skip_unmerged) {
- add_entry(o, ce, 0, 0);
+ add_same_unmerged(ce, o);
return mask;
}
}
@@ -329,6 +438,13 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
if (unpack_nondirectories(n, mask, dirmask, src, names, info) < 0)
return -1;
+ if (src[0]) {
+ if (ce_stage(src[0]))
+ mark_ce_used_same_name(src[0], o);
+ else
+ mark_ce_used(src[0], o);
+ }
+
/* Now handle any directories.. */
if (dirmask) {
unsigned long conflicts = mask & ~dirmask;
@@ -338,22 +454,6 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
conflicts |= 1;
}
- /* special case: "diff-index --cached" looking at a tree */
- if (o->diff_index_cached &&
- n == 1 && dirmask == 1 && S_ISDIR(names->mode)) {
- int matches;
- matches = cache_tree_matches_traversal(o->src_index->cache_tree,
- names, info);
- /*
- * Everything under the name matches. Adjust o->pos to
- * skip the entire hierarchy.
- */
- if (matches) {
- o->pos += matches;
- return mask;
- }
- }
-
if (traverse_trees_recursive(n, dirmask, conflicts,
names, info) < 0)
return -1;
@@ -400,14 +500,33 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
info.fn = unpack_callback;
info.data = o;
+ if (o->prefix) {
+ /*
+ * Unpack existing index entries that sort before the
+ * prefix the tree is spliced into. Note that o->merge
+ * is always true in this case.
+ */
+ while (1) {
+ struct cache_entry *ce = next_cache_entry(o);
+ if (!ce)
+ break;
+ if (ce_in_traverse_path(ce, &info))
+ break;
+ if (unpack_index_entry(ce, o) < 0)
+ return unpack_failed(o, NULL);
+ }
+ }
+
if (traverse_trees(len, t, &info) < 0)
return unpack_failed(o, NULL);
}
/* Any left-over entries in the index? */
if (o->merge) {
- while (o->pos < o->src_index->cache_nr) {
- struct cache_entry *ce = o->src_index->cache[o->pos];
+ while (1) {
+ struct cache_entry *ce = next_cache_entry(o);
+ if (!ce)
+ break;
if (unpack_index_entry(ce, o) < 0)
return unpack_failed(o, NULL);
}
@@ -416,6 +535,12 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
if (o->trivial_merges_only && o->nontrivial_merge)
return unpack_failed(o, "Merge requires file-level merging");
+ /*
+ * some callers, most notably "git status -v" runs unpack_trees()
+ * multiple times; clean everything up after us.
+ */
+ mark_all_ce_unused(o->src_index);
+
o->src_index = NULL;
ret = check_updates(o) ? (-2) : 0;
if (o->dst_index)
@@ -522,7 +647,9 @@ static int verify_clean_subdirectory(struct cache_entry *ce, const char *action,
* in that directory.
*/
namelen = strlen(ce->name);
- for (i = o->pos; i < o->src_index->cache_nr; i++) {
+ for (i = locate_in_src_index(ce, o);
+ i < o->src_index->cache_nr;
+ i++) {
struct cache_entry *ce2 = o->src_index->cache[i];
int len = ce_namelen(ce2);
if (len < namelen ||
@@ -530,12 +657,14 @@ static int verify_clean_subdirectory(struct cache_entry *ce, const char *action,
ce2->name[namelen] != '/')
break;
/*
- * ce2->name is an entry in the subdirectory.
+ * ce2->name is an entry in the subdirectory to be
+ * removed.
*/
if (!ce_stage(ce2)) {
if (verify_uptodate(ce2, o))
return -1;
add_entry(o, ce2, CE_REMOVE, 0);
+ mark_ce_used(ce2, o);
}
cnt++;
}
@@ -591,7 +720,6 @@ static int verify_absent(struct cache_entry *ce, const char *action,
return 0;
if (!lstat(ce->name, &st)) {
- int ret;
int dtype = ce_to_dtype(ce);
struct cache_entry *result;
@@ -619,28 +747,8 @@ static int verify_absent(struct cache_entry *ce, const char *action,
* files that are in "foo/" we would lose
* them.
*/
- ret = verify_clean_subdirectory(ce, action, o);
- if (ret < 0)
- return ret;
-
- /*
- * If this removed entries from the index,
- * what that means is:
- *
- * (1) the caller unpack_callback() saw path/foo
- * in the index, and it has not removed it because
- * it thinks it is handling 'path' as blob with
- * D/F conflict;
- * (2) we will return "ok, we placed a merged entry
- * in the index" which would cause o->pos to be
- * incremented by one;
- * (3) however, original o->pos now has 'path/foo'
- * marked with "to be removed".
- *
- * We need to increment it by the number of
- * deleted entries here.
- */
- o->pos += ret;
+ if (verify_clean_subdirectory(ce, action, o) < 0)
+ return -1;
return 0;
}
diff --git a/unpack-trees.h b/unpack-trees.h
index d19df44..9a0733e 100644
--- a/unpack-trees.h
+++ b/unpack-trees.h
@@ -30,7 +30,7 @@ struct unpack_trees_options {
diff_index_cached,
gently;
const char *prefix;
- int pos;
+ int cache_bottom;
struct dir_struct *dir;
merge_fn_t fn;
struct unpack_trees_error_msgs msgs;
--
1.6.5.rc1.90.ga3b1b
^ permalink raw reply related
* [PATCH RESEND] git gui: make current branch default in "remote delete branch" merge check
From: Heiko Voigt @ 2009-09-20 9:47 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git
Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net>
---
git-gui/lib/remote_branch_delete.tcl | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/git-gui/lib/remote_branch_delete.tcl b/git-gui/lib/remote_branch_delete.tcl
index 4e02fc0..9b119a7 100644
--- a/git-gui/lib/remote_branch_delete.tcl
+++ b/git-gui/lib/remote_branch_delete.tcl
@@ -248,6 +248,8 @@ method _write_url {args} { set urltype url }
method _write_check_head {args} { set checktype head }
method _write_head_list {args} {
+ global current_branch
+
$head_m delete 0 end
foreach abr $head_list {
$head_m insert end radiobutton \
@@ -256,7 +258,11 @@ method _write_head_list {args} {
-variable @check_head
}
if {[lsearch -exact -sorted $head_list $check_head] < 0} {
- set check_head {}
+ if {[lsearch -exact -sorted $head_list $current_branch] < 0} {
+ set check_head {}
+ } else {
+ set check_head $current_branch
+ }
}
}
--
1.6.5.rc1.10.g20f34
^ permalink raw reply related
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