Git development
 help / color / mirror / Atom feed
* Re: [PATCH v6 00/11] Column display
From: Nguyen Thai Ngoc Duy @ 2012-02-27  0:40 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vaa45dwq7.fsf@alter.siamese.dyndns.org>

2012/2/27 Junio C Hamano <gitster@pobox.com>:
> But I am very much reluctant to see us adding a "git column" subcommand; I
> cannot justify it myself because what it does is even less connected to
> git than the "--no-index" mode of grep/diff commands, i.e. it does not
> have much to do with "Git, the version control system".
>
> Shouldn't it be "test-column" that is useful during the hacking, much like
> "test-date", "test-chmtime", and "test_credential"?

It used to be test-column. But we would need an external program to
pipe through to minimize changing display code, especially when
display code can get complicated (e.g. git-tag for example). The other
reason is to get column display even when the command does not support
it (e.g. GIT_PAGER="git column" git diff --name-status HEAD~10)
-- 
Duy

^ permalink raw reply

* Re: sha-1 check in rev-list --verify-objects redundant?
From: Nguyen Thai Ngoc Duy @ 2012-02-27  0:48 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <7v1uphff8o.fsf@alter.siamese.dyndns.org>

On Mon, Feb 27, 2012 at 4:37 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Nguyen Thai Ngoc Duy <pclouds@gmail.com> writes:
>
>> On the well-formedness, unless I'm mistaken, --verify-objects is
>> _always_ used in conjunction with index-pack.
>
> Hmm, you are making my head hurt.  Is the above "always" a typo of
> "never"?
>
> The static check_everything_connected() function in builtin/fetch.c is a
> direct callsite of "rev-list --verify-objects", and the function is used
> in two codepaths:
>
>  * store_updated_refs() that is used after we receive and store objects
>   from the other end.  We may or may not have run index-pack in this
>   codepath; in either case we need to make sure the other side did send
>   everything that is needed to complete the history between what we used
>   to have and what they claimed to supply us, to protect us from a broken
>   remote side.

I stand corrected. --verify-objects is _usually_ used in conjunction
with index-pack, when the media is a pack (i.e. no remote helpers)

>  * quickfetch() that is called even before we get any object from the
>   other end, to optimize the transfer when we already have what we need.
>
> The latter is the original use to protect against unconnected island of
> chain I explained in the previous message, but the former is also abot the
> same protection, in a different callchain.

I think we can trust what we already have, so in the latter case (and
the former when the medium is a pack), --objects should suffice.

> In both cases, the check by --verify-objects is about completeness of the
> history (is everything connected to the tips of refs we have?), and is
> different from integrity of individual objects (is each individual object
> well formed and hash correctly?).  Both kinds of sanity need to be
> checked, as they are orthogonal concepts.
>
> In order to check the history completeness, we need to read the objects
> that we walk during the check. I wouldn't be surprised if the codepath to
> do this is written overly defensive, taking a belt-and-suspender approach,
> and check the well-formedness of an object before it reads it to find out
> the other objects pointed by it.
>
> If we _know_ that we have checked the integrity of all the necessary
> individual objects before we start reading them in order to check the
> completeness of the history, there is an opportunity to optimize by
> teaching --verify-objects paths to optionally be looser than it currently
> is, to avoid checking the object integrity twice.

Ok, will cook something. The reason I raised it is because
--verify-objects --all on git.git could take ~1m10s, but if we assume
object integrity is fine and skip it, it could drop to 10s (I suspect
--objects gives the same number).
-- 
Duy

^ permalink raw reply

* Re: sha-1 check in rev-list --verify-objects redundant?
From: Junio C Hamano @ 2012-02-27  1:23 UTC (permalink / raw)
  To: Nguyen Thai Ngoc Duy; +Cc: Git Mailing List
In-Reply-To: <CACsJy8C9=BJvKvFB3XrSqNXV-y3=o1pTJPtFBXK3jSheBff3Uw@mail.gmail.com>

Nguyen Thai Ngoc Duy <pclouds@gmail.com> writes:

>>  * quickfetch() that is called even before we get any object from the
>>   other end, to optimize the transfer when we already have what we need.
>>
>> The latter is the original use to protect against unconnected island of
>> chain I explained in the previous message, but the former is also abot the
>> same protection, in a different callchain.
>
> I think we can trust what we already have, so in the latter case (and
> the former when the medium is a pack), --objects should suffice.

Hrm, what you seem to be missing is that in the latter case, the objects
we are walking to make sure the connectivity are *not* yet considered as
part of "what we already have" (hence we can trust).  The whole point of
quickfetch is to turn these untrustworthy bits that happen to exist in our
repository into a part of trustable history without having to fetch from
the other side to complete them.  In the former case, when we know that
pack has been indexed with recent index-pack/unpack-objects that are more
picky (didn't Shawn and I recently tighten them?), we may be able to do
without object integrity checks.

>> If we _know_ that we have checked the integrity of all the necessary
>> individual objects before we start reading them in order to check the
>> completeness of the history, there is an opportunity to optimize by
>> teaching --verify-objects paths to optionally be looser than it currently
>> is, to avoid checking the object integrity twice.
>
> Ok, will cook something. The reason I raised it is because
> --verify-objects --all on git.git could take ~1m10s, but if we assume
> object integrity is fine and skip it, it could drop to 10s (I suspect
> --objects gives the same number).

That is a big assumption that I personally do not want to sacrifice the
integrity of my history on.  I would 100% agree with the above with s/if
we assume/if we know/, though.

^ permalink raw reply

* [PATCHv3 0/4] gitweb: Match highlighting in project search
From: Jakub Narebski @ 2012-02-27  1:28 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jakub Narebski

These patches are separated from second part of previous version of
this series

  "[PATCHv2 0/8] gitweb: Faster and improved project search"
  http://thread.gmane.org/gmane.comp.version-control.git/190852

It is meant to replace 'jn/gitweb-hilite-regions' in pu.

This series adds highlighting of matching string to project search.
The per-project 'commit' and 'grep' search already implement match
highlighting.  Additional goal is to provide beginnings of match
highlighting framework, to be used thorough gitweb, reducing code
duplication and unifying handling of match highlighting, improving
it.

The implementation of match highlighting in this series can highlight
correctly multiple matches in single line, as opposed to hand-rolled
code for highlighting in 'grep' and 'commit' search types for 'search'
action.


Previous version of this series had as a last patch proof-of-concept
of using match highlighting infrastructure for per-project search,
namely 'grep' search:

  gitweb: Use esc_html_match_hl() in 'grep' search
  http://thread.gmane.org/gmane.comp.version-control.git/190852/focus=190860

This version does not include it, among others because of question
on how to implement -nbsp=>1 version of match highlighting (see first
patch in series for comments).  It would be as a separate patch series.


Jakub Narebski (4):
  gitweb: Introduce esc_html_match_hl and esc_html_hl_regions
  gitweb: Highlight matched part of project name when searching
    projects
  gitweb: Highlight matched part of project description when searching
    projects
  gitweb: Highlight matched part of shortened project description

 gitweb/gitweb.perl |   95 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 92 insertions(+), 3 deletions(-)

-- 
1.7.9

^ permalink raw reply

* Re: [PATCH v6 00/11] Column display
From: Junio C Hamano @ 2012-02-27  1:37 UTC (permalink / raw)
  To: Nguyen Thai Ngoc Duy; +Cc: git
In-Reply-To: <CACsJy8AyZcNSPEY8S0WczVu0ychGKr61BoBm0iy39ZsVM=zHpA@mail.gmail.com>

Nguyen Thai Ngoc Duy <pclouds@gmail.com> writes:

> It used to be test-column. But we would need an external program to
> pipe through to minimize changing display code, especially when
> display code can get complicated (e.g. git-tag for example).

Hrm, I was hoping that we don't have to resort to a hacky implementation
like that; upload-pack/receive-pack that are not run directly by the end
users but having to be somewhere in path were bad enough, but they were
very much about git.

But at least with your series, "git column" is as invisible as git-sh-setup
and git-stripspace by being marked as purehelpers, so your patch may be
the best we could do.  I dunno.

^ permalink raw reply

* [PATCHv3 0/4] gitweb: Match highlighting in project search
From: Jakub Narebski @ 2012-02-27  1:55 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jakub Narebski

These patches are separated from second part of previous version of
this series

  "[PATCHv2 0/8] gitweb: Faster and improved project search"
  http://thread.gmane.org/gmane.comp.version-control.git/190852

It is meant to replace 'jn/gitweb-hilite-regions' in pu.

This series adds highlighting of matching string to project search.
The per-project 'commit' and 'grep' search already implement match
highlighting.  Additional goal is to provide beginnings of match
highlighting framework, to be used thorough gitweb, reducing code
duplication and unifying handling of match highlighting, improving
it.

The implementation of match highlighting in this series can highlight
correctly multiple matches in single line, as opposed to hand-rolled
code for highlighting in 'grep' and 'commit' search types for 'search'
action.


Previous version of this series had as a last patch proof-of-concept
of using match highlighting infrastructure for per-project search,
namely 'grep' search:

  gitweb: Use esc_html_match_hl() in 'grep' search
  http://thread.gmane.org/gmane.comp.version-control.git/190852/focus=190860

This version does not include it, among others because of question
on how to implement -nbsp=>1 version of match highlighting (see first
patch in series for comments).  It would be as a separate patch series.


Jakub Narebski (4):
  gitweb: Introduce esc_html_match_hl and esc_html_hl_regions
  gitweb: Highlight matched part of project name when searching
    projects
  gitweb: Highlight matched part of project description when searching
    projects
  gitweb: Highlight matched part of shortened project description

 gitweb/gitweb.perl |   95 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 92 insertions(+), 3 deletions(-)

-- 
1.7.9

^ permalink raw reply

* [PATCHv3 2/4] gitweb: Highlight matched part of project name when searching projects
From: Jakub Narebski @ 2012-02-27  1:55 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jakub Narebski
In-Reply-To: <1330307722-25351-1-git-send-email-jnareb@gmail.com>

Use esc_html_match_hl() introduced in previous commit to escape HTML
and mark match, using span element with 'match' class.  Currently only
the 'path' part (i.e. the project name) is highlighted; match might be
on the project description.  Highlighting match in description is left
for next commit.

The code makes use of the fact that defined $search_regexp means that
there was search going on.

Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
Changes from v2:
* Introducing esc_html_match_hl() had been put together with
  introduction of esc_html_hl_regions() in previuos commit.
  Commit message got updated accordingly.

Changes from v1:
* Main part of esc_html_match_hl() got split into esc_html_hl_regions(),
  which was introduced in previous commit.

 gitweb/gitweb.perl |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index b790f67..829526f 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -5407,7 +5407,9 @@ sub git_project_list_rows {
 			print "</td>\n";
 		}
 		print "<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
-		                        -class => "list"}, esc_html($pr->{'path'})) . "</td>\n" .
+		                        -class => "list"},
+		                       esc_html_match_hl($pr->{'path'}, $search_regexp)) .
+		      "</td>\n" .
 		      "<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
 		                        -class => "list", -title => $pr->{'descr_long'}},
 		                        esc_html($pr->{'descr'})) . "</td>\n" .
