* Re: Bug: "git checkout -b" should be allowed in empty repo
From: Jeff King @ 2012-01-30 21:50 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Michael Haggerty, git
In-Reply-To: <7vaa55ar4v.fsf@alter.siamese.dyndns.org>
On Mon, Jan 30, 2012 at 12:10:08PM -0800, Junio C Hamano wrote:
> diff --git a/builtin/checkout.c b/builtin/checkout.c
> index f1984d9..195c40b 100644
> --- a/builtin/checkout.c
> +++ b/builtin/checkout.c
> @@ -922,6 +922,19 @@ static int parse_branchname_arg(int argc, const char **argv,
> return argcount;
> }
>
> +static int switch_unborn_to_new_branch(struct checkout_opts *opts, const char *old_ref)
> +{
> + int status;
> + struct strbuf branch_ref = STRBUF_INIT;
> +
> + strbuf_addf(&branch_ref, "refs/heads/%s", opts->new_branch);
> + warning(_("Leaving the unborn branch '%s' behind..."),
> + skip_prefix(old_ref, "refs/heads/"));
> + status = create_symref("HEAD", branch_ref.buf, "checkout -b");
> + strbuf_reset(&branch_ref);
> + return status;
> +}
Is it really worth warning? After all, by definition you are not leaving
any commits or useful work behind.
Also, this has the same strbuf reset/release leak as the last patch. :)
-Peff
^ permalink raw reply
* Re: [PATCH] merge: add instructions to the commit message when editing
From: Junio C Hamano @ 2012-01-30 21:52 UTC (permalink / raw)
To: Thomas Rast; +Cc: Thomas Rast, git
In-Reply-To: <878vkoamu3.fsf@thomas.inf.ethz.ch>
Thomas Rast <trast@inf.ethz.ch> writes:
>> Please enter the commit message for your merge commit. Explain
>> why the merge is necessary, especially if it merges an updated
>> upstream into a topic branch.
>>
>> ... because people who need to be told to "justify it" would probably be
>> helped by a more explicit "explain _why_ it is needed".
>
> Why not. The "explain..." might be construed as a bit too coercive, but
> I cannot come up with a way to defuse it (well, except again tacking on
> "you should") ...
Would "Please enter the commit message for your merge commit, to explain
why ..." work?
^ permalink raw reply
* Re: [PATCH] find_pack_entry(): do not keep packed_git pointer locally
From: Junio C Hamano @ 2012-01-30 23:26 UTC (permalink / raw)
To: Nguyễn Thái Ngọc Duy; +Cc: git
In-Reply-To: <1327922750-12106-1-git-send-email-pclouds@gmail.com>
Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:
> Commit f7c22cc (always start looking up objects in the last used pack
> first - 2007-05-30) introduces a static packed_git* pointer as an
> optimization. The kept pointer however may become invalid if
> free_pack_by_name() happens to free that particular pack.
>
> Current code base does not access packs after calling
> free_pack_by_name() so it should not be a problem. Anyway, move the
> pointer out so that free_pack_by_name() can reset it to avoid running
> into troubles in future.
>
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---
Thanks. Two curiosities:
- Why is there no hunk to actually clear the pointer in
free_pack_by_name() in this patch?
- Could we make the magic (void *)1 value a #define'd constant? Perhaps
we could even use NULL for that purpose?
> diff --git a/sha1_file.c b/sha1_file.c
> index 88f2151..4ecc953 100644
> --- a/sha1_file.c
> +++ b/sha1_file.c
> @@ -54,6 +54,8 @@ static struct cached_object empty_tree = {
> 0
> };
>
> +static struct packed_git *find_pack_entry_last_found = (void *)1;
> +
> static struct cached_object *find_cached_object(const unsigned char *sha1)
> {
> int i;
> @@ -720,6 +722,8 @@ void free_pack_by_name(const char *pack_name)
> close_pack_index(p);
> free(p->bad_object_sha1);
> *pp = p->next;
> + if (find_pack_entry_last_found == p)
> + find_pack_entry_last_found = (void*)1;
> free(p);
> return;
> }
> @@ -2012,14 +2016,13 @@ int is_pack_valid(struct packed_git *p)
>
> static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
> {
> - static struct packed_git *last_found = (void *)1;
> struct packed_git *p;
> off_t offset;
>
> prepare_packed_git();
> if (!packed_git)
> return 0;
> - p = (last_found == (void *)1) ? packed_git : last_found;
> + p = (find_pack_entry_last_found == (void *)1) ? packed_git : find_pack_entry_last_found;
>
> do {
> if (p->num_bad_objects) {
> @@ -2046,16 +2049,16 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
> e->offset = offset;
> e->p = p;
> hashcpy(e->sha1, sha1);
> - last_found = p;
> + find_pack_entry_last_found = p;
> return 1;
> }
>
> next:
> - if (p == last_found)
> + if (p == find_pack_entry_last_found)
> p = packed_git;
> else
> p = p->next;
> - if (p == last_found)
> + if (p == find_pack_entry_last_found)
> p = p->next;
> } while (p);
> return 0;
^ permalink raw reply
* [BUG] git clean -X skips a directory containing only ignored files
From: Paul Berry @ 2012-01-30 23:36 UTC (permalink / raw)
To: git
I am trying to use "git clean -X" to remove object files (which
are gitignored) from my source tree, but it appears to miss
object files that are in a subdirectory without any git-tracked
files:
$ git init test
Initialized empty Git repository in /home/pberry/tmp/test/.git/
$ cd test
$ mkdir foo
$ touch foo/bar.o
$ echo '*.o' > .gitignore
$ git add .gitignore
$ git commit -mgitignore
[master (root-commit) 6b5ffcb] gitignore
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 .gitignore
$ git status
# On branch master
nothing to commit (working directory clean)
$ git clean -d -X -f
$ ls foo
bar.o
It seems to me that bar.o should have been removed, because
according to the git-clean docs, -X means "Remove only files
ignored by git", and bar.o is definitely being ignored by git.
It looks like a very similar bug was reported back in 2010, but
not fixed:
http://git.661346.n2.nabble.com/BUG-git-clean-X-behaviour-when-gitignore-has-sub-directory-entries-td5575307.html.
I've confirmed that the workaround mentioned by Jonathan Nieder
in that thread fixes my problem too (removing "dir.flags |=
DIR_SHOW_OTHER_DIRECTORIES;" from builtin/clean.c). However I'm
guessing from Jonathan's comments that it would be better to fix
this bug elsewhere (somewhere in dir.c perhaps).
Is anyone interested in following up on this old bug?
Alternatively, if someone could give me some guidance as to the
best way to go about fixing this bug, I would be glad to submit a
patch.
Thanks,
Paul
^ permalink raw reply
* Re: [PATCH v2 3/4] completion: cleanup __gitcomp*
From: SZEDER Gábor @ 2012-01-31 0:15 UTC (permalink / raw)
To: Jonathan Nieder
Cc: Felipe Contreras, git, Felipe Contreras, Ted Pavlic,
Shawn O. Pearce, Junio C Hamano
In-Reply-To: <20120130175004.GG10618@burratino>
Hi,
On Mon, Jan 30, 2012 at 11:50:04AM -0600, Jonathan Nieder wrote:
> Felipe Contreras wrote:
>
> > I don't know why there's so much code; these functions don't seem to be
> > doing much:
>
> Unless you mean "This patch has had inadequate review and I don't
> understand the code I'm patching, so do not trust it", please drop
> this commentary or place it after the three dashes.
>
> > * no need to check $#, ${3:-$cur} is much easier
> > * __gitcomp_nl doesn't seem to using the initial IFS
> >
> > This makes the code much simpler.
> >
> > Eventually it would be nice to wrap everything that touches compgen and
> > COMPREPLY in one function for the zsh wrapper.
> >
> > Comments by Jonathan Nieder.
>
> I don't want this acknowledgement. Who should care that I commented
> on something?
>
> > Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
> > ---
> > contrib/completion/git-completion.bash | 20 +++-----------------
> > 1 files changed, 3 insertions(+), 17 deletions(-)
>
> This diffstat tells me more of what I wanted to know about the patch
> than the description did.
>
> I imagine it would have been enough to say something along the lines of
> "The __gitcomp and __gitcomp_nl functions are unnecessarily verbose.
> __gitcomp_nl sets IFS to " \t\n" unnecessarily
Yeah, that's unnecessary. I'm not sure why I did that, perhaps just
blindly followed suit of gitcomp_1(), without realizing that I don't
do any word-splitting in __gitcomp_nl() except when invoking compgen.
> before setting it to "\n"
> by mistake.
But that is deliberate, that's why it's called __gitcomp_nl(), see
a31e6262 (completion: optimize refs completion, 2011-10-15), third
paragraph.
> Both functions use 'if' statements to read parameters
> with defaults, where the ${parameter:-default} idiom would be just as
> clear. By fixing these, we can make each function almost a one-liner."
>
> By the way, the subject ("clean up __gitcomp*") tells me almost as
> little as something like "fix __gitcomp*". A person reading the
> shortlog would like to know _how_ you are fixing it, or what the
> impact of the change will be --- e.g., something like "simplify
> __gitcomp and __gitcomp_nl" would be clearer.
>
> [...]
> > --- a/contrib/completion/git-completion.bash
> > +++ b/contrib/completion/git-completion.bash
> [...]
> > @@ -524,18 +520,8 @@ __gitcomp ()
> > # appended.
> > __gitcomp_nl ()
> > {
> > - local s=$'\n' IFS=' '$'\t'$'\n'
> > - local cur_="$cur" suffix=" "
> > -
> > - if [ $# -gt 2 ]; then
> > - cur_="$3"
> > - if [ $# -gt 3 ]; then
> > - suffix="$4"
> > - fi
> > - fi
> > -
> > - IFS=$s
> > - COMPREPLY=($(compgen -P "${2-}" -S "$suffix" -W "$1" -- "$cur_"))
> > + local IFS=$'\n'
> > + COMPREPLY=($(compgen -P "${2-}" -S "${4:- }" -W "$1" -- "${3:-$cur}"))
>
> This loses the nice name $suffix for the -S argument. Not a problem,
> just noticing.
I think loosing the name of $suffix would be OK, because the comment
above the function explains what the fourth parameter is about.
However, that comment also says that "If [the 4. argument is]
specified but empty, nothing is appended.", but this patch changes
this behavior, because "${4:- }" is substituted by a SP when $4 is an
empty string. You have to drop the colon and use "${4- }" there:
$ foo=""
$ echo ,${foo:- },
, ,
$ echo ,${foo- },
,,
Best,
Gábor
^ permalink raw reply
* [PATCH 0/2] gitweb: Project search improvements
From: Jakub Narebski @ 2012-01-31 0:20 UTC (permalink / raw)
To: git; +Cc: Bernhard R. Link, Jakub Narebski
This was once a part of larger series improving project search in
gitweb, but those two patches can stand alone. I am sending this
series (especially the second patch) in response to Bernhard patches
adding support for project_filter.
These patches should be applied on top of his work, i.e. on top of
'bl/gitweb-project-filter' branch.
Jakub Narebski (2):
gitweb: Improve projects search form
gitweb: Make project search respect project_filter
gitweb/gitweb.perl | 35 ++++++++++++++++++++++++++++++-----
gitweb/static/gitweb.css | 7 ++++++-
2 files changed, 36 insertions(+), 6 deletions(-)
--
1.7.6
^ permalink raw reply
* [PATCH 2/2] gitweb: Make project search respect project_filter
From: Jakub Narebski @ 2012-01-31 0:20 UTC (permalink / raw)
To: git; +Cc: Bernhard R. Link, Jakub Narebski
In-Reply-To: <1327969255-26622-1-git-send-email-jnareb@gmail.com>
Make gitweb search within filtered projects (i.e. projects shown), and
change "List all projects" to "List all projects in '$project_filter/'"
if project_filter is used.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
This patch is new.
gitweb/gitweb.perl | 18 +++++++++++++-----
1 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index c4e0d8e..80975dd 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -5158,11 +5158,18 @@ sub git_patchset_body {
sub git_project_search_form {
my ($searchtext, $search_use_regexp);
+ my $limit = '';
+ if ($project_filter) {
+ $limit = " in '$project_filter/'";
+ }
+
print "<div class=\"projsearch\">\n";
print $cgi->startform(-method => 'get', -action => $my_uri) .
- $cgi->hidden(-name => 'a', -value => 'project_list') . "\n" .
- $cgi->textfield(-name => 's', -value => $searchtext,
- -title => 'Search project by name and description',
+ $cgi->hidden(-name => 'a', -value => 'project_list') . "\n";
+ print $cgi->hidden(-name => 'pf', -value => $project_filter). "\n"
+ if (defined $project_filter);
+ print $cgi->textfield(-name => 's', -value => $searchtext,
+ -title => "Search project by name and description$limit",
-size => 60) . "\n" .
"<span title=\"Extended regular expression\">" .
$cgi->checkbox(-name => 'sr', -value => 1, -label => 're',
@@ -5170,8 +5177,9 @@ sub git_project_search_form {
"</span>\n" .
$cgi->submit(-name => 'btnS', -value => 'Search') .
$cgi->end_form() . "\n" .
- $cgi->a({-href => href(project => undef, searchtext => undef)},
- 'List all projects') . "<br />\n";
+ $cgi->a({-href => href(project => undef, searchtext => undef,
+ project_filter => $project_filter)},
+ esc_html("List all projects$limit")) . "<br />\n";
print "</div>\n";
}
--
1.7.6
^ permalink raw reply related
* [PATCH 1/2] gitweb: Improve projects search form
From: Jakub Narebski @ 2012-01-31 0:20 UTC (permalink / raw)
To: git; +Cc: Bernhard R. Link, Jakub Narebski
In-Reply-To: <1327969255-26622-1-git-send-email-jnareb@gmail.com>
Refactor generating project search form into git_project_search_form().
Make text field wider and add on mouse over explanation (via "title"
attribute), add an option to use regular expressions, and replace
'Search:' label with [Search] button.
Also add "List all projects" link to make it easier to go back from
search result to list of all projects (note that empty search term
is disallowed).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
The major advantage is that you can use regular expression in
searching projects... well, at least there is UI for it, because you
could handcraft URL earlier anyway.
This patch was presented on git mailing list earlier.
gitweb/gitweb.perl | 27 ++++++++++++++++++++++-----
gitweb/static/gitweb.css | 7 ++++++-
2 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index fa8a300..c4e0d8e 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -5155,6 +5155,26 @@ sub git_patchset_body {
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+sub git_project_search_form {
+ my ($searchtext, $search_use_regexp);
+
+ print "<div class=\"projsearch\">\n";
+ print $cgi->startform(-method => 'get', -action => $my_uri) .
+ $cgi->hidden(-name => 'a', -value => 'project_list') . "\n" .
+ $cgi->textfield(-name => 's', -value => $searchtext,
+ -title => 'Search project by name and description',
+ -size => 60) . "\n" .
+ "<span title=\"Extended regular expression\">" .
+ $cgi->checkbox(-name => 'sr', -value => 1, -label => 're',
+ -checked => $search_use_regexp) .
+ "</span>\n" .
+ $cgi->submit(-name => 'btnS', -value => 'Search') .
+ $cgi->end_form() . "\n" .
+ $cgi->a({-href => href(project => undef, searchtext => undef)},
+ 'List all projects') . "<br />\n";
+ print "</div>\n";
+}
+
# fills project list info (age, description, owner, category, forks)
# for each project in the list, removing invalid projects from
# returned list
@@ -6022,11 +6042,8 @@ sub git_project_list {
insert_file($home_text);
print "</div>\n";
}
- print $cgi->startform(-method => "get") .
- "<p class=\"projsearch\">Search:\n" .
- $cgi->textfield(-name => "s", -value => $searchtext) . "\n" .
- "</p>" .
- $cgi->end_form() . "\n";
+
+ git_project_search_form($searchtext, $search_use_regexp);
git_project_list_body(\@list, $order);
git_footer_html();
}
diff --git a/gitweb/static/gitweb.css b/gitweb/static/gitweb.css
index c7827e8..c530355 100644
--- a/gitweb/static/gitweb.css
+++ b/gitweb/static/gitweb.css
@@ -520,8 +520,13 @@ div.search {
right: 12px
}
-p.projsearch {
+div.projsearch {
text-align: center;
+ margin: 20px 0px;
+}
+
+div.projsearch form {
+ margin-bottom: 2px;
}
td.linenr {
--
1.7.6
^ permalink raw reply related
* Re: [PATCH v2 3/4] completion: cleanup __gitcomp*
From: Jonathan Nieder @ 2012-01-31 0:25 UTC (permalink / raw)
To: SZEDER Gábor
Cc: Felipe Contreras, git, Felipe Contreras, Ted Pavlic,
Shawn O. Pearce, Junio C Hamano
In-Reply-To: <20120131001535.GB2632@goldbirke>
SZEDER Gábor wrote:
> On Mon, Jan 30, 2012 at 11:50:04AM -0600, Jonathan Nieder wrote:
>> I imagine it would have been enough to say something along the lines of
>> "The __gitcomp and __gitcomp_nl functions are unnecessarily verbose.
>> __gitcomp_nl sets IFS to " \t\n" unnecessarily
>
> Yeah, that's unnecessary. I'm not sure why I did that, perhaps just
> blindly followed suit of gitcomp_1(), without realizing that I don't
> do any word-splitting in __gitcomp_nl() except when invoking compgen.
>
>> before setting it to "\n"
>> by mistake.
>
> But that is deliberate, that's why it's called __gitcomp_nl(), see
> a31e6262 (completion: optimize refs completion, 2011-10-15), third
> paragraph.
Yep, sorry for the ambiguity. I meant that setting IFS to " \t\n"
(before setting it to "\n") was not done for any serious reason.
The explanation is definitely clearer with "by mistake" dropped.
Thanks,
Jonathan
^ permalink raw reply
* Re: [PATCH] find_pack_entry(): do not keep packed_git pointer locally
From: Nguyen Thai Ngoc Duy @ 2012-01-31 2:01 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Nicolas Pitre
In-Reply-To: <7v62fsai1i.fsf@alter.siamese.dyndns.org>
(Pulling Nico in for Q2 below. No snipping so he has a context)
2012/1/31 Junio C Hamano <gitster@pobox.com>:
> Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:
>
>> Commit f7c22cc (always start looking up objects in the last used pack
>> first - 2007-05-30) introduces a static packed_git* pointer as an
>> optimization. The kept pointer however may become invalid if
>> free_pack_by_name() happens to free that particular pack.
>>
>> Current code base does not access packs after calling
>> free_pack_by_name() so it should not be a problem. Anyway, move the
>> pointer out so that free_pack_by_name() can reset it to avoid running
>> into troubles in future.
>>
>> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
>> ---
>
> Thanks. Two curiosities:
>
> - Why is there no hunk to actually clear the pointer in
> free_pack_by_name() in this patch?
I think it's there (the patch did work for me when I tried to
integrate repack to pack-objects).
-- 8<--
> @@ -720,6 +722,8 @@ void free_pack_by_name(const char *pack_name)
> close_pack_index(p);
> free(p->bad_object_sha1);
> *pp = p->next;
> + if (find_pack_entry_last_found == p)
> + find_pack_entry_last_found = (void*)1;
> free(p);
> return;
> }
-- 8< --
> - Could we make the magic (void *)1 value a #define'd constant? Perhaps
> we could even use NULL for that purpose?
Q1. Sure.
Q2. No NULL is probably not suitable. I think Nico wanted to express
"we tried to find but found none (i.e. NULL)" too and 1 means "no we
have not tried".
>> diff --git a/sha1_file.c b/sha1_file.c
>> index 88f2151..4ecc953 100644
>> --- a/sha1_file.c
>> +++ b/sha1_file.c
>> @@ -54,6 +54,8 @@ static struct cached_object empty_tree = {
>> 0
>> };
>>
>> +static struct packed_git *find_pack_entry_last_found = (void *)1;
>> +
>> static struct cached_object *find_cached_object(const unsigned char *sha1)
>> {
>> int i;
>> @@ -720,6 +722,8 @@ void free_pack_by_name(const char *pack_name)
>> close_pack_index(p);
>> free(p->bad_object_sha1);
>> *pp = p->next;
>> + if (find_pack_entry_last_found == p)
>> + find_pack_entry_last_found = (void*)1;
>> free(p);
>> return;
>> }
>> @@ -2012,14 +2016,13 @@ int is_pack_valid(struct packed_git *p)
>>
>> static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
>> {
>> - static struct packed_git *last_found = (void *)1;
>> struct packed_git *p;
>> off_t offset;
>>
>> prepare_packed_git();
>> if (!packed_git)
>> return 0;
>> - p = (last_found == (void *)1) ? packed_git : last_found;
>> + p = (find_pack_entry_last_found == (void *)1) ? packed_git : find_pack_entry_last_found;
>>
>> do {
>> if (p->num_bad_objects) {
>> @@ -2046,16 +2049,16 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
>> e->offset = offset;
>> e->p = p;
>> hashcpy(e->sha1, sha1);
>> - last_found = p;
>> + find_pack_entry_last_found = p;
>> return 1;
>> }
>>
>> next:
>> - if (p == last_found)
>> + if (p == find_pack_entry_last_found)
>> p = packed_git;
>> else
>> p = p->next;
>> - if (p == last_found)
>> + if (p == find_pack_entry_last_found)
>> p = p->next;
>> } while (p);
>> return 0;
--
Duy
^ permalink raw reply
* Re: [PATCH] find_pack_entry(): do not keep packed_git pointer locally
From: Nicolas Pitre @ 2012-01-31 4:19 UTC (permalink / raw)
To: Nguyen Thai Ngoc Duy; +Cc: Junio C Hamano, git
In-Reply-To: <CACsJy8AS0nZOoXZZfz0OEwoWe88wp2aGR5NGqpG7xQmUvwi7TA@mail.gmail.com>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1534 bytes --]
On Tue, 31 Jan 2012, Nguyen Thai Ngoc Duy wrote:
> (Pulling Nico in for Q2 below. No snipping so he has a context)
>
> 2012/1/31 Junio C Hamano <gitster@pobox.com>:
> > Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:
> >
> >> Commit f7c22cc (always start looking up objects in the last used pack
> >> first - 2007-05-30) introduces a static packed_git* pointer as an
> >> optimization. The kept pointer however may become invalid if
> >> free_pack_by_name() happens to free that particular pack.
Hmmm, good point.
> >> Current code base does not access packs after calling
> >> free_pack_by_name() so it should not be a problem. Anyway, move the
> >> pointer out so that free_pack_by_name() can reset it to avoid running
> >> into troubles in future.
> >>
> >> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> >> ---
[...]
> > - Could we make the magic (void *)1 value a #define'd constant? Perhaps
> > we could even use NULL for that purpose?
>
> Q1. Sure.
Indeed. The idea might have been to use a non null value that cannot
match any pointer...
> Q2. No NULL is probably not suitable. I think Nico wanted to express
> "we tried to find but found none (i.e. NULL)" too and 1 means "no we
> have not tried".
Well, I could imagine I might have thought about something like that.
However, looking at the latest code in the master branch I can't see
any way for last_found to ever be assigned a NULL value. So if the
(void*)1 value might have been useful, it is certainly not anymore.
Nicolas
^ permalink raw reply
* Re: [PATCH] merge: add instructions to the commit message when editing
From: Thomas Rast @ 2012-01-31 7:46 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Thomas Rast, git
In-Reply-To: <7vhazcamdl.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> Thomas Rast <trast@inf.ethz.ch> writes:
>
>>> Please enter the commit message for your merge commit. Explain
>>> why the merge is necessary, especially if it merges an updated
>>> upstream into a topic branch.
>>>
>>> ... because people who need to be told to "justify it" would probably be
>>> helped by a more explicit "explain _why_ it is needed".
>>
>> Why not. The "explain..." might be construed as a bit too coercive, but
>> I cannot come up with a way to defuse it (well, except again tacking on
>> "you should") ...
>
> Would "Please enter the commit message for your merge commit, to explain
> why ..." work?
Yes, though it winds up as a rather long sentence. I could then shorten
it to
Please enter a commit message that explains why the merge commit is
necessary, especially if it merges an updated upstream into a topic
branch.
though that's only _implying_ that you're completing a merge.
Your pick ;-)
--
Thomas Rast
trast@{inf,student}.ethz.ch
^ permalink raw reply
* Re: gitk Wish hangs on Mac OS X 10.6.8
From: Matti Linnanvuori @ 2012-01-31 7:49 UTC (permalink / raw)
To: git
In-Reply-To: <E423F584-55C0-4A27-B3DD-48B78EDE1C79@portalify.com>
Hi!
gitk Wish occasionally hangs on Mac OS X 10.6.8. I have to force kill it to make it disappear. git version 1.7.8.4, too, has this bug.
regards, Matti Linnanvuori
^ permalink raw reply
* Re: Bug: "git checkout -b" should be allowed in empty repo
From: Michael Haggerty @ 2012-01-31 8:57 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v39axc9gp.fsf@alter.siamese.dyndns.org>
On 01/30/2012 07:48 PM, Junio C Hamano wrote:
> Michael Haggerty <mhagger@alum.mit.edu> writes:
>
>> [3] If commit 0000000 were treated specially, then there would be no
>> unborn branches but only branches pointing at the empty commit. In that
>> case, my expectation would change--the old branch should be left
>> pointing at 0000000. But currently git has no concept of an unborn
>> branch that is not HEAD.
>
> And it probably is not a good thing to add such. Under that constraints,
> HEAD that says refs/heads/foo where foo does not exist yet needs to be
> special cased at places where it matters.
>
> For that matter, even if we artificially created refs/heads/foo before any
> commit is made and made it point at 0{40}, you would need to add special
> cases to other parts of the system
No, the idea is to avoid special casing by making 0{40} into a real (but
empty) revision.
> (e.g. "commit" needs to notice that the
> result should be a root, not a child of 0{40};
No, commits that were previously generated as orphans *would* now be
generated as children of the special 0{40} commit.
> "checkout other_branch"
> needs to notice that it should refrain from running the equivalent of
> "read-tree -m HEAD other_branch" because HEAD does not point at a real
> tree;
No, it would merge the 0{40} commit with other_branch like usual,
resulting in the same contents as other_branch. Indeed, if other_branch
is also ultimately a descendant of 0{40}, this would be like a
fast-forward merge.
> etc.
This "etc" might include problems.
> so it does not change the fact that the unborn branch is case
> is special.
On the contrary, I believe that much special casing could be eliminated
and the UI made more uniform by treating everything as a descendant of a
special "NULL" commit.
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
^ permalink raw reply
* Re: Bug: "git checkout -b" should be allowed in empty repo
From: Johannes Sixt @ 2012-01-31 10:01 UTC (permalink / raw)
To: Michael Haggerty; +Cc: Junio C Hamano, git
In-Reply-To: <4F27ACED.2050709@alum.mit.edu>
Am 1/31/2012 9:57, schrieb Michael Haggerty:
> No, the idea is to avoid special casing by making 0{40} into a real (but
> empty) revision.
But then why not just have git init perform the equivalent of
c=$(echo "Start" | git commit-tree $empty_tree_sha1) &&
git update-ref refs/heads/master $c
People who dislike an empty initial commit can always use "git commit
--amend" for the first "real" commit.
-- Hannes
^ permalink raw reply
* Re: Bug: "git checkout -b" should be allowed in empty repo
From: Jakub Narebski @ 2012-01-31 10:09 UTC (permalink / raw)
To: Michael Haggerty; +Cc: Junio C Hamano, git
In-Reply-To: <4F27ACED.2050709@alum.mit.edu>
Michael Haggerty <mhagger@alum.mit.edu> writes:
> On 01/30/2012 07:48 PM, Junio C Hamano wrote:
>> Michael Haggerty <mhagger@alum.mit.edu> writes:
>>
>>> [3] If commit 0000000 were treated specially, then there would be no
>>> unborn branches but only branches pointing at the empty commit. In that
>>> case, my expectation would change--the old branch should be left
>>> pointing at 0000000. But currently git has no concept of an unborn
>>> branch that is not HEAD.
>>
>> And it probably is not a good thing to add such. Under that constraints,
>> HEAD that says refs/heads/foo where foo does not exist yet needs to be
>> special cased at places where it matters.
>>
>> For that matter, even if we artificially created refs/heads/foo before any
>> commit is made and made it point at 0{40}, you would need to add special
>> cases to other parts of the system
>
> No, the idea is to avoid special casing by making 0{40} into a real (but
> empty) revision.
>
>> (e.g. "commit" needs to notice that the
>> result should be a root, not a child of 0{40};
>
> No, commits that were previously generated as orphans *would* now be
> generated as children of the special 0{40} commit.
You would still have to have quite a bit of special cases about 0{40}
NUL commit. Perhaps less special cases, but new special cases.
[...]
>> so it does not change the fact that the unborn branch is case
>> is special.
>
> On the contrary, I believe that much special casing could be eliminated
> and the UI made more uniform by treating everything as a descendant of a
> special "NULL" commit.
I don't see how this can be done in backward-compatibile way.
Please note that in Git it is quite natural to have more than one root
(parentless) commit, even without presence of disconnected / orphan
branches. They are result of joining originally separate projects.
git.git has quite a few of them (more than 6, IIRC).
--
Jakub Narebski
^ permalink raw reply
* Re: Bug: "git checkout -b" should be allowed in empty repo
From: demerphq @ 2012-01-31 10:11 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Michael Haggerty, Junio C Hamano, git
In-Reply-To: <4F27BBED.9080902@viscovery.net>
On 31 January 2012 11:01, Johannes Sixt <j.sixt@viscovery.net> wrote:
> Am 1/31/2012 9:57, schrieb Michael Haggerty:
>> No, the idea is to avoid special casing by making 0{40} into a real (but
>> empty) revision.
>
> But then why not just have git init perform the equivalent of
>
> c=$(echo "Start" | git commit-tree $empty_tree_sha1) &&
> git update-ref refs/heads/master $c
>
> People who dislike an empty initial commit can always use "git commit
> --amend" for the first "real" commit.
Because it would then violate a system invariant that all commits are
descendants of the root commit.
You can model a git commit graph as a pathway through multidimensional
space of all possible commit trees. From that perspective it makes
sense that every pathway starts at the origin point of the
multidimensional space, which is conceptually the same as the proposed
root commit.
Anyway, I am not saying it should change, just that from some point of
views it makes a lot of sense.
Yves
--
perl -Mre=debug -e "/just|another|perl|hacker/"
^ permalink raw reply
* Disable merge conflicts on on non-conflicting changes to subsequent lines
From: Marcin Wiśnicki @ 2012-01-31 10:55 UTC (permalink / raw)
To: git
If two subsequent lines are changed in different branches, merging
will result in conflict event if there isn't any.
Invoking merge tool will mark file as resolved automatically.
Is there a way to disable this behavior ? I want the merge to happen
automatically if possible.
^ permalink raw reply
* [PATCH] pack-objects: convert to use parse_options()
From: Nguyễn Thái Ngọc Duy @ 2012-01-31 13:48 UTC (permalink / raw)
To: git; +Cc: Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin/pack-objects.c | 317 +++++++++++++++++++++---------------------------
1 files changed, 141 insertions(+), 176 deletions(-)
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 0f2e7b8..59fdb3f 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -18,16 +18,11 @@
#include "refs.h"
#include "thread-utils.h"
-static const char pack_usage[] =
- "git pack-objects [ -q | --progress | --all-progress ]\n"
- " [--all-progress-implied]\n"
- " [--max-pack-size=<n>] [--local] [--incremental]\n"
- " [--window=<n>] [--window-memory=<n>] [--depth=<n>]\n"
- " [--no-reuse-delta] [--no-reuse-object] [--delta-base-offset]\n"
- " [--threads=<n>] [--non-empty] [--revs [--unpacked | --all]]\n"
- " [--reflog] [--stdout | base-name] [--include-tag]\n"
- " [--keep-unreachable | --unpack-unreachable]\n"
- " [< ref-list | < object-list]";
+static const char *pack_usage[] = {
+ "git pack-objects --stdout [options...] [< ref-list | < object-list]",
+ "git pack-objects [options...] base-name [< ref-list | < object-list]",
+ NULL
+};
struct object_entry {
struct pack_idx_entry idx;
@@ -2305,183 +2300,140 @@ static void get_object_list(int ac, const char **av)
loosen_unused_packed_objects(&revs);
}
+static int option_parse_index_version(const struct option *opt,
+ const char *arg, int unset)
+{
+ char *c;
+ const char *val = arg;
+ pack_idx_opts.version = strtoul(val, &c, 10);
+ if (pack_idx_opts.version > 2)
+ die("unsupported index version %s", val);
+ if (*c == ',' && c[1])
+ pack_idx_opts.off32_limit = strtoul(c+1, &c, 0);
+ if (*c || pack_idx_opts.off32_limit & 0x80000000)
+ die("bad index version %s", val);
+ return 0;
+}
+
+static int option_parse_ulong(const struct option *opt,
+ const char *arg, int unset)
+{
+ if (unset)
+ die("option %s does not accept negative form",
+ opt->long_name);
+
+ if (!git_parse_ulong(arg, opt->value))
+ die("unable to parse value '%s' for option %s",
+ arg, opt->long_name);
+ return 0;
+}
+
+#define OPT_ULONG(s, l, v, h) \
+ { OPTION_CALLBACK, (s), (l), (v), "n", (h), \
+ PARSE_OPT_NONEG, option_parse_ulong }
+
int cmd_pack_objects(int argc, const char **argv, const char *prefix)
{
int use_internal_rev_list = 0;
int thin = 0;
int all_progress_implied = 0;
- uint32_t i;
- const char **rp_av;
- int rp_ac_alloc = 64;
- int rp_ac;
+ const char *rp_av[6];
+ int rp_ac = 0;
+ int rev_list_unpacked = 0, rev_list_all = 0, rev_list_reflog = 0;
+ struct option pack_objects_options[] = {
+ OPT_SET_INT('q', "quiet", &progress,
+ "do not show progress meter", 0),
+ OPT_SET_INT(0, "progress", &progress,
+ "show progress meter", 1),
+ OPT_SET_INT(0, "all-progress", &progress,
+ "show progress meter during object writing phase", 2),
+ OPT_BOOL(0, "all-progress-implied",
+ &all_progress_implied,
+ "similar to --all-progress when progress meter is shown"),
+ { OPTION_CALLBACK, 0, "index-version", NULL, "version",
+ "force generating pack index at a particular version",
+ 0, option_parse_index_version },
+ OPT_ULONG(0, "max-pack-size", &pack_size_limit,
+ "maximum size of each output pack file"),
+ OPT_BOOL(0, "local", &local,
+ "ignore borrowed objects from alternate object store"),
+ OPT_BOOL(0, "incremental", &incremental,
+ "ignore packed objects"),
+ OPT_INTEGER(0, "window", &window,
+ "limit pack window by objects"),
+ OPT_ULONG(0, "window-memory", &window_memory_limit,
+ "limit pack window by memory"),
+ OPT_INTEGER(0, "depth", &depth,
+ "limit pack window by maximum delta depth"),
+ OPT_BOOL(0, "reuse-delta", &reuse_delta,
+ "reusing existing deltas"),
+ OPT_BOOL(0, "reuse-object", &reuse_object,
+ "reusing existing objects"),
+ OPT_BOOL(0, "delta-base-offset", &allow_ofs_delta,
+ "use OFS_DELTA objects"),
+ OPT_INTEGER(0, "threads", &delta_search_threads,
+ "use threads when searching for best delta matches"),
+ OPT_BOOL(0, "non-empty", &non_empty,
+ "only create if it would contain at least one object"),
+ OPT_BOOL(0, "revs", &use_internal_rev_list,
+ "read revision arguments from standard output"),
+ { OPTION_SET_INT, 0, "unpacked", &rev_list_unpacked, NULL,
+ "limit the objects to those that are not already packed",
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 },
+ { OPTION_SET_INT, 0, "all", &rev_list_all, NULL,
+ "include all refs under $GIT_DIR/refs directory",
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 },
+ { OPTION_SET_INT, 0, "reflog", &rev_list_reflog, NULL,
+ "include objects referred by reflog entries",
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 },
+ OPT_BOOL(0, "stdout", &pack_to_stdout,
+ "output pack to stdout"),
+ OPT_BOOL(0, "include-tag", &include_tag,
+ "include unasked-for annotated tags"),
+ OPT_BOOL(0, "keep-unreachable", &keep_unreachable,
+ "keep unreachable objects"),
+ OPT_BOOL(0, "unpack-unreachable", &unpack_unreachable,
+ "unpack unreachable objects"),
+ OPT_BOOL(0, "thin", &thin,
+ "create thin packs"),
+ OPT_BOOL(0, "honor-pack-keep", &ignore_packed_keep,
+ "ignore packs that have companion .keep file"),
+ OPT_INTEGER(0, "compression", &pack_compression_level,
+ "pack compression level"),
+ OPT_SET_INT(0, "keep-true-parents", &grafts_replace_parents,
+ "do not hide commits by grafts", 0),
+ OPT_END(),
+ };
read_replace_refs = 0;
- rp_av = xcalloc(rp_ac_alloc, sizeof(*rp_av));
-
- rp_av[0] = "pack-objects";
- rp_av[1] = "--objects"; /* --thin will make it --objects-edge */
- rp_ac = 2;
-
reset_pack_idx_option(&pack_idx_opts);
git_config(git_pack_config, NULL);
if (!pack_compression_seen && core_compression_seen)
pack_compression_level = core_compression_level;
progress = isatty(2);
- for (i = 1; i < argc; i++) {
- const char *arg = argv[i];
+ argc = parse_options(argc, argv, prefix, pack_objects_options,
+ pack_usage, 0);
- if (*arg != '-')
- break;
+ rp_av[rp_ac++] = "pack-objects";
+ if (thin) {
+ use_internal_rev_list = 1;
+ rp_av[rp_ac++] = "--objects-edge";
+ } else
+ rp_av[rp_ac++] = "--objects";
- if (!strcmp("--non-empty", arg)) {
- non_empty = 1;
- continue;
- }
- if (!strcmp("--local", arg)) {
- local = 1;
- continue;
- }
- if (!strcmp("--incremental", arg)) {
- incremental = 1;
- continue;
- }
- if (!strcmp("--honor-pack-keep", arg)) {
- ignore_packed_keep = 1;
- continue;
- }
- if (!prefixcmp(arg, "--compression=")) {
- char *end;
- int level = strtoul(arg+14, &end, 0);
- if (!arg[14] || *end)
- usage(pack_usage);
- if (level == -1)
- level = Z_DEFAULT_COMPRESSION;
- else if (level < 0 || level > Z_BEST_COMPRESSION)
- die("bad pack compression level %d", level);
- pack_compression_level = level;
- continue;
- }
- if (!prefixcmp(arg, "--max-pack-size=")) {
- pack_size_limit_cfg = 0;
- if (!git_parse_ulong(arg+16, &pack_size_limit))
- usage(pack_usage);
- continue;
- }
- if (!prefixcmp(arg, "--window=")) {
- char *end;
- window = strtoul(arg+9, &end, 0);
- if (!arg[9] || *end)
- usage(pack_usage);
- continue;
- }
- if (!prefixcmp(arg, "--window-memory=")) {
- if (!git_parse_ulong(arg+16, &window_memory_limit))
- usage(pack_usage);
- continue;
- }
- if (!prefixcmp(arg, "--threads=")) {
- char *end;
- delta_search_threads = strtoul(arg+10, &end, 0);
- if (!arg[10] || *end || delta_search_threads < 0)
- usage(pack_usage);
-#ifdef NO_PTHREADS
- if (delta_search_threads != 1)
- warning("no threads support, "
- "ignoring %s", arg);
-#endif
- continue;
- }
- if (!prefixcmp(arg, "--depth=")) {
- char *end;
- depth = strtoul(arg+8, &end, 0);
- if (!arg[8] || *end)
- usage(pack_usage);
- continue;
- }
- if (!strcmp("--progress", arg)) {
- progress = 1;
- continue;
- }
- if (!strcmp("--all-progress", arg)) {
- progress = 2;
- continue;
- }
- if (!strcmp("--all-progress-implied", arg)) {
- all_progress_implied = 1;
- continue;
- }
- if (!strcmp("-q", arg)) {
- progress = 0;
- continue;
- }
- if (!strcmp("--no-reuse-delta", arg)) {
- reuse_delta = 0;
- continue;
- }
- if (!strcmp("--no-reuse-object", arg)) {
- reuse_object = reuse_delta = 0;
- continue;
- }
- if (!strcmp("--delta-base-offset", arg)) {
- allow_ofs_delta = 1;
- continue;
- }
- if (!strcmp("--stdout", arg)) {
- pack_to_stdout = 1;
- continue;
- }
- if (!strcmp("--revs", arg)) {
- use_internal_rev_list = 1;
- continue;
- }
- if (!strcmp("--keep-unreachable", arg)) {
- keep_unreachable = 1;
- continue;
- }
- if (!strcmp("--unpack-unreachable", arg)) {
- unpack_unreachable = 1;
- continue;
- }
- if (!strcmp("--include-tag", arg)) {
- include_tag = 1;
- continue;
- }
- if (!strcmp("--unpacked", arg) ||
- !strcmp("--reflog", arg) ||
- !strcmp("--all", arg)) {
- use_internal_rev_list = 1;
- if (rp_ac >= rp_ac_alloc - 1) {
- rp_ac_alloc = alloc_nr(rp_ac_alloc);
- rp_av = xrealloc(rp_av,
- rp_ac_alloc * sizeof(*rp_av));
- }
- rp_av[rp_ac++] = arg;
- continue;
- }
- if (!strcmp("--thin", arg)) {
- use_internal_rev_list = 1;
- thin = 1;
- rp_av[1] = "--objects-edge";
- continue;
- }
- if (!prefixcmp(arg, "--index-version=")) {
- char *c;
- pack_idx_opts.version = strtoul(arg + 16, &c, 10);
- if (pack_idx_opts.version > 2)
- die("bad %s", arg);
- if (*c == ',')
- pack_idx_opts.off32_limit = strtoul(c+1, &c, 0);
- if (*c || pack_idx_opts.off32_limit & 0x80000000)
- die("bad %s", arg);
- continue;
- }
- if (!strcmp(arg, "--keep-true-parents")) {
- grafts_replace_parents = 0;
- continue;
- }
- usage(pack_usage);
+ if (rev_list_unpacked) {
+ use_internal_rev_list = 1;
+ rp_av[rp_ac++] = "--unpacked";
+ }
+ if (rev_list_all) {
+ use_internal_rev_list = 1;
+ rp_av[rp_ac++] = "--all";
+ }
+ if (rev_list_reflog) {
+ use_internal_rev_list = 1;
+ rp_av[rp_ac++] = "--reflog";
}
/* Traditionally "pack-objects [options] base extra" failed;
@@ -2497,12 +2449,25 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
* walker.
*/
- if (!pack_to_stdout)
- base_name = argv[i++];
-
- if (pack_to_stdout != !base_name)
- usage(pack_usage);
+ if (!pack_to_stdout) {
+ if (!argc)
+ die("base name required if --stdout is not given");
+ base_name = argv[0];
+ argc--;
+ }
+ if (argc)
+ die("base name or --stdout are mutually exclusive");
+ if (!reuse_object)
+ reuse_delta = 0;
+ if (pack_compression_level == -1)
+ pack_compression_level = Z_DEFAULT_COMPRESSION;
+ else if (pack_compression_level < 0 || pack_compression_level > Z_BEST_COMPRESSION)
+ die("bad pack compression level %d", pack_compression_level);
+#ifdef NO_PTHREADS
+ if (delta_search_threads != 1)
+ warning("no threads support, ignoring %s", arg);
+#endif
if (!pack_to_stdout && !pack_size_limit)
pack_size_limit = pack_size_limit_cfg;
if (pack_to_stdout && pack_size_limit)
--
1.7.8.36.g69ee2
^ permalink raw reply related
* [PATCH] Correct singular form in diff summary line for human interaction
From: Nguyễn Thái Ngọc Duy @ 2012-01-31 14:24 UTC (permalink / raw)
To: git
Cc: Ævar Arnfjörð Bjarmason, Frederik Schwarzer,
Junio C Hamano, Nguyễn Thái Ngọc Duy
"git diff --stat" and "git apply --stat" now learn to print the line
"%d files changed, %d insertions(+), %d deletions(-)" in singular form
whenever applicable.
This change uncondtionally would upset scripts because scripts are not
nice. They simply hate changes. They can be very hostile when that
happens. So only adjust the line for human consumption.
Convenient function interactive_use() is added for this purpose. The
command thinks it's in human hands when:
- GIT_SCRIPTING environment variable is not set
- pager is on or
- both stdout and stderr point to tty device
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
The third attempt in the last couple months to remove three "s" in
one line. I did not upset the test suite with this and hopefully
won't upset any scripts around. Good start?
builtin/apply.c | 3 ++-
cache.h | 1 +
diff.c | 33 ++++++++++++++++++++++++++++-----
diff.h | 3 +++
| 7 +++++++
5 files changed, 41 insertions(+), 6 deletions(-)
diff --git a/builtin/apply.c b/builtin/apply.c
index c24dc54..389898f 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -14,6 +14,7 @@
#include "builtin.h"
#include "string-list.h"
#include "dir.h"
+#include "diff.h"
#include "parse-options.h"
/*
@@ -3241,7 +3242,7 @@ static void stat_patch_list(struct patch *patch)
show_stats(patch);
}
- printf(" %d files changed, %d insertions(+), %d deletions(-)\n", files, adds, dels);
+ print_stat_summary(stdout, files, adds, dels);
}
static void numstat_patch_list(struct patch *patch)
diff --git a/cache.h b/cache.h
index 10afd71..7e0bb2b 100644
--- a/cache.h
+++ b/cache.h
@@ -1175,6 +1175,7 @@ extern void setup_pager(void);
extern const char *pager_program;
extern int pager_in_use(void);
extern int pager_use_color;
+extern int interactive_use(void);
extern const char *editor_program;
extern const char *askpass_program;
diff --git a/diff.c b/diff.c
index 7e15426..2d63e9c 100644
--- a/diff.c
+++ b/diff.c
@@ -1322,6 +1322,32 @@ static void fill_print_name(struct diffstat_file *file)
file->print_name = pname;
}
+int print_stat_summary(FILE *fp, int files, int insertions, int deletions)
+{
+ struct strbuf sb = STRBUF_INIT;
+ int ret;
+
+ if (!interactive_use())
+ return fprintf(fp, " %d files changed, %d insertions(+), %d deletions(-)\n",
+ files, insertions, deletions);
+
+ strbuf_addf(&sb,
+ ngettext(" %d file changed,", " %d files changed,",
+ files),
+ files);
+ strbuf_addf(&sb,
+ ngettext(" %d insertion(+),", " %d insertions(+),",
+ insertions),
+ insertions);
+ strbuf_addf(&sb,
+ ngettext(" %d deletion(-)\n", " %d deletions(-)\n",
+ deletions),
+ deletions);
+ ret = fputs(sb.buf, fp);
+ strbuf_release(&sb);
+ return ret;
+}
+
static void show_stats(struct diffstat_t *data, struct diff_options *options)
{
int i, len, add, del, adds = 0, dels = 0;
@@ -1475,9 +1501,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
extra_shown = 1;
}
fprintf(options->file, "%s", line_prefix);
- fprintf(options->file,
- " %d files changed, %d insertions(+), %d deletions(-)\n",
- total_files, adds, dels);
+ print_stat_summary(options->file, total_files, adds, dels);
}
static void show_shortstats(struct diffstat_t *data, struct diff_options *options)
@@ -1507,8 +1531,7 @@ static void show_shortstats(struct diffstat_t *data, struct diff_options *option
options->output_prefix_data);
fprintf(options->file, "%s", msg->buf);
}
- fprintf(options->file, " %d files changed, %d insertions(+), %d deletions(-)\n",
- total_files, adds, dels);
+ print_stat_summary(options->file, total_files, adds, dels);
}
static void show_numstat(struct diffstat_t *data, struct diff_options *options)
diff --git a/diff.h b/diff.h
index ae71f4c..7af5f1e 100644
--- a/diff.h
+++ b/diff.h
@@ -324,4 +324,7 @@ extern struct userdiff_driver *get_textconv(struct diff_filespec *one);
extern int parse_rename_score(const char **cp_p);
+extern int print_stat_summary(FILE *fp, int files,
+ int insertions, int deletions);
+
#endif /* DIFF_H */
--git a/pager.c b/pager.c
index 975955b..9a3d3d8 100644
--- a/pager.c
+++ b/pager.c
@@ -110,3 +110,10 @@ int pager_in_use(void)
env = getenv("GIT_PAGER_IN_USE");
return env ? git_config_bool("GIT_PAGER_IN_USE", env) : 0;
}
+
+int interactive_use(void)
+{
+ const char *env;
+ env = getenv("GIT_SCRIPTING");
+ return !env && (pager_in_use() || (isatty(1) && isatty(2)));
+}
--
1.7.8.36.g69ee2
^ permalink raw reply related
* Alternates corruption issue
From: Richard Purdie @ 2012-01-31 14:05 UTC (permalink / raw)
To: GIT Mailing-list; +Cc: Hart, Darren, Ashfield, Bruce
I have a problem with git clone commands using alternates failing by
mixing up different repositories. I have a situation where I could end
up with both:
/srv/mirrors/repo
/srv/mirrors/repo.git
as bare clones.
I then try cloning "repo" with alternates with the command:
$ git clone -s -n /srv/mirrors/repo /tmp/foo
Cloning into /tmp/foo...
done.
$ cat /tmp/foo/.git/objects/info/alternates
/srv/mirrors/repo.git/objects
Note how I'm now referencing repo.git, not repo. This doesn't work as
expected giving some very bizarre results when actually using the
repository.
I appreciate this is a rather bizarre corner case but its one that is
breaking the build system I work with. Ideally people would use a
consistent URL for the same repository but we have an example where they
haven't and this really shouldn't break like this.
Looking at the code, the cause seems to be
clone.c:get_repo_path():
static char *suffix[] = { "/.git", ".git", "" };
since its looking in order for:
repo/.git (fails)
repo.git (suceeds, incorrect)
repo (never looked at)
I'm not sure what would break if that order were to change, swapping the
last two options.
I can "force" the issue by running:
git clone -s -n /srv/mirrors/repo/ /tmp/foo
but this results in the slightly odd looking:
$ cat /tmp/foo/.git/objects/info/alternates
/srv/mirrors/repo//objects
which does at least work.
Any idea if its possible to fix the root cause of this problem?
Cheers,
Richard
^ permalink raw reply
* [PATCH/RFC v3] grep: Add the option '--exclude'
From: Albert Yale @ 2012-01-31 14:45 UTC (permalink / raw)
To: git; +Cc: gitster, Albert Yale
[PATCH/RFC v3] grep: Add the option '--exclude'
Signed-off-by: Albert Yale <surfingalbert@gmail.com>
---
Here's my latest progress towards a cleaner implementation.
Albert Yale
Documentation/git-grep.txt | 7 +++
builtin/grep.c | 41 +++++++++++++--
cache.h | 3 +
dir.c | 126 +++++++++++++++++++++++++++++++++++++------
dir.h | 3 +-
read-cache.c | 2 +-
6 files changed, 158 insertions(+), 24 deletions(-)
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index 6a8b1e3..67a83aa 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -22,6 +22,7 @@ SYNOPSIS
[--color[=<when>] | --no-color]
[-A <post-context>] [-B <pre-context>] [-C <context>]
[-f <file>] [-e] <pattern>
+ [-x <pattern>|--exclude <pattern>]
[--and|--or|--not|(|)|-e <pattern>...]
[ [--exclude-standard] [--cached | --no-index | --untracked] | <tree>...]
[--] [<pathspec>...]
@@ -124,6 +125,12 @@ OPTIONS
Use fixed strings for patterns (don't interpret pattern
as a regex).
+-x <pattern>::
+--exclude <pattern>::
+ In addition to those found in .gitignore (per directory) and
+ $GIT_DIR/info/exclude, also consider these patterns to be in the
+ set of the ignore rules in effect.
+
-n::
--line-number::
Prefix the line number to matching lines.
diff --git a/builtin/grep.c b/builtin/grep.c
index 9ce064a..e9e1ac1 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -528,7 +528,8 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int
struct cache_entry *ce = active_cache[nr];
if (!S_ISREG(ce->ce_mode))
continue;
- if (!match_pathspec_depth(pathspec, ce->name, ce_namelen(ce), 0, NULL))
+ if (!match_pathspec_depth(pathspec, ce->name, ce_namelen(ce),
+ 0, NULL, 1))
continue;
/*
* If CE_VALID is on, we assume worktree file and its cache entry
@@ -566,6 +567,11 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
while (tree_entry(tree, &entry)) {
int te_len = tree_entry_len(&entry);
+ if (match_pathspec_depth(pathspec->exclude,
+ entry.path, strlen(entry.path),
+ 0, NULL, 0))
+ continue;
+
if (match != all_entries_interesting) {
match = tree_entry_interesting(&entry, base, tn_len, pathspec);
if (match == all_entries_not_interesting)
@@ -606,8 +612,17 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
struct object *obj, const char *name)
{
- if (obj->type == OBJ_BLOB)
+ if (obj->type == OBJ_BLOB) {
+ const char *name_without_sha1 = strchr(name, ':') + 1;
+
+ if (match_pathspec_depth(pathspec->exclude,
+ name_without_sha1,
+ strlen(name_without_sha1),
+ 0, NULL, 0))
+ return 0;
+
return grep_sha1(opt, obj->sha1, name, 0);
+ }
if (obj->type == OBJ_COMMIT || obj->type == OBJ_TREE) {
struct tree_desc tree;
void *data;
@@ -671,7 +686,7 @@ static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec,
for (i = 0; i < dir.nr; i++) {
const char *name = dir.entries[i]->name;
int namelen = strlen(name);
- if (!match_pathspec_depth(pathspec, name, namelen, 0, NULL))
+ if (!match_pathspec_depth(pathspec, name, namelen, 0, NULL, 1))
continue;
hit |= grep_file(opt, dir.entries[i]->name);
if (hit && opt->status_only)
@@ -764,6 +779,14 @@ static int pattern_callback(const struct option *opt, const char *arg,
return 0;
}
+static int exclude_cb(const struct option *opt, const char *arg,
+ int unset)
+{
+ struct string_list *exclude_list = opt->value;
+ string_list_append(exclude_list, arg);
+ return 0;
+}
+
static int help_callback(const struct option *opt, const char *arg, int unset)
{
return -1;
@@ -792,7 +815,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
pattern_type_pcre,
};
int pattern_type = pattern_type_unspecified;
-
+ struct string_list exclude_list = STRING_LIST_INIT_NODUP;
struct option options[] = {
OPT_BOOLEAN(0, "cached", &cached,
"search in index instead of in the work tree"),
@@ -872,6 +895,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
"read patterns from file", file_callback),
{ OPTION_CALLBACK, 'e', NULL, &opt, "pattern",
"match <pattern>", PARSE_OPT_NONEG, pattern_callback },
+ { OPTION_CALLBACK, 'x', "exclude", &exclude_list, "pattern",
+ "add <pattern> to ignore rules", PARSE_OPT_NONEG, exclude_cb },
{ OPTION_CALLBACK, 0, "and", &opt, NULL,
"combine patterns specified with -e",
PARSE_OPT_NOARG | PARSE_OPT_NONEG, and_callback },
@@ -1053,6 +1078,12 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
pathspec.max_depth = opt.max_depth;
pathspec.recursive = 1;
+ if (exclude_list.nr) {
+ add_pathspec_item_from_string_list(pathspec.exclude, &exclude_list);
+ pathspec.exclude->max_depth = opt.max_depth;
+ pathspec.exclude->recursive = 1;
+ }
+
if (show_in_pager && (cached || list.nr))
die(_("--open-files-in-pager only works on the worktree"));
@@ -1102,5 +1133,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
if (hit && show_in_pager)
run_pager(&opt, prefix);
free_grep_patterns(&opt);
+ free_pathspec(&pathspec);
+ string_list_clear(&exclude_list, 0);
return !hit;
}
diff --git a/cache.h b/cache.h
index 9bd8c2d..683458a 100644
--- a/cache.h
+++ b/cache.h
@@ -533,9 +533,12 @@ struct pathspec {
int len;
unsigned int use_wildcard:1;
} *items;
+
+ struct pathspec *exclude; /* This is never NULL. */
};
extern int init_pathspec(struct pathspec *, const char **);
+extern int add_pathspec_item_from_string_list(struct pathspec *, const struct string_list *);
extern void free_pathspec(struct pathspec *);
extern int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec);
diff --git a/dir.c b/dir.c
index 0a78d00..9e4312c 100644
--- a/dir.c
+++ b/dir.c
@@ -9,6 +9,8 @@
#include "dir.h"
#include "refs.h"
+#include "string-list.h"
+
struct path_simplify {
int len;
const char *path;
@@ -253,34 +255,47 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,
*/
int match_pathspec_depth(const struct pathspec *ps,
const char *name, int namelen,
- int prefix, char *seen)
+ int prefix, char *seen,
+ int empty_pathspec_can_match)
{
int i, retval = 0;
+ const char *name_without_prefix = name + prefix;
+ int namelen_without_prefix = namelen - prefix;
if (!ps->nr) {
- if (!ps->recursive || ps->max_depth == -1)
- return MATCHED_RECURSIVELY;
+ if (empty_pathspec_can_match) {
+ if (match_pathspec_depth(ps->exclude,
+ name, namelen,
+ prefix, seen, 0))
+ return 0;
- if (within_depth(name, namelen, 0, ps->max_depth))
- return MATCHED_EXACTLY;
+ if (!ps->recursive || ps->max_depth == -1)
+ return MATCHED_RECURSIVELY;
+
+ if (within_depth(name, namelen, 0, ps->max_depth))
+ return MATCHED_EXACTLY;
+ else
+ return 0;
+ }
else
return 0;
}
- name += prefix;
- namelen -= prefix;
-
for (i = ps->nr - 1; i >= 0; i--) {
int how;
if (seen && seen[i] == MATCHED_EXACTLY)
continue;
- how = match_pathspec_item(ps->items+i, prefix, name, namelen);
+ how = match_pathspec_item(ps->items+i, prefix,
+ name_without_prefix,
+ namelen_without_prefix);
if (ps->recursive && ps->max_depth != -1 &&
how && how != MATCHED_FNMATCH) {
int len = ps->items[i].len;
- if (name[len] == '/')
+ if (name_without_prefix[len] == '/')
len++;
- if (within_depth(name+len, namelen-len, 0, ps->max_depth))
+ if (within_depth(name_without_prefix+len,
+ namelen_without_prefix-len,
+ 0, ps->max_depth))
how = MATCHED_EXACTLY;
else
how = 0;
@@ -292,6 +307,12 @@ int match_pathspec_depth(const struct pathspec *ps,
seen[i] = how;
}
}
+
+ if (retval && match_pathspec_depth(ps->exclude,
+ name, namelen,
+ prefix, seen, 0))
+ return 0;
+
return retval;
}
@@ -1259,12 +1280,79 @@ static int pathspec_item_cmp(const void *a_, const void *b_)
return strcmp(a->match, b->match);
}
+static int init_pathspec_item(struct pathspec_item *item, const char *path)
+{
+ item->match = path;
+ item->len = strlen(path);
+ item->use_wildcard = !no_wildcard(path);
+
+ return item->use_wildcard;
+}
+
+int add_pathspec_item_from_string_list(struct pathspec *pathspec,
+ const struct string_list *path_list)
+{
+ int i;
+ struct pathspec_item *new_items;
+ int previous_items_count = pathspec->nr;
+
+ if (!path_list->nr)
+ return 0;
+
+ pathspec->nr += path_list->nr;
+
+ if (previous_items_count)
+ pathspec->items = xrealloc(pathspec->items,
+ sizeof(struct pathspec_item)*pathspec->nr);
+ else
+ pathspec->items = xcalloc(pathspec->nr, sizeof(struct pathspec_item));
+
+ new_items = pathspec->items + previous_items_count;
+
+ for (i = 0; i < path_list->nr; i++) {
+ struct pathspec_item *item = new_items+i;
+ const char *path = path_list->items[i].string;
+
+ pathspec->has_wildcard |= init_pathspec_item(item, path);
+ }
+
+ /*
+ * Give the pathspec a pathspec->exclude so we can test
+ * pathspec->exclude->nr without testing the validity of
+ * pathspec->exclude first.
+ */
+ if (!pathspec->exclude)
+ pathspec->exclude = xcalloc(1, sizeof(*pathspec));
+
+ qsort(pathspec->items, pathspec->nr,
+ sizeof(struct pathspec_item), pathspec_item_cmp);
+
+ /*
+ * Please comment/review:
+ *
+ * Here, pathspec->raw is NULL despite pathspec->nr being non-zero.
+ *
+ * Usually, a NULL pathspec->raw implies that pathspec->nr is zero.
+ *
+ * A problem might arrise if other areas of the code assume that a
+ * NULL pathspec->raw means that pathspec->nr is zero, or vice-versa.
+ */
+
+ return 0;
+}
+
int init_pathspec(struct pathspec *pathspec, const char **paths)
{
const char **p = paths;
int i;
memset(pathspec, 0, sizeof(*pathspec));
+ /*
+ * We create pathspec->exclude unconditionally so that we don't have
+ * to test the validity of pathspec->exclude before using the value
+ * of pathspec->exclude->nr.
+ */
+ pathspec->exclude = xcalloc(1, sizeof(*pathspec));
if (!p)
return 0;
while (*p)
@@ -1279,11 +1367,7 @@ int init_pathspec(struct pathspec *pathspec, const char **paths)
struct pathspec_item *item = pathspec->items+i;
const char *path = paths[i];
- item->match = path;
- item->len = strlen(path);
- item->use_wildcard = !no_wildcard(path);
- if (item->use_wildcard)
- pathspec->has_wildcard = 1;
+ pathspec->has_wildcard |= init_pathspec_item(item, path);
}
qsort(pathspec->items, pathspec->nr,
@@ -1294,6 +1378,12 @@ int init_pathspec(struct pathspec *pathspec, const char **paths)
void free_pathspec(struct pathspec *pathspec)
{
- free(pathspec->items);
- pathspec->items = NULL;
+ if (pathspec->items) {
+ free(pathspec->items);
+ pathspec->items = NULL;
+ }
+ if (pathspec->exclude) {
+ free_pathspec(pathspec->exclude);
+ pathspec->exclude = NULL;
+ }
}
diff --git a/dir.h b/dir.h
index dd6947e..2b9870d 100644
--- a/dir.h
+++ b/dir.h
@@ -68,7 +68,8 @@ extern char *common_prefix(const char **pathspec);
extern int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen);
extern int match_pathspec_depth(const struct pathspec *pathspec,
const char *name, int namelen,
- int prefix, char *seen);
+ int prefix, char *seen,
+ int empty_pathspec_can_match);
extern int within_depth(const char *name, int namelen, int depth, int max_depth);
extern int fill_directory(struct dir_struct *dir, const char **pathspec);
diff --git a/read-cache.c b/read-cache.c
index a51bba1..9783c4f 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -708,7 +708,7 @@ int ce_same_name(struct cache_entry *a, struct cache_entry *b)
int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec)
{
- return match_pathspec_depth(pathspec, ce->name, ce_namelen(ce), 0, NULL);
+ return match_pathspec_depth(pathspec, ce->name, ce_namelen(ce), 0, NULL, 1);
}
/*
--
1.7.8.3
^ permalink raw reply related
* Re: [BUG] git clean -X skips a directory containing only ignored files
From: Michael Schubert @ 2012-01-31 14:47 UTC (permalink / raw)
To: Paul Berry; +Cc: git
In-Reply-To: <CA+yLL67J-7U9z7HVvq5wTc1g4_UCtqYfEyqdt7XR5zDqvQN5NA@mail.gmail.com>
On 01/31/2012 12:36 AM, Paul Berry wrote:
> I am trying to use "git clean -X" to remove object files (which
> are gitignored) from my source tree, but it appears to miss
> object files that are in a subdirectory without any git-tracked
> files:
>
> $ git init test
> Initialized empty Git repository in /home/pberry/tmp/test/.git/
> $ cd test
> $ mkdir foo
> $ touch foo/bar.o
> $ echo '*.o' > .gitignore
> $ git add .gitignore
> $ git commit -mgitignore
> [master (root-commit) 6b5ffcb] gitignore
> 1 files changed, 1 insertions(+), 0 deletions(-)
> create mode 100644 .gitignore
> $ git status
> # On branch master
> nothing to commit (working directory clean)
> $ git clean -d -X -f
> $ ls foo
> bar.o
>
> It seems to me that bar.o should have been removed, because
> according to the git-clean docs, -X means "Remove only files
> ignored by git", and bar.o is definitely being ignored by git.
>
>
> It looks like a very similar bug was reported back in 2010, but
> not fixed:
> http://git.661346.n2.nabble.com/BUG-git-clean-X-behaviour-when-gitignore-has-sub-directory-entries-td5575307.html.
> I've confirmed that the workaround mentioned by Jonathan Nieder
> in that thread fixes my problem too (removing "dir.flags |=
> DIR_SHOW_OTHER_DIRECTORIES;" from builtin/clean.c). However I'm
> guessing from Jonathan's comments that it would be better to fix
> this bug elsewhere (somewhere in dir.c perhaps).
Removing DIR_SHOW_OTHER_DIRECTORIES just happens to not trigger
this particular "bug" but breaks pretty much everything else.
As a workaround, you could explicitly add the directory to your
gitignore file.
Here's a test:
-- >8 --
Subject: [PATCH] t7300-clean: show known breakage with "git clean -d -X"
"git clean -d -X" fails for directories containing only untracked files.
Example:
$ ls -R .
.:
foo
./foo:
bar.o
$ cat .gitignore
*.o
$ git clean -d -X -f
$ ! test -d foo || echo fail
Reported-by: Paul Berry <stereotype441@gmail.com>
Signed-off-by: Michael Schubert <mschub@elegosoft.com>
---
t/t7300-clean.sh | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index 800b536..0b6d545 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -332,6 +332,13 @@ test_expect_success 'git clean -d -X' '
'
+test_expect_failure 'git clean -d -X' '
+ mkdir -p a/b &&
+ touch a/b/c.o &&
+ git clean -d -X &&
+ ! test -d a
+'
+
test_expect_success 'clean.requireForce defaults to true' '
git config --unset clean.requireForce &&
--
1.7.9.174.g356eff6
^ permalink raw reply related
* Re: [PATCH] Correct singular form in diff summary line for human interaction
From: Jonathan Nieder @ 2012-01-31 15:20 UTC (permalink / raw)
To: Nguyễn Thái Ngọc Duy
Cc: git, Ævar Arnfjörð Bjarmason, Frederik Schwarzer,
Junio C Hamano
In-Reply-To: <1328019840-6168-1-git-send-email-pclouds@gmail.com>
Hi,
Nguyễn Thái Ngọc Duy wrote:
> Convenient function interactive_use() is added for this purpose. The
> command thinks it's in human hands when:
I admit I really dislike this, especially:
> - GIT_SCRIPTING environment variable is not set
If my GUI app was parsing diffstats to convert them into a visual
representation, as a novice it may not be obvious to me where to find
the menu entry file to set this envvar in.
But maybe I'm not the right person to ask, since I'd be okay with
removing the "s"es (with an appropriate incubation time to discover
whether we are introducing a regression) unconditionally.
If there is an environment variable to say "I don't want to see
variations on strings intended for humans", can it be spelled as
LC_ALL=C?
Just my two cents,
Jonathan
^ permalink raw reply
* Re: Bug: "git checkout -b" should be allowed in empty repo
From: Michael Haggerty @ 2012-01-31 16:32 UTC (permalink / raw)
To: Jakub Narebski; +Cc: Junio C Hamano, git, demerphq
In-Reply-To: <m3k448che9.fsf@localhost.localdomain>
On 01/31/2012 11:09 AM, Jakub Narebski wrote:
> I don't see how this can be done in backward-compatibile way.
Yes, backwards compatibility would probably prevent the NULL commit idea
from ever being implemented in a literal way.
But it is conceivable that it could be faked with some strategic
if sha1 == '0'*40:
treat_as_special_null_commit
elif len(parents) == 0:
parents = ['0'*40]
In other words, include a little special case fakery in the data
structures near root commits (an O(1) amount of work) to avoid special
cases in all commands that can touch root commits (an O(number of
commands) amount of work).
Alternatively, the NULL commit could be a UI construct that has no
manifestation in the object model. This would not save implementation
work, but would perhaps give a more consistent way to deal with root
commits in the UI than the current array of --orphan etc. options.
> Please note that in Git it is quite natural to have more than one root
> (parentless) commit, even without presence of disconnected / orphan
> branches. They are result of joining originally separate projects.
> git.git has quite a few of them (more than 6, IIRC).
I don't see the problem, unless you mean that it would be difficult to
merge repositories that don't link back to a NULL commit with
hypothetical future repositories that do include a NULL commit. But a
world in which two kinds of repositories have to be supported is
pointless anyway, because then the git code would have to include *both*
kinds of special cases and nothing would be gained.
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
^ 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