-- 
1.7.9

^ permalink raw reply related

* [PATCHv3 3/4] gitweb: Highlight matched part of project description when searching projects
From: Jakub Narebski @ 2012-02-27  1:55 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jakub Narebski
In-Reply-To: <1330307722-25351-1-git-send-email-jnareb@gmail.com>

Use esc_html_match_hl() from earlier commit to mark match in the
_whole_ description when searching projects.

Currently, with this commit, when searching projects there is always
shown full description of a project, and not a shortened one (like for
ordinary projects list view), even if the match is on project name and
not project description.  Because we always show full description of a
project, and not possibly shortened name, there is no need for having
full description on mouseover via title attribute.

Showing full description when there is match on it is useful to avoid
situation where match is in shortened, invisible part.  On the other
hand that makes project search different than projects list view; also
there can be problems with overly-long project descriptions.

Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
Changes from v2 and v1:
* Code updated to not use -title attribute in project search; we don't
  need to show full project description on mouseover, as we always
  show description in full, not shortened.

* Commit message updated to changes in previous commits.

* Removed notes (in commit message) about trouble with highlighting
  match of full description using shortened one; we add it in next
  commit, and it is not very complicated.

 gitweb/gitweb.perl |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 829526f..03a8dd9 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -5411,8 +5411,12 @@ sub git_project_list_rows {
 		                       esc_html_match_hl($pr->{'path'}, $search_regexp)) .
 		      "</td>\n" .
 		      "<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
-		                        -class => "list", -title => $pr->{'descr_long'}},
-		                        esc_html($pr->{'descr'})) . "</td>\n" .
+		                        -class => "list",
+		                        $search_regexp ? () : -title => $pr->{'descr_long'}},
+		                        $search_regexp
+		                        ? esc_html_match_hl($pr->{'descr_long'}, $search_regexp)
+		                        : esc_html($pr->{'descr'})) .
+		      "</td>\n" .
 		      "<td><i>" . chop_and_escape_str($pr->{'owner'}, 15) . "</i></td>\n";
 		print "<td class=\"". age_class($pr->{'age'}) . "\">" .
 		      (defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "</td>\n" .
-- 
1.7.9

^ permalink raw reply related

* [PATCHv3 1/4] gitweb: Introduce esc_html_match_hl and esc_html_hl_regions
From: Jakub Narebski @ 2012-02-27  1:55 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jakub Narebski
In-Reply-To: <1330307722-25351-1-git-send-email-jnareb@gmail.com>

The esc_html_match_hl() subroutine added in this commit will be used
to highlight *all* matches of given regexp, using 'match' class.
Ultimately it is to be used in all match highlighting, starting
with project search, which does not have it yet.

It uses the esc_html_hl_regions() subroutine, which is meant to
highlight in a given string a list of regions (given as a list of
[ beg, end ] pairs of positions in string), using HTML <span> element
with given class.  It could probably be used in other places that
do highlighting of part of ready line, like highlighting of changes
in a diff (diff refinement highlighting).


Implementation and enhancement notes:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Currently esc_html_hl_regions() subroutine doesn't accept any
  parameters, like esc_html() does.  We might want for example to
  pass  nbsp=>1  to it.

  It can easily be done with the following code:

    my %opts = grep { ref($_) ne "ARRAY" } @sel;
    @sel     = grep { ref($_) eq "ARRAY" } @sel;

  This allow adding parameters after or before regions, e.g.:

    esc_html_hl_regions("foo bar", "mark", [ 0, 3 ], -nbsp => 1);

* esc_html_hl_regions() escapes like esc_html(); if we wanted to
  highlight with esc_path(), we could pass subroutine reference
  to now named esc_gen_hl_regions().

    esc_html_hl_regions("foo bar", "mark", \&esc_path, [ 0, 3 ]);

  Note that this way we can handle -nbsp=>1 case automatically,
  e.g.

    esc_html_hl_regions("foo bar", "mark",
                        sub { esc_html(@_, -nbsp=>1) },
                        [ 0, 3 ]);

* Alternate solution for highlighting region of a string would be to
  use the idea that strings are to be HTML-escaped, and references to
  scalars are HTML (like in the idea for generic committags).

  This would require modifying gitweb code or esc_html to get list of
  fragments, e.g.:

    esc_html(\'<span class="mark">', 'foo', \'</span>', ' bar',
             { -nbsp => 1 });

  or

    esc_html([\'<span class="mark">', 'foo', \'</span>', ' bar'],
             -nbsp=>1);

  esc_html_match_hl() could be then simple wrapper around "match
  formatter", e.g.

    esc_html([ render_match_hl($str, $regexp) ], -nbsp=>1);


Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
This commit is here mainly for the notes in the commit message,
otherwise it could have been squashed with the next commit.  Having
it as a separate commit might help with reviewing.

Changes from v2 (patch was not present in v1):
* Patch includes esc_html_match_hl() subroutine (the interface), and
  not only the esc_html_hl_regions() "engine".

* Slightly expanded "Implementation and enhancement notes" section in
  the commit message.

* Added not about possible future use of esc_html_hl_regions()
  in commit message

 gitweb/gitweb.perl |   41 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 41 insertions(+), 0 deletions(-)

diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 4ceb1a6..b790f67 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -1715,6 +1715,47 @@ sub chop_and_escape_str {
 	}
 }
 
+# Highlight selected fragments of string, using given CSS class,
+# and escape HTML.  It is assumed that fragments do not overlap.
+# Regions are passed as list of pairs (array references).
+#
+# Example: esc_html_hl_regions("foobar", "mark", [ 0, 3 ]) returns
+# '<span class="mark">foo</span>bar'
+sub esc_html_hl_regions {
+	my ($str, $css_class, @sel) = @_;
+	return esc_html($str) unless @sel;
+
+	my $out = '';
+	my $pos = 0;
+
+	for my $s (@sel) {
+		$out .= esc_html(substr($str, $pos, $s->[0] - $pos))
+			if ($s->[0] - $pos > 0);
+		$out .= $cgi->span({-class => $css_class},
+		                   esc_html(substr($str, $s->[0], $s->[1] - $s->[0])));
+
+		$pos = $s->[1];
+	}
+	$out .= esc_html(substr($str, $pos))
+		if ($pos < length($str));
+
+	return $out;
+}
+
+# highlight match (if any), and escape HTML
+sub esc_html_match_hl {
+	my ($str, $regexp) = @_;
+	return esc_html($str) unless defined $regexp;
+
+	my @matches;
+	while ($str =~ /$regexp/g) {
+		push @matches, [$-[0], $+[0]];
+	}
+	return esc_html($str) unless @matches;
+
+	return esc_html_hl_regions($str, 'match', @matches);
+}
+
 ## ----------------------------------------------------------------------
 ## functions returning short strings
 
-- 
1.7.9

^ permalink raw reply related

* [PATCHv4 4/4] gitweb: Highlight matched part of shortened project description
From: Jakub Narebski @ 2012-02-27  1:55 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jakub Narebski
In-Reply-To: <1330307722-25351-1-git-send-email-jnareb@gmail.com>

Previous commit make gitweb use esc_html_match_hl() to mark match in
the _whole_ description of a project when searching projects.

This commit makes gitweb highlight match in _shortened_ description,
based on match in whole description, using esc_html_match_hl_chopped()
subroutine.

If match is in removed (chopped) part, even partially, then trailing
"... " is highlighted.

Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
It was marked as RFC, because I am not sure if it is right way to
highlight match in shortened string, or if we better use full string,
or full string if match is in chopped part.

Changes from v3:
* The relation between esc_html_match_hl() and esc_html_match_hl_chopped()
  got changed; instead of esc_html_match_hl() being wrapper and
  esc_html_match_hl_chopped() doing all the work, common part is
  refactored into matchpos_list(), and both esc_html_match_hl* are
  kept separate.  It results in a bit of code duplication, but
  hopefully it also makes code more clear (it is e.g. less nested).

* Brings back -title that was removed in previous commit, to show full
  description on mouseover (partial revert of previous commit).

Changes from v2:
* Harden esc_html_match_hl_chopped() against calling with both
  $chopped and $regexp undefined (even though it wouldn't happen
  with current code).

* esc_html_match_hl_chopped() uses now esc_html_hl_regions(),
  like esc_html_match_hl() used to do.

Changes from v1:
* Instead of esc_html_match_hl_chopped() duplicating much od code in
  esc_html_match_hl(), make esc_html_match_hl() call the *_chopped()
  one with $chopped set to undef.

  Now managing highlighting of $chopped part is just a matter of
  adjusting and filtering @matches to apply to $chopped rather than
  original $str where match was performed.

  As a side issue when match span past chop point current code uses
  one selection <span class+match">foo... </span> and not two
  <span class="match">foo</span><span class="match">... </span>

 gitweb/gitweb.perl |   52 +++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 03a8dd9..1fc5361 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -1742,20 +1742,61 @@ sub esc_html_hl_regions {
 	return $out;
 }
 
-# highlight match (if any), and escape HTML
-sub esc_html_match_hl {
+# return positions of beginning and end of each match
+sub matchpos_list {
 	my ($str, $regexp) = @_;
-	return esc_html($str) unless defined $regexp;
+	return unless (defined $str && defined $regexp);
 
 	my @matches;
 	while ($str =~ /$regexp/g) {
 		push @matches, [$-[0], $+[0]];
 	}
+	return @matches;
+}
+
+# highlight match (if any), and escape HTML
+sub esc_html_match_hl {
+	my ($str, $regexp) = @_;
+	return esc_html($str) unless defined $regexp;
+
+	my @matches = matchpos_list($str, $regexp);
 	return esc_html($str) unless @matches;
 
 	return esc_html_hl_regions($str, 'match', @matches);
 }
 
+
+# highlight match (if any) of shortened string, and escape HTML
+sub esc_html_match_hl_chopped {
+	my ($str, $chopped, $regexp) = @_;
+	return esc_html_match_hl($str, $regexp) unless defined $chopped;
+
+	my @matches = matchpos_list($str, $regexp);
+	return esc_html($chopped) unless @matches;
+
+	# filter matches so that we mark chopped string
+	my $tail = "... "; # see chop_str
+	unless ($chopped =~ s/\Q$tail\E$//) {
+		$tail = '';
+	}
+	my $chop_len = length($chopped);
+	my $tail_len = length($tail);
+	my @filtered;
+
+	for my $m (@matches) {
+		if ($m->[0] > $chop_len) {
+			push @filtered, [ $chop_len, $chop_len + $tail_len ] if ($tail_len > 0);
+			last;
+		} elsif ($m->[1] > $chop_len) {
+			push @filtered, [ $m->[0], $chop_len + $tail_len ];
+			last;
+		}
+		push @filtered, $m;
+	}
+
+	return esc_html_hl_regions($chopped . $tail, 'match', @filtered);
+}
+
 ## ----------------------------------------------------------------------
 ## functions returning short strings
 
@@ -5412,9 +5453,10 @@ sub git_project_list_rows {
 		      "</td>\n" .
 		      "<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
 		                        -class => "list",
-		                        $search_regexp ? () : -title => $pr->{'descr_long'}},
+		                        -title => $pr->{'descr_long'}},
 		                        $search_regexp
-		                        ? esc_html_match_hl($pr->{'descr_long'}, $search_regexp)
+		                        ? esc_html_match_hl_chopped($pr->{'descr_long'},
+		                                                    $pr->{'descr'}, $search_regexp)
 		                        : esc_html($pr->{'descr'})) .
 		      "</td>\n" .
 		      "<td><i>" . chop_and_escape_str($pr->{'owner'}, 15) . "</i></td>\n";
-- 
1.7.9

^ permalink raw reply related

* [ANNOUNCE] Git 1.7.8.5
From: Junio C Hamano @ 2012-02-27  2:51 UTC (permalink / raw)
  To: git

A maintenance release Git 1.7.8.5 is now available at the usual
places.

The release tarballs are found at:

    http://code.google.com/p/git-core/downloads/list

and their SHA-1 checksums are:

bb3d715437a4751f7de0c89156bf97dae7c6049a  git-1.7.8.5.tar.gz
71cf25158ae3499e33327fa9469279771429f9f7  git-htmldocs-1.7.8.5.tar.gz
ce327331973b6e100b6a69ab8f9c526690260e92  git-manpages-1.7.8.5.tar.gz

Also the following public repositories all have a copy of the v1.7.8.5
tag and the maint-1.7.8 branch that the tag points at:

  url = git://repo.or.cz/alt-git.git
  url = https://code.google.com/p/git-core/
  url = git://git.sourceforge.jp/gitroot/git-core/git.git
  url = git://git-core.git.sourceforge.net/gitroot/git-core/git-core
  url = https://github.com/gitster/git

Git v1.7.8.5 Release Notes
==========================

Fixes since v1.7.8.4
--------------------

 * Dependency on our thread-utils.h header file was missing for
   objects that depend on it in the Makefile.

 * "git am" when fed an empty file did not correctly finish reading it
   when it attempts to guess the input format.

 * "git grep -P" (when PCRE is enabled in the build) did not match the
   beginning and the end of the line correctly with ^ and $.

 * "git rebase -m" tried to run "git notes copy" needlessly when
   nothing was rewritten.

Also contains minor fixes and documentation updates.

----------------------------------------------------------------

Changes since v1.7.8.4 are as follows:

Andrew Wong (1):
      rebase -m: only call "notes copy" when rewritten exists and is non-empty

Dmitry V. Levin (1):
      Makefile: add thread-utils.h to LIB_H

Jeff King (1):
      imap-send: remove dead code

Jim Meyering (1):
      am: don't infloop for an empty input file

Junio C Hamano (2):
      Git 1.7.6.6
      Git 1.7.8.5

Michał Kiedrowicz (1):
      grep -P: Fix matching ^ and $

^ permalink raw reply

* Re: [PATCH v6 06/11] column: add column.ui for default column output settings
From: Junio C Hamano @ 2012-02-27  6:20 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git
In-Reply-To: <1330170078-29353-7-git-send-email-pclouds@gmail.com>

Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:

> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---
>  Documentation/config.txt     |   26 ++++++++++++++++++++++++++
>  Documentation/git-column.txt |    6 +++++-
>  builtin/column.c             |   21 +++++++++++++++++++++
>  column.c                     |   28 ++++++++++++++++++++++++++++
>  column.h                     |    2 ++
>  5 files changed, 82 insertions(+), 1 deletions(-)
>
> diff --git a/Documentation/config.txt b/Documentation/config.txt
> index abeb82b..5216598 100644
> --- a/Documentation/config.txt
> +++ b/Documentation/config.txt
> @@ -821,6 +821,32 @@ color.ui::
>  	`never` if you prefer git commands not to use color unless enabled
>  	explicitly with some other configuration or the `--color` option.
>  
> +column.ui::
> +	Specify whether supported commands should output in columns.
> +	This variable consists of a list of tokens separated by spaces
> +	or commas:
> ++
> +--
> +`always`;;
> +	always show in columns
> +`never`;;
> +	never show in columns
> +`auto`;;
> +	show in columns if the output is to the terminal
> +`column`;;
> +	fill columns before rows (default)
> +`row`;;
> +	fill rows before columns
> +`dense`;;
> +	make unequal size columns to utilize more space
> +`nodense`;;
> +	make equal size columns
> +`color`;;
> +	input contains ANSI escape sequence for coloring
> +--
> ++
> +	This option defaults to 'never'.

I tried comparing output from 

    $ git help -a
    $ git -c column.ui=row help -a

but did not spot differences.  What am I doing wrong?

^ permalink raw reply

* Re: [PATCH] fsck: do not print dangling objects by default
From: Zbigniew Jędrzejewski-Szmek @ 2012-02-27  6:42 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Clemens Buchacher
In-Reply-To: <7vhayddxgp.fsf@alter.siamese.dyndns.org>

On 02/26/2012 11:46 PM, Junio C Hamano wrote:
> Junio C Hamano<gitster@pobox.com>  writes:
>
>> I think that both the ultimate goal explained above, and the direction in
>> which the documentation updates tries to move us, are good.  I only gave a
>> cursory look at the code changes, but what they implement seems to match
>> the intention.
>>
>> Of course I may be missing something, so objections from others to argue
>> why we shouldn't do this is very much welcomed to stop me and Clemens ;-).
>
> Let's start with the obvious.
>
> It is much easier for a user to use a new option on the command line when
> he wants to use an improved behaviour when he runs the command manually.
> Having to update scripts that run the command to act on its output, on the
> other hand, is much more painful to the users.
>
> And the intended audience for this change clearly is interactive users
> that follow the user-manual to try things out.
>
> Given that, isn't it not just sufficient but actually better to instead
> add a new --no-dangling option and keep the default unchanged?

I understood the goal of this change as "modify fsck output to not show 
confusing 'dangling' messages by default. Not when running the tutorial 
and having the output explained in parallel, but when someone runs 
git-fsck to clean up the repository. In that situation, if somebody 
knows enough to run --no-dangling, than they know enough to ignore the 
'dangling' messages in the output.

For the knowledgeable user, --no-dangling could be useful to avoid 
uninteresting messages which usually dwarf the rest of output, but this 
would be less important.

Zbyszek

^ permalink raw reply

* Re: [PATCH v6 06/11] column: add column.ui for default column output settings
From: Nguyen Thai Ngoc Duy @ 2012-02-27  7:04 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vvcmsbxvz.fsf@alter.siamese.dyndns.org>

2012/2/27 Junio C Hamano <gitster@pobox.com>:
> I tried comparing output from
>
>    $ git help -a
>    $ git -c column.ui=row help -a
>
> but did not spot differences.  What am I doing wrong?

Config does not affect "help -a". It has always been sorted column
first. But yeah if you prefer row-first, then it should probably
follow that too.
-- 
Duy

^ permalink raw reply

* Re: [PATCH v6 00/11] Column display
From: Junio C Hamano @ 2012-02-27  7:46 UTC (permalink / raw)
  To: Nguyen Thai Ngoc Duy; +Cc: git
In-Reply-To: <7v8vjpcaz3.fsf@alter.siamese.dyndns.org>

Junio C Hamano <gitster@pobox.com> writes:

> But at least with your series, "git column" is as invisible as git-sh-setup
> and git-stripspace by being marked as purehelpers, so your patch may be
> the best we could do.  I dunno.

I finally realized the true reason why I was so reluctant to take this
series.  If the series were presented like the following, I wouldn't have
had any problem:

    There is a widely used program, "column", that takes a data stream
    one-item-per-line as its input and produces columnar output.  Some
    lists we produce as our output, e.g. "git tag --list", are often too
    tall and sufficiently narrow, that "git tag --list | column" is a
    useful thing to do.  The first patch in this series teaches "git tag
    --list" to do just that but internally, so the user does not have to
    pipe manually from the command line.

    Luckily, "column" is a free software, and more importantly, it is
    written modularly enough so that we can reuse its primary logic to
    produce lines for columnar output without having to feed its input
    from the standard input or drain its output directly to the standard
    output.  Build an API around its core, and plug that logic to "branch
    --list", "help -a" and other commands.

But that is not the case.

Yes, there is "column" that comes with BSD, and I am not suggesting to gut
it and reuse its code, but by adding our own "git column" and implementing
it as a built-in internal, we are making it harder for the outside world
to benefit from our implementation, even when our "git column" some day
becomes polished enough to the point that people who are used to the BSD
"column" start to wish their "column" had extra features offered by "git
column", without swallowing "git" as a whole.

Come to think of it, that is really the same distaste I had against both
"diff --no-index" and "grep --no-index".  We know adding our enhancements
over non-git versions of these programs is a better gift to the outside
world, but we instead added the --no-index mode to Git to only keep the
benefit to ourselves, because it is far easier for us to do so.

But I do not deeply care either way.

^ permalink raw reply

* What's cooking in git.git (Feb 2012, #09; Sun, 26)
From: Junio C Hamano @ 2012-02-27  7:49 UTC (permalink / raw)
  To: git

Here are the topics that have been cooking.  Commits prefixed with '-' are
only in 'pu' (proposed updates) while commits prefixed with '+' are in 'next'.

You can find the changes described here in the integration branches of the
repositories listed at

    http://git-blame.blogspot.com/p/git-public-repositories.html

--------------------------------------------------
[New Topics]

* jc/am-3-nonstandard-popt (2012-02-26) 2 commits
  (merged to 'next' on 2012-02-26 at 62a6ddf)
 + test: "am -3" can accept non-standard -p<num>
  (merged to 'next' on 2012-02-26 at 1363bd6)
 + am -3: allow nonstandard -p<num> option

The code to synthesize the fake ancestor tree used by 3-way merge
fallback in "git am" was not prepared to read a patch created with
a non-standard -p<num> value.

* cb/fsck-squelch-dangling (2012-02-26) 1 commit
 - fsck: do not print dangling objects by default

Introduces "fsck --dangling" and removes the output for dangling objects
from the default output.

I personally do not think it is worth risking backward compatibility in
the way this patch implements the squelching of the output.  An approach
to add --no-dangling option without changing the default would be OK,
though.

* rf/no-no-no-parseopt (2012-02-26) 3 commits
 - parse-options: remove PARSE_OPT_NEGHELP
 - parse-options: allow positivation of options starting, with no-
 - test-parse-options: convert to OPT_BOOL()

Options that use PARSE_OPT_NEGHELP needed to word their help text in
a strange way.

--------------------------------------------------
[Graduated to "master"]

* fc/push-prune (2012-02-22) 4 commits
  (merged to 'next' on 2012-02-23 at 8044055)
 + push: add '--prune' option
 + remote: refactor code into alloc_delete_ref()
 + remote: reorganize check_pattern_match()
 + remote: use a local variable in match_push_refs()

"git push" learned the "--prune" option, similar to "git fetch".

* jb/filter-ignore-sigpipe (2012-02-21) 1 commit
  (merged to 'next' on 2012-02-23 at 605dd39)
 + Ignore SIGPIPE when running a filter driver

When the filter driver exits before reading the content before the main
git process writes the contents to be filtered to the pipe to it, the
latter could be killed with SIGPIPE instead of ignoring such an event as
an error.

* jc/add-refresh-unmerged (2012-02-17) 1 commit
  (merged to 'next' on 2012-02-21 at 09f8721)
 + refresh_index: do not show unmerged path that is outside pathspec

"git add --refresh <pathspec>" warned about unmerged paths outside the
given pathspec.

* jc/doc-merge-options (2012-02-22) 1 commit
  (merged to 'next' on 2012-02-23 at dcf1d13)
 + Documentation/merge-options.txt: group "ff" related options together

Documentation for "git merge" had "--ff-only" far away from other options
related to the handling of fast-forward merges.

* jk/config-include (2012-02-17) 10 commits
  (merged to 'next' on 2012-02-20 at 7b150b7)
 + config: add include directive
 + config: eliminate config_exclusive_filename
 + config: stop using config_exclusive_filename
 + config: provide a version of git_config with more options
 + config: teach git_config_rename_section a file argument
 + config: teach git_config_set_multivar_in_file a default path
 + config: copy the return value of prefix_filename
 + t1300: add missing &&-chaining
 + docs/api-config: minor clarifications
 + docs: add a basic description of the config API

An assignment to the include.path pseudo-variable causes the named file
to be included in-place when Git looks up configuration variables.

* jk/maint-avoid-streaming-filtered-contents (2012-02-24) 3 commits
  (merged to 'next' on 2012-02-26 at 25e014c)
 + do not stream large files to pack when filters are in use
 + teach dry-run convert_to_git not to require a src buffer
 + teach convert_to_git a "dry run" mode

The bulk check-in codepath streamed contents that needs smudge/clean
filters without running them, instead of punting and delegating to the
codepath to run filters after slurping everything to core.

* jn/gitweb-search-optim (2012-02-23) 3 commits
  (merged to 'next' on 2012-02-23 at 9f9125f)
 + gitweb: Faster project search
 + gitweb: Option for filling only specified info in fill_project_list_info
 + gitweb: Refactor checking if part of project info need filling
 (this branch is used by jn/gitweb-hilite-regions.)

"gitweb" learns to read various pieces of information for the repositories
lazily, instead of reading everything that could be needed (including the
ones that are not necessary for a specific task).

* js/configure-libintl (2012-02-20) 1 commit
  (merged to 'next' on 2012-02-21 at 79d7ccc)
 + configure: don't use -lintl when there is no gettext support

Build fix for autoconf, meant for 'maint' track.

* ld/git-p4-expanded-keywords (2012-02-14) 1 commit
  (merged to 'next' on 2012-02-16 at a9004c5)
 + git-p4: add initial support for RCS keywords

Teach git-p4 to unexpand $RCS$-like keywords that are embedded in
tracked contents in order to reduce unnecessary merge conflicts.

Replaced with the rerolled patch.

* pj/remote-set-branches-usage-fix (2012-02-19) 1 commit
  (merged to 'next' on 2012-02-21 at cb71d0e)
 + remote: fix set-branches usage and documentation

Documentation fix.

* sp/smart-http-failure-to-push (2012-02-23) 1 commit
  (merged to 'next' on 2012-02-23 at fe0b2aa)
 + disconnect from remote helpers more gently

When a remote helper exits before reading the blank line from the main git
process to signal the end of commands, the latter could be killed with
SIGPIPE. Instead we should ignore such event as a non-error.

* tr/maint-bundle-long-subject (2012-02-23) 4 commits
  (merged to 'next' on 2012-02-23 at b2c1605)
 + t5704: match tests to modern style
 + strbuf: improve strbuf_get*line documentation
 + bundle: use a strbuf to scan the log for boundary commits
 + bundle: put strbuf_readline_fd in strbuf.c with adjustments

"git bundle create" produced a corrupt bundle file upon seeing commits
with excessively long subject line.

* tr/perftest (2012-02-17) 3 commits
  (merged to 'next' on 2012-02-20 at 4c75ba9)
 + Add a performance test for git-grep
 + Introduce a performance testing framework
 + Move the user-facing test library to test-lib-functions.sh

The beginning of a new performance benchmark framework.

--------------------------------------------------
[Stalled]

* jc/diff-ignore-case (2012-02-19) 6 commits
 - diff -i
 - diff: --ignore-case
 - xdiff: introduce XDF_IGNORE_CASE
 - xdiff: introduce XDF_INEXACT_MATCH
 - xdiff: PATIENCE/HISTOGRAM are not independent option bits
 - xdiff: remove XDL_PATCH_* macros

"git diff" learns "--ignore-case" option.

Commits near the tip need to be better titled.

* jc/pickaxe-ignore-case (2012-02-21) 1 commit
 - pickaxe: allow -i to search in patch case-insensitively

The original "-S" pickaxe probably needs to be taught about the option.

* jl/maint-submodule-relative (2012-02-09) 2 commits
 - submodules: always use a relative path from gitdir to work tree
 - submodules: always use a relative path to gitdir

The second one looked iffy.

* hv/submodule-recurse-push (2012-02-13) 3 commits
 - push: teach --recurse-submodules the on-demand option
 - Refactor submodule push check to use string list instead of integer
 - Teach revision walking machinery to walk multiple times sequencially

The bottom one was not clearly explained and needs a reroll.

* jc/advise-push-default (2011-12-18) 1 commit
 - push: hint to use push.default=upstream when appropriate

Peff had a good suggestion outlining an updated code structure so that
somebody new can try to dip his or her toes in the development. Any
takers?

* ss/git-svn-prompt-sans-terminal (2012-01-04) 3 commits
 - fixup! 15eaaf4
 - git-svn, perl/Git.pm: extend Git::prompt helper for querying users
 - perl/Git.pm: "prompt" helper to honor GIT_ASKPASS and SSH_ASKPASS

The bottom one has been replaced with a rewrite based on comments from
Ævar. The second one needs more work, both in perl/Git.pm and prompt.c, to
give precedence to tty over SSH_ASKPASS when terminal is available.

* jc/split-blob (2012-02-23) 7 commits
 - fixup?
 - chunked-object: streaming checkout
 - chunked-object: fallback checkout codepaths
 - bulk-checkin: support chunked-object encoding
 - bulk-checkin: allow the same data to be multiply hashed
 - new representation types in the packstream
 - varint-in-pack: refactor varint encoding/decoding

Not ready.

I finished the streaming checkout codepath, but as explained in 127b177
(bulk-checkin: support chunked-object encoding, 2011-11-30), these are
still early steps of a long and painful journey. At least pack-objects and
fsck need to learn the new encoding for the series to be usable locally,
and then index-pack/unpack-objects needs to learn it to be used remotely.

Given that I heard a lot of noise that people want large files, and that I
was asked by somebody at GitTogether'11 privately for an advice on how to
pay developers (not me) to help adding necessary support, I am somewhat
dissapointed that the original patch series that was sent almost two
months ago still remains here without much comments and updates from the
developer community. I even made the interface to the logic that decides
where to split chunks easily replaceable, and I deliberately made the
logic in the original patch extremely stupid to entice others, especially
the "bup" fanboys, to come up with a better logic, thinking that giving
people an easy target to shoot for, they may be encouraged to help
out. The plan is not working :-(.

--------------------------------------------------
[Cooking]

* zj/diff-stat-dyncol (2012-02-24) 10 commits
 - diff --stat: add config option to limit graph width
 - diff --stat: enable limiting of the graph part
 - diff --stat: add a test for output with COLUMNS=40
 - diff --stat: use a maximum of 5/8 for the filename part
 - merge --stat: use the full terminal width
 - log --stat: use the full terminal width
 - show --stat: use the full terminal width
 - diff --stat: use the full terminal width
 - diff --stat: tests for long filenames and big change counts
 - Merge branches zj/decimal-width, zj/term-columns and jc/diff-stat-scaler

Rerolled.

* nd/columns (2012-02-26) 11 commits
 - tag: add --column
 - column: support piping stdout to external git-column process
 - status: add --column
 - branch: add --column
 - help: reuse print_columns() for help -a
 - column: add column.ui for default column output settings
 - column: support columns with different widths
 - column: add columnar layout
 - Stop starting pager recursively
 - Add git-column and column mode parsing
 - column: add API to print items in columns

Rerolled.

* ph/cherry-pick-advice-refinement (2012-02-22) 1 commit
  (merged to 'next' on 2012-02-26 at 1c930c3)
 + cherry-pick: No advice to commit if --no-commit

The advice given by a conflicted "cherry-pick --no-commit" told the user
to make a commit after resolving conflicts.

Will merge to "master".

* pj/completion-remote-set-url-branches (2012-02-22) 2 commits
  (merged to 'next' on 2012-02-26 at 0062008)
 + completion: normalize increment/decrement style
 + completion: remote set-* <name> and <branch>

Will merge to "master".

* th/git-diffall (2012-02-24) 1 commit
 - contrib: added git-diffall

* jn/gitweb-hilite-regions (2012-02-26) 4 commits
 - gitweb: Highlight matched part of shortened project description
 - gitweb: Highlight matched part of project description when searching projects
 - gitweb: Highlight matched part of project name when searching projects
 - gitweb: Introduce esc_html_match_hl and esc_html_hl_regions

Project search in "gitweb" shows the substring that matched in the project
name and description highlighted. The highlighting logic is meant to be
reused later for other kinds of searches e.g. grep and commit log search.

* jb/required-filter (2012-02-17) 1 commit
  (merged to 'next' on 2012-02-26 at e9ba88a)
 + Add a setting to require a filter to be successful

A content filter used to be a way to make the recorded contents "more
useful", but this defines a way to optionally mark a filter "required".

Will merge to "master".

^ permalink raw reply

* [PATCH 00/11] Large blob fixes
From: Nguyễn Thái Ngọc Duy @ 2012-02-27  7:55 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy

These patches make sure we avoid keeping whole blob in memory, at
least in common cases. Blob-only streaming code paths are opened to
accomplish that.

I don't quite like having three different implementations for
checking sha-1 signature (one on git_istream, one on packed_git and
the other one in index-pack) but I failed to see how to unify them.

Making archive-zip work with stream can be difficult. But at least tar
format works. Good enough for me.

Nguyễn Thái Ngọc Duy (11):
  Add more large blob test cases
  Factor out and export large blob writing code to arbitrary file
    handle
  cat-file: use streaming interface to print blobs
  parse_object: special code path for blobs to avoid putting whole
    object in memory
  show: use streaming interface for showing blobs
  index-pack --verify: skip sha-1 collision test
  index-pack: split second pass obj handling into own function
  index-pack: reduce memory usage when the pack has large blobs
  pack-check: do not unpack blobs
  archive: support streaming large files to a tar archive
  fsck: use streaming interface for writing lost-found blobs

 archive-tar.c        |   35 +++++++++++++---
 archive-zip.c        |    9 ++--
 archive.c            |   51 ++++++++++++++++--------
 archive.h            |   11 ++++-
 builtin/cat-file.c   |   22 ++++++++++
 builtin/fsck.c       |    8 +---
 builtin/index-pack.c |  108 +++++++++++++++++++++++++++++++++++++------------
 builtin/log.c        |    9 ++++-
 cache.h              |    5 ++-
 entry.c              |   39 ++++++++++++------
 fast-import.c        |    2 +-
 object.c             |   11 +++++
 pack-check.c         |   21 +++++++++-
 sha1_file.c          |   78 +++++++++++++++++++++++++++++++-----
 t/t1050-large.sh     |   59 +++++++++++++++++++++++++++-
 wrapper.c            |   27 +++++++++++-
 16 files changed, 400 insertions(+), 95 deletions(-)

-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply

* [PATCH 01/11] Add more large blob test cases
From: Nguyễn Thái Ngọc Duy @ 2012-02-27  7:55 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1330329315-11407-1-git-send-email-pclouds@gmail.com>

New test cases list commands that should work when memory is
limited. All memory allocation functions (*) learn to reject any
allocation larger than $GIT_ALLOC_LIMIT if set.

(*) Not exactly all. Some places do not use x* functions, but
malloc/calloc directly, notably diff-delta. These could path should
never be run on large blobs.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 t/t1050-large.sh |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 wrapper.c        |   27 ++++++++++++++++++++++--
 2 files changed, 82 insertions(+), 4 deletions(-)

diff --git a/t/t1050-large.sh b/t/t1050-large.sh
index 29d6024..f245e59 100755
--- a/t/t1050-large.sh
+++ b/t/t1050-large.sh
@@ -10,7 +10,9 @@ test_expect_success setup '
 	echo X | dd of=large1 bs=1k seek=2000 &&
 	echo X | dd of=large2 bs=1k seek=2000 &&
 	echo X | dd of=large3 bs=1k seek=2000 &&
-	echo Y | dd of=huge bs=1k seek=2500
+	echo Y | dd of=huge bs=1k seek=2500 &&
+	GIT_ALLOC_LIMIT=1500 &&
+	export GIT_ALLOC_LIMIT
 '
 
 test_expect_success 'add a large file or two' '
@@ -100,4 +102,59 @@ test_expect_success 'packsize limit' '
 	)
 '
 
+test_expect_success 'diff --raw' '
+	git commit -q -m initial &&
+	echo modified >>large1 &&
+	git add large1 &&
+	git commit -q -m modified &&
+	git diff --raw HEAD^
+'
+
+test_expect_success 'hash-object' '
+	git hash-object large1
+'
+
+test_expect_failure 'cat-file a large file' '
+	git cat-file blob :large1 >/dev/null
+'
+
+test_expect_failure 'git-show a large file' '
+	git show :large1 >/dev/null
+
+'
+
+test_expect_failure 'clone' '
+	git clone -n file://"$PWD"/.git new &&
+	(
+	cd new &&
+	git config core.bigfilethreshold 200k &&
+	git checkout master
+	)
+'
+
+test_expect_failure 'fetch updates' '
+	echo modified >> large1 &&
+	git commit -q -a -m updated &&
+	(
+	cd new &&
+	git fetch --keep # FIXME should not need --keep
+	)
+'
+
+test_expect_failure 'fsck' '
+	git fsck --full
+'
+
+test_expect_success 'repack' '
+	git repack -ad
+'
+
+test_expect_failure 'tar achiving' '
+	git archive --format=tar HEAD >/dev/null
+'
+
+test_expect_failure 'zip achiving' '
+	git archive --format=zip HEAD >/dev/null
+'
+
 test_done
diff --git a/wrapper.c b/wrapper.c
index 85f09df..d4c0972 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -9,6 +9,18 @@ static void do_nothing(size_t size)
 
 static void (*try_to_free_routine)(size_t size) = do_nothing;
 
+static void memory_limit_check(size_t size)
+{
+	static int limit = -1;
+	if (limit == -1) {
+		const char *env = getenv("GIT_ALLOC_LIMIT");
+		limit = env ? atoi(env) * 1024 : 0;
+	}
+	if (limit && size > limit)
+		die("attempting to allocate %d over limit %d",
+		    size, limit);
+}
+
 try_to_free_t set_try_to_free_routine(try_to_free_t routine)
 {
 	try_to_free_t old = try_to_free_routine;
@@ -32,7 +44,10 @@ char *xstrdup(const char *str)
 
 void *xmalloc(size_t size)
 {
-	void *ret = malloc(size);
+	void *ret;
+
+	memory_limit_check(size);
+	ret = malloc(size);
 	if (!ret && !size)
 		ret = malloc(1);
 	if (!ret) {
@@ -79,7 +94,10 @@ char *xstrndup(const char *str, size_t len)
 
 void *xrealloc(void *ptr, size_t size)
 {
-	void *ret = realloc(ptr, size);
+	void *ret;
+
+	memory_limit_check(size);
+	ret = realloc(ptr, size);
 	if (!ret && !size)
 		ret = realloc(ptr, 1);
 	if (!ret) {
@@ -95,7 +113,10 @@ void *xrealloc(void *ptr, size_t size)
 
 void *xcalloc(size_t nmemb, size_t size)
 {
-	void *ret = calloc(nmemb, size);
+	void *ret;
+
+	memory_limit_check(size * nmemb);
+	ret = calloc(nmemb, size);
 	if (!ret && (!nmemb || !size))
 		ret = calloc(1, 1);
 	if (!ret) {
-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply related

* [PATCH 02/11] Factor out and export large blob writing code to arbitrary file handle
From: Nguyễn Thái Ngọc Duy @ 2012-02-27  7:55 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1330329315-11407-1-git-send-email-pclouds@gmail.com>


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 cache.h |    3 +++
 entry.c |   39 ++++++++++++++++++++++++++-------------
 2 files changed, 29 insertions(+), 13 deletions(-)

diff --git a/cache.h b/cache.h
index e12b15f..6ce691b 100644
--- a/cache.h
+++ b/cache.h
@@ -937,6 +937,9 @@ struct checkout {
 		 refresh_cache:1;
 };
 
+extern int streaming_write_sha1(int fd, int seekable, const unsigned char *sha1,
+				enum object_type exp_type,
+				struct stream_filter *filter);
 extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath);
 
 struct cache_def {
diff --git a/entry.c b/entry.c
index 852fea1..dde0d17 100644
--- a/entry.c
+++ b/entry.c
@@ -115,26 +115,20 @@ static int fstat_output(int fd, const struct checkout *state, struct stat *st)
 	return 0;
 }
 
-static int streaming_write_entry(struct cache_entry *ce, char *path,
-				 struct stream_filter *filter,
-				 const struct checkout *state, int to_tempfile,
-				 int *fstat_done, struct stat *statbuf)
+int streaming_write_sha1(int fd, int seekable, const unsigned char *sha1,
+			 enum object_type exp_type,
+			 struct stream_filter *filter)
 {
 	struct git_istream *st;
 	enum object_type type;
 	unsigned long sz;
 	int result = -1;
 	ssize_t kept = 0;
-	int fd = -1;
 
-	st = open_istream(ce->sha1, &type, &sz, filter);
+	st = open_istream(sha1, &type, &sz, filter);
 	if (!st)
 		return -1;
-	if (type != OBJ_BLOB)
-		goto close_and_exit;
-
-	fd = open_output_fd(path, ce, to_tempfile);
-	if (fd < 0)
+	if (exp_type != OBJ_ANY && type != exp_type)
 		goto close_and_exit;
 
 	for (;;) {
@@ -144,7 +138,7 @@ static int streaming_write_entry(struct cache_entry *ce, char *path,
 
 		if (!readlen)
 			break;
-		if (sizeof(buf) == readlen) {
+		if (seekable && sizeof(buf) == readlen) {
 			for (holeto = 0; holeto < readlen; holeto++)
 				if (buf[holeto])
 					break;
@@ -166,10 +160,29 @@ static int streaming_write_entry(struct cache_entry *ce, char *path,
 	if (kept && (lseek(fd, kept - 1, SEEK_CUR) == (off_t) -1 ||
 		     write(fd, "", 1) != 1))
 		goto close_and_exit;
-	*fstat_done = fstat_output(fd, state, statbuf);
+	result = 0;
 
 close_and_exit:
 	close_istream(st);
+	return result;
+}
+
+static int streaming_write_entry(struct cache_entry *ce, char *path,
+				 struct stream_filter *filter,
+				 const struct checkout *state, int to_tempfile,
+				 int *fstat_done, struct stat *statbuf)
+{
+	int result = -1;
+	int fd = open_output_fd(path, ce, to_tempfile);
+	if (fd < 0)
+		goto close_and_exit;
+
+	if (streaming_write_sha1(fd, 1, ce->sha1, OBJ_BLOB, filter))
+		goto close_and_exit;
+
+	*fstat_done = fstat_output(fd, state, statbuf);
+
+close_and_exit:
 	if (0 <= fd)
 		result = close(fd);
 	if (result && 0 <= fd)
-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply related

* [PATCH 03/11] cat-file: use streaming interface to print blobs
From: Nguyễn Thái Ngọc Duy @ 2012-02-27  7:55 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1330329315-11407-1-git-send-email-pclouds@gmail.com>


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/cat-file.c |   22 ++++++++++++++++++++++
 t/t1050-large.sh   |    2 +-
 2 files changed, 23 insertions(+), 1 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 8ed501f..3f3b558 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -82,6 +82,24 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long
 		write_or_die(1, cp, endp - cp);
 }
 
+static int write_blob(const unsigned char *sha1)
+{
+	unsigned char new_sha1[20];
+
+	if (sha1_object_info(sha1, NULL) == OBJ_TAG) {
+		enum object_type type;
+		unsigned long size;
+		char *buffer = read_sha1_file(sha1, &type, &size);
+		if (memcmp(buffer, "object ", 7) ||
+		    get_sha1_hex(buffer + 7, new_sha1))
+			die("%s not a valid tag", sha1_to_hex(sha1));
+		sha1 = new_sha1;
+		free(buffer);
+	}
+
+	return streaming_write_sha1(1, 0, sha1, OBJ_BLOB, NULL);
+}
+
 static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
 {
 	unsigned char sha1[20];
@@ -127,6 +145,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
 			return cmd_ls_tree(2, ls_args, NULL);
 		}
 
+		if (type == OBJ_BLOB)
+			return write_blob(sha1);
 		buf = read_sha1_file(sha1, &type, &size);
 		if (!buf)
 			die("Cannot read object %s", obj_name);
@@ -149,6 +169,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
 		break;
 
 	case 0:
+		if (type_from_string(exp_type) == OBJ_BLOB)
+			return write_blob(sha1);
 		buf = read_object_with_reference(sha1, exp_type, &size, NULL);
 		break;
 
diff --git a/t/t1050-large.sh b/t/t1050-large.sh
index f245e59..39a3e77 100755
--- a/t/t1050-large.sh
+++ b/t/t1050-large.sh
@@ -114,7 +114,7 @@ test_expect_success 'hash-object' '
 	git hash-object large1
 '
 
-test_expect_failure 'cat-file a large file' '
+test_expect_success 'cat-file a large file' '
 	git cat-file blob :large1 >/dev/null
 '
 
-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply related

* [PATCH 04/11] parse_object: special code path for blobs to avoid putting whole object in memory
From: Nguyễn Thái Ngọc Duy @ 2012-02-27  7:55 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1330329315-11407-1-git-send-email-pclouds@gmail.com>


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 object.c    |   11 +++++++++++
 sha1_file.c |   33 ++++++++++++++++++++++++++++++++-
 2 files changed, 43 insertions(+), 1 deletions(-)

diff --git a/object.c b/object.c
index 6b06297..0498b18 100644
--- a/object.c
+++ b/object.c
@@ -198,6 +198,17 @@ struct object *parse_object(const unsigned char *sha1)
 	if (obj && obj->parsed)
 		return obj;
 
+	if ((obj && obj->type == OBJ_BLOB) ||
+	    (!obj && has_sha1_file(sha1) &&
+	     sha1_object_info(sha1, NULL) == OBJ_BLOB)) {
+		if (check_sha1_signature(repl, NULL, 0, NULL) < 0) {
+			error("sha1 mismatch %s\n", sha1_to_hex(repl));
+			return NULL;
+		}
+		parse_blob_buffer(lookup_blob(sha1), NULL, 0);
+		return lookup_object(sha1);
+	}
+
 	buffer = read_sha1_file(sha1, &type, &size);
 	if (buffer) {
 		if (check_sha1_signature(repl, buffer, size, typename(type)) < 0) {
diff --git a/sha1_file.c b/sha1_file.c
index f9f8d5e..a77ef0a 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -19,6 +19,7 @@
 #include "pack-revindex.h"
 #include "sha1-lookup.h"
 #include "bulk-checkin.h"
+#include "streaming.h"
 
 #ifndef O_NOATIME
 #if defined(__linux__) && (defined(__i386__) || defined(__PPC__))
@@ -1149,7 +1150,37 @@ static const struct packed_git *has_packed_and_bad(const unsigned char *sha1)
 int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long size, const char *type)
 {
 	unsigned char real_sha1[20];
-	hash_sha1_file(map, size, type, real_sha1);
+	enum object_type obj_type;
+	struct git_istream *st;
+	git_SHA_CTX c;
+	char hdr[32];
+	int hdrlen;
+
+	if (map) {
+		hash_sha1_file(map, size, type, real_sha1);
+		return hashcmp(sha1, real_sha1) ? -1 : 0;
+	}
+
+	st = open_istream(sha1, &obj_type, &size, NULL);
+	if (!st)
+		return -1;
+
+	/* Generate the header */
+	hdrlen = sprintf(hdr, "%s %lu", typename(obj_type), size) + 1;
+
+	/* Sha1.. */
+	git_SHA1_Init(&c);
+	git_SHA1_Update(&c, hdr, hdrlen);
+	for (;;) {
+		char buf[1024 * 16];
+		ssize_t readlen = read_istream(st, buf, sizeof(buf));
+
+		if (!readlen)
+			break;
+		git_SHA1_Update(&c, buf, readlen);
+	}
+	git_SHA1_Final(real_sha1, &c);
+	close_istream(st);
 	return hashcmp(sha1, real_sha1) ? -1 : 0;
 }
 
-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply related

* [PATCH 05/11] show: use streaming interface for showing blobs
From: Nguyễn Thái Ngọc Duy @ 2012-02-27  7:55 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1330329315-11407-1-git-send-email-pclouds@gmail.com>


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/log.c    |    9 ++++++++-
 t/t1050-large.sh |    2 +-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/builtin/log.c b/builtin/log.c
index 7d1f6f8..4c4b17a 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -386,13 +386,20 @@ static int show_object(const unsigned char *sha1, int show_tag_object,
 {
 	unsigned long size;
 	enum object_type type;
-	char *buf = read_sha1_file(sha1, &type, &size);
+	char *buf;
 	int offset = 0;
 
+	if (!show_tag_object) {
+		fflush(stdout);
+		return streaming_write_sha1(1, 0, sha1, OBJ_ANY, NULL);
+	}
+
+	buf = read_sha1_file(sha1, &type, &size);
 	if (!buf)
 		return error(_("Could not read object %s"), sha1_to_hex(sha1));
 
 	if (show_tag_object)
+		assert(type == OBJ_TAG);
 		while (offset < size && buf[offset] != '\n') {
 			int new_offset = offset + 1;
 			while (new_offset < size && buf[new_offset++] != '\n')
diff --git a/t/t1050-large.sh b/t/t1050-large.sh
index 39a3e77..66acb3b 100755
--- a/t/t1050-large.sh
+++ b/t/t1050-large.sh
@@ -118,7 +118,7 @@ test_expect_success 'cat-file a large file' '
 	git cat-file blob :large1 >/dev/null
 '
 
-test_expect_failure 'git-show a large file' '
+test_expect_success 'git-show a large file' '
 	git show :large1 >/dev/null
 
 '
-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply related

* [PATCH 06/11] index-pack --verify: skip sha-1 collision test
From: Nguyễn Thái Ngọc Duy @ 2012-02-27  7:55 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1330329315-11407-1-git-send-email-pclouds@gmail.com>

index-pack --verify (or verify-pack) is about verifying the pack
itself. SHA-1 collision test is about outside (probably malicious)
objects with the same SHA-1 entering current repo.

SHA-1 collision test is currently done unconditionally. Which means if
you verify an in-repo pack, all objects from the pack will be checked
against objects in repo, which are themselves.

Skip this test for --verify, unless --strict is also specified.

linux-2.6 $ ls -sh .git/objects/pack/pack-e7732c98a8d54840add294c3c562840f78764196.pack
401M .git/objects/pack/pack-e7732c98a8d54840add294c3c562840f78764196.pack

Without the patch (and with another patch to cut out second pass in
index-pack):

linux-2.6 $ time ~/w/git/old index-pack -v --verify .git/objects/pack/pack-e7732c98a8d54840add294c3c562840f78764196.pack
Indexing objects: 100% (1944656/1944656), done.
fatal: pack has 1617280 unresolved deltas

real    1m1.223s
user    0m55.028s
sys     0m0.828s

With the patch:

linux-2.6 $ time ~/w/git/git index-pack -v --verify .git/objects/pack/pack-e7732c98a8d54840add294c3c562840f78764196.pack
Indexing objects: 100% (1944656/1944656), done.
fatal: pack has 1617280 unresolved deltas

real    0m41.714s
user    0m40.994s
sys     0m0.550s

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/index-pack.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index dd1c5c9..cee83b9 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -62,6 +62,7 @@ static int nr_resolved_deltas;
 
 static int from_stdin;
 static int strict;
+static int verify;
 static int verbose;
 
 static struct progress *progress;
@@ -461,7 +462,7 @@ static void sha1_object(const void *data, unsigned long size,
 			enum object_type type, unsigned char *sha1)
 {
 	hash_sha1_file(data, size, typename(type), sha1);
-	if (has_sha1_file(sha1)) {
+	if ((strict || !verify) && has_sha1_file(sha1)) {
 		void *has_data;
 		enum object_type has_type;
 		unsigned long has_size;
@@ -1078,7 +1079,7 @@ static void show_pack_info(int stat_only)
 
 int cmd_index_pack(int argc, const char **argv, const char *prefix)
 {
-	int i, fix_thin_pack = 0, verify = 0, stat_only = 0, stat = 0;
+	int i, fix_thin_pack = 0, stat_only = 0, stat = 0;
 	const char *curr_pack, *curr_index;
 	const char *index_name = NULL, *pack_name = NULL;
 	const char *keep_name = NULL, *keep_msg = NULL;
-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply related

* [PATCH 08/11] index-pack: reduce memory usage when the pack has large blobs
From: Nguyễn Thái Ngọc Duy @ 2012-02-27  7:55 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1330329315-11407-1-git-send-email-pclouds@gmail.com>

This command unpacks every non-delta objects in order to:

1. calculate sha-1
2. do byte-to-byte sha-1 collision test if we happen to have objects
   with the same sha-1
3. validate object content in strict mode

All this requires the entire object to stay in memory, a bad news for
giant blobs. This patch lowers memory consumption by not saving the
object in memory whenever possible, calculating SHA-1 while unpacking
the object.

This patch assumes that the collision test is rarely needed. The
collision test will be done later in second pass if necessary, which
puts the entire object back to memory again (We could even do the
collision test without putting the entire object back in memory, by
comparing as we unpack it).

In strict mode, it always keeps non-blob objects in memory for
validation (blobs do not need data validation). "--strict --verify"
also keeps blobs in memory.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/index-pack.c |   74 +++++++++++++++++++++++++++++++++++++++++---------
 t/t1050-large.sh     |    4 +-
 2 files changed, 63 insertions(+), 15 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index e3cb684..86de813 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -277,30 +277,60 @@ static void unlink_base_data(struct base_data *c)
 	free_base_data(c);
 }
 
-static void *unpack_entry_data(unsigned long offset, unsigned long size)
+static void *unpack_entry_data(unsigned long offset, unsigned long size,
+			       enum object_type type, unsigned char *sha1)
 {
+	static char fixed_buf[8192];
 	int status;
 	git_zstream stream;
-	void *buf = xmalloc(size);
+	void *buf;
+	git_SHA_CTX c;
+
+	if (sha1) {		/* do hash_sha1_file internally */
+		char hdr[32];
+		int hdrlen = sprintf(hdr, "%s %lu", typename(type), size)+1;
+		git_SHA1_Init(&c);
+		git_SHA1_Update(&c, hdr, hdrlen);
+
+		buf = fixed_buf;
+	} else {
+		buf = xmalloc(size);
+	}
 
 	memset(&stream, 0, sizeof(stream));
 	git_inflate_init(&stream);
 	stream.next_out = buf;
-	stream.avail_out = size;
+	stream.avail_out = buf == fixed_buf ? sizeof(fixed_buf) : size;
 
 	do {
 		stream.next_in = fill(1);
 		stream.avail_in = input_len;
 		status = git_inflate(&stream, 0);
 		use(input_len - stream.avail_in);
+		if (sha1) {
+			git_SHA1_Update(&c, buf, stream.next_out - (unsigned char *)buf);
+			stream.next_out = buf;
+			stream.avail_out = sizeof(fixed_buf);
+		}
 	} while (status == Z_OK);
 	if (stream.total_out != size || status != Z_STREAM_END)
 		bad_object(offset, "inflate returned %d", status);
 	git_inflate_end(&stream);
+	if (sha1) {
+		git_SHA1_Final(sha1, &c);
+		buf = NULL;
+	}
 	return buf;
 }
 
-static void *unpack_raw_entry(struct object_entry *obj, union delta_base *delta_base)
+static int is_delta_type(enum object_type type)
+{
+	return (type == OBJ_REF_DELTA || type == OBJ_OFS_DELTA);
+}
+
+static void *unpack_raw_entry(struct object_entry *obj,
+			      union delta_base *delta_base,
+			      unsigned char *sha1)
 {
 	unsigned char *p;
 	unsigned long size, c;
@@ -360,7 +390,17 @@ static void *unpack_raw_entry(struct object_entry *obj, union delta_base *delta_
 	}
 	obj->hdr_size = consumed_bytes - obj->idx.offset;
 
-	data = unpack_entry_data(obj->idx.offset, obj->size);
+	/*
+	 * --verify --strict: sha1_object() does all collision test
+	 *          --strict: sha1_object() does all except blobs,
+	 *                    blobs tested in second pass
+	 * --verify         : no collision test
+	 *                  : all in second pass
+	 */
+	if (is_delta_type(obj->type) ||
+	    (strict && (verify || obj->type != OBJ_BLOB)))
+		sha1 = NULL;	/* save unpacked object */
+	data = unpack_entry_data(obj->idx.offset, obj->size, obj->type, sha1);
 	obj->idx.crc32 = input_crc32;
 	return data;
 }
@@ -461,8 +501,9 @@ static void find_delta_children(const union delta_base *base,
 static void sha1_object(const void *data, unsigned long size,
 			enum object_type type, unsigned char *sha1)
 {
-	hash_sha1_file(data, size, typename(type), sha1);
-	if ((strict || !verify) && has_sha1_file(sha1)) {
+	if (data)
+		hash_sha1_file(data, size, typename(type), sha1);
+	if (data && (strict || !verify) && has_sha1_file(sha1)) {
 		void *has_data;
 		enum object_type has_type;
 		unsigned long has_size;
@@ -511,11 +552,6 @@ static void sha1_object(const void *data, unsigned long size,
 	}
 }
 
-static int is_delta_type(enum object_type type)
-{
-	return (type == OBJ_REF_DELTA || type == OBJ_OFS_DELTA);
-}
-
 /*
  * This function is part of find_unresolved_deltas(). There are two
  * walkers going in the opposite ways.
@@ -690,10 +726,22 @@ static int compare_delta_entry(const void *a, const void *b)
  * - if used as a base, uncompress the object and apply all deltas,
  *   recursively checking if the resulting object is used as a base
  *   for some more deltas.
+ * - if the same object exists in repository and we're not in strict
+ *   mode, we skipped the sha-1 collision test in the first pass.
+ *   Do it now.
  */
 static void second_pass(struct object_entry *obj)
 {
 	struct base_data *base_obj = alloc_base_data();
+
+	if (((!strict && !verify) ||
+	     (strict && !verify && obj->type == OBJ_BLOB)) &&
+	    has_sha1_file(obj->idx.sha1)) {
+		void *data = get_data_from_pack(obj);
+		sha1_object(data, obj->size, obj->type, obj->idx.sha1);
+		free(data);
+	}
+
 	base_obj->obj = obj;
 	base_obj->data = NULL;
 	find_unresolved_deltas(base_obj);
@@ -719,7 +767,7 @@ static void parse_pack_objects(unsigned char *sha1)
 				nr_objects);
 	for (i = 0; i < nr_objects; i++) {
 		struct object_entry *obj = &objects[i];
-		void *data = unpack_raw_entry(obj, &delta->base);
+		void *data = unpack_raw_entry(obj, &delta->base, obj->idx.sha1);
 		obj->real_type = obj->type;
 		if (is_delta_type(obj->type)) {
 			nr_deltas++;
diff --git a/t/t1050-large.sh b/t/t1050-large.sh
index 66acb3b..7e78c72 100755
--- a/t/t1050-large.sh
+++ b/t/t1050-large.sh
@@ -123,7 +123,7 @@ test_expect_success 'git-show a large file' '
 
 '
 
-test_expect_failure 'clone' '
+test_expect_success 'clone' '
 	git clone -n file://"$PWD"/.git new &&
 	(
 	cd new &&
@@ -132,7 +132,7 @@ test_expect_failure 'clone' '
 	)
 '
 
-test_expect_failure 'fetch updates' '
+test_expect_success 'fetch updates' '
 	echo modified >> large1 &&
 	git commit -q -a -m updated &&
 	(
-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply related

* [PATCH 07/11] index-pack: split second pass obj handling into own function
From: Nguyễn Thái Ngọc Duy @ 2012-02-27  7:55 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1330329315-11407-1-git-send-email-pclouds@gmail.com>


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/index-pack.c |   31 ++++++++++++++++++-------------
 1 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index cee83b9..e3cb684 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -683,6 +683,23 @@ static int compare_delta_entry(const void *a, const void *b)
 				   objects[delta_b->obj_no].type);
 }
 
+/*
+ * Second pass:
+ * - for all non-delta objects, look if it is used as a base for
+ *   deltas;
+ * - if used as a base, uncompress the object and apply all deltas,
+ *   recursively checking if the resulting object is used as a base
+ *   for some more deltas.
+ */
+static void second_pass(struct object_entry *obj)
+{
+	struct base_data *base_obj = alloc_base_data();
+	base_obj->obj = obj;
+	base_obj->data = NULL;
+	find_unresolved_deltas(base_obj);
+	display_progress(progress, nr_resolved_deltas);
+}
+
 /* Parse all objects and return the pack content SHA1 hash */
 static void parse_pack_objects(unsigned char *sha1)
 {
@@ -737,26 +754,14 @@ static void parse_pack_objects(unsigned char *sha1)
 	qsort(deltas, nr_deltas, sizeof(struct delta_entry),
 	      compare_delta_entry);
 
-	/*
-	 * Second pass:
-	 * - for all non-delta objects, look if it is used as a base for
-	 *   deltas;
-	 * - if used as a base, uncompress the object and apply all deltas,
-	 *   recursively checking if the resulting object is used as a base
-	 *   for some more deltas.
-	 */
 	if (verbose)
 		progress = start_progress("Resolving deltas", nr_deltas);
 	for (i = 0; i < nr_objects; i++) {
 		struct object_entry *obj = &objects[i];
-		struct base_data *base_obj = alloc_base_data();
 
 		if (is_delta_type(obj->type))
 			continue;
-		base_obj->obj = obj;
-		base_obj->data = NULL;
-		find_unresolved_deltas(base_obj);
-		display_progress(progress, nr_resolved_deltas);
+		second_pass(obj);
 	}
 }
 
-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox