Git development
 help / color / mirror / Atom feed
* Re: [PATCH] Rework strbuf API and semantics.
From: Junio C Hamano @ 2007-09-06  9:31 UTC (permalink / raw)
  To: Pierre Habouzit; +Cc: git
In-Reply-To: <11890199232110-git-send-email-madcoder@debian.org>

Pierre Habouzit <madcoder@debian.org> writes:

>   A strbuf can be used to store byte arrays, or as an extended string
> library. The `buf' member can be passed to any C legacy string function,
> because strbuf operations always ensure there is a terminating \0 at the end
> of the buffer, not accounted in the `len' field of the structure.
>
>   A strbuf can be used to generate a string/buffer whose final size is not
> really known, and then "strbuf_detach" can be used to get the built buffer,
> and keep the wrapping "strbuf" structure usable for further work again.
>
>   Other interesting feature: strbuf_grow(sb, size) ensure that there is
> enough allocated space in `sb' to put `size' new octets of data in the
> buffer. It helps avoiding reallocating data for nothing when the problem the
> strbuf helps to solve has a known typical size.

"Rework API semantics" needs to be accompanied with an API
description, perhaps at the beginning of each externally
visible function.

Also the commit log message needs to explain what the old
semantics was and what the improved one is, to highlight the
changes needed to the callers.  Especially...

> @@ -1657,11 +1656,11 @@ static void *cmd_data (size_t *size)
>  			if (term_len == command_buf.len
>  				&& !strcmp(term, command_buf.buf))
>  				break;
> -			ALLOC_GROW(buffer, length + command_buf.len, sz);
> +			ALLOC_GROW(buffer, length + command_buf.len + 1, sz);
>  			memcpy(buffer + length,
>  				command_buf.buf,
> -				command_buf.len - 1);
> -			length += command_buf.len - 1;
> +				command_buf.len);
> +			length += command_buf.len;
>  			buffer[length++] = '\n';
>  		}
>  		free(term);

... it is not all obvious why these off-by-one changes are
needed without such a description.  The other hunks in this
patch to this file are all such changes.

> -static void inline strbuf_add(struct strbuf *sb, int ch) {

> +static inline void strbuf_addch(struct strbuf *sb, size_t c) {
> +	strbuf_grow(sb, 1);
> +	sb->buf[sb->len++] = c;
> +	sb->buf[sb->len] = '\0';
> +}

You certainly did not mean size_t wide characters.

^ permalink raw reply

* Re: People unaware of the importance of "git gc"?
From: Andreas Ericsson @ 2007-09-06  9:28 UTC (permalink / raw)
  To: Russ Dill; +Cc: git
In-Reply-To: <loom.20070906T044017-727@post.gmane.org>

Russ Dill wrote:
>> Ok, how about doing something like this?
>>
> 
> git add? merge? rebase? No, I have a sneakier place to invoke gc.
> 
> Whenever $EDITOR gets invoked. Heck, whenever git is waiting for any user input,
> do some gc in the background, it'd just have to be incremental so that we could
> pick up where we left off.
> 

I like it. Writing a commit-message takes anywhere from 30 seconds to 5 minutes
for me (sometimes having to check up bug id's, or verifying details in the code).
Sneaking in a repack here would be absolutely stellar :)

It's also nice in that it won't affect people who just follow a project's tip to
get the bleeding edge. For them it shouldn't matter much that they have multiple
small packs obtained while fetching, or if it's all bungled together in a big one.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

^ permalink raw reply

* Re: [RFC] Convert builin-mailinfo.c to use The Better String Library.
From: Andreas Ericsson @ 2007-09-06  9:12 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Dmitry Kakurin, Matthieu Moy, Git
In-Reply-To: <20070906045942.GR18160@spearce.org>

Shawn O. Pearce wrote:
> Dmitry Kakurin <dmitry.kakurin@gmail.com> wrote:
>> When I first looked at Git source code two things struck me as odd:
>> 1. Pure C as opposed to C++. No idea why. Please don't talk about 
>> portability, it's BS.
> 
> It is also a relatively simple language that
> a large number of open source programmers know.  This makes it easy
> for them to get involved in the project.


This is important. Git contains code from more than 300 people. I'm
guessing you could cut that number by 2/3 if it had been written in C++.

Git is cheating a bit though. Its primary audience was (and is) the
various integrators working on the Linux kernel, all of whom are fairly
competent C programmers.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

^ permalink raw reply

* Re: Git's database structure
From: Junio C Hamano @ 2007-09-06  9:09 UTC (permalink / raw)
  To: Andreas Ericsson
  Cc: Jon Smirl, Julian Phillips, Theodore Tso, Git Mailing List
In-Reply-To: <46DFBF13.9040109@op5.se>

Andreas Ericsson <ae@op5.se> writes:

> Estimated daily uses of git-blame, world-wide: few
> Estimated daily uses of git-{merge,diff}, worldwide: lots

Which makes the author of git-blame weep X-<.

The real issue is that embedding pathname in blob does _not_
help "git blame" but would actively hurt it.  A file with the
identical contents moved between the parent to child commit
shares the same blob object and same object name in the real
git.  Jon's modified system that hashes pathname together with
the contents would have them as two completely unrelated objects
with different object names, which only means that even 100%
similarity rename case becomes as expensive to find as renames
of lower similarity, which needs to expand and look into blob
contents.

^ permalink raw reply

* Re: [PATCH 3/9] Add strbuf_printf() to do formatted printing to a strbuf.
From: Junio C Hamano @ 2007-09-06  8:55 UTC (permalink / raw)
  To: Kristian Høgsberg; +Cc: git
In-Reply-To: <11890382243290-git-send-email-krh@redhat.com>

As you noted in your follow-up message, this one has overlaps
with the other strbuf series.  I could adjust them if I wanted
to, but I do not have time for it right now.  I might try over
the weekend but no promises.

^ permalink raw reply

* What's cooking in git.git (topics)
From: Junio C Hamano @ 2007-09-06  8:52 UTC (permalink / raw)
  To: git

Here are the topics that have been cooking.  Commits prefixed
with '-' are only in 'pu' while commits prefixed with '+' are
in 'next'.  The topics list the commits in reverse chronological
order.

* js/tag (Mon Sep 3 17:51:43 2007 +0100) 1 commit
 + verify-tag: also grok CR/LFs in the tag signature

Looks correct.  Merge to 'master' this weekend.

* lh/svn-first-parent (Wed Sep 5 11:35:29 2007 +0200) 1 commit
 + git-svn: add support for --first-parent

Queued to 'next' with Eric's blessing.  Perhaps merge to
'master' by the end of next week unless there are issues.

* rs/archive (Mon Sep 3 20:08:01 2007 +0200) 3 commits
 + Remove unused function convert_sha1_file()
 + archive: specfile support (--pretty=format: in archive files)
 + Export format_commit_message()

Waiting for the "$Format: ...$" updates.

* js/remote (Sun Sep 2 21:10:14 2007 +0100) 1 commit
 + Teach "git remote" a mirror mode

Waiting for tests.  We should resurrect earlier "git remote rm"
and add tests for it as well.

* jc/stash-create (Mon Jul 9 00:51:23 2007 -0700) 2 commits
 - rebase: allow starting from a dirty tree.
 - stash: implement "stash create"

A quick hack to allow starting "git rebase" in a dirty work tree
by automatically stashing the changes first, and unstashing them
after rebase is done.  Needs tests and documentation.

* np/delta (Thu Sep 6 02:13:11 2007 -0400) 4 commits
 - basic threaded delta search
 - rearrange delta search progress reporting
 - localize window memory usage accounting
 - straighten the list of objects to deltify

I do not know where Nico's "threaded pack generation" would lead
us to yet, so they are parked on 'pu' for now.  The first in the
series should be applicable to 'next', though.

* jc/pack (Sat Sep 1 23:53:47 2007 -0700) 1 commit
 + Keep last used delta base in the delta window

Would need to straighten out the implementation from the one
that is suited for the original FIFO usage to another that is
more appropriate for LRU.

* jc/autogc (Wed Sep 5 14:59:59 2007 -0700) 2 commits
 - Invoke "git gc --auto" from commit, merge, am and rebase.
 - Implement git gc --auto

This has been updated since the ones I sent to the list earlier
in the day.  It detects a situation where the user has too much
cruft in the repository that too many loose objects are left
unpruned, and issues a warning.  Also 'rebase' is covered by
running "git gc --auto" from either merge or am.

* ph/strbuf (Wed Sep 5 21:18:43 2007 +0200) 7 commits
 - Use strbuf in cache-tree.c
 - Use strbuf in buitin-rerere.c
 - Use strbuf in apply, blame, commit-tree and diff
 - mktree: Simplify write_tree() using strbuf's.
 - fast-import: Use strbuf API, and simplify cmd_data()
 - Simplify strbuf uses in archive-tar.c using strbuf API
 - Rework strbuf API and semantics.

The idea is good, and removes more code than it adds, but I find
it not 'next' material yet.  I haven't checked every single line
yet, and this series needs that kind of vetting.

* jc/pathspec (Tue Sep 4 02:47:25 2007 -0700) 1 commit
 - tree-diff.c: split out a function to match a single pattern.

Just started and not even started to cause breakage yet ;-).
I'd want to fix pathspec semantics of "diff-tree", "log" and
"ls-tree" so that they understand globs in addition to leading
directory prefix, just like "ls-files", "diff-files",
"diff-index" and "grep" does.

* jc/diff (Mon Dec 25 01:08:50 2006 -0800) 2 commits
 - test-para: combined diff between HEAD, index and working tree.
 - para-walk: walk n trees, index and working tree in parallel

Have been on hold for a long time.  This is about traversing the
index, work tree and zero or more trees in parallel, which is
one way to rewrite the merge backend.  I may end up reusing
merge-tree.c implementation which would make this series
unnecessary.

^ permalink raw reply

* What's in git.git (stable)
From: Junio C Hamano @ 2007-09-06  8:52 UTC (permalink / raw)
  To: git

* The 'maint' branch has these fixes since v1.5.3.1

Dmitry V. Levin (1):
  Makefile: Add cache-tree.h to the headers list

Junio C Hamano (1):
  git-apply: do not read past the end of buffer

Shawn O. Pearce (3):
  Don't allow contrib/workdir/git-new-workdir to trash existing dirs
  Cleanup unnecessary file modifications in t1400-update-ref
  Include a git-push example for creating a remote branch


* The 'master' branch has these since v1.5.3 in addition to the
  above.

Carlos Rica (1):
  Function for updating refs.

Douglas Stockwell (1):
  send-email: Add support for SSL and SMTP-AUTH

Junio C Hamano (1):
  Start 1.5.4 cycle

Simon Hausmann (8):
  git-p4: Always call 'p4 sync ...' before submitting to Perforce.
  git-p4: After submission to p4 always synchronize from p4 again
      (into refs/remotes). Whether to rebase HEAD or not is still
      left as question to the end-user.
  git-p4: Cleanup; moved the code for getting a sorted list of p4
      changes for a list of given depot paths into a standalone
      method.
  git-p4: Cleanup; moved the code to import a list of p4 changes
      using fast-import into a separate member function of P4Sync.
  git-p4: Cleanup; Turn self.revision into a function local variable
      (it's not used anywhere outside the function).
  git-p4: Cleanup; moved the code for the initial #head or revision
      import into a separate function, out of P4Sync.run.
  git-p4: Cleanup; moved the (duplicated) code for turning a branch
      into a git ref (for example foo ->
      refs/remotes/p4/<project>/foo) into a separate method.
  git-p4: Added support for automatically importing newly appearing
      perforce branches.

^ permalink raw reply

* Re: Git's database structure
From: Andreas Ericsson @ 2007-09-06  8:49 UTC (permalink / raw)
  To: Jon Smirl; +Cc: Julian Phillips, Theodore Tso, Junio C Hamano, Git Mailing List
In-Reply-To: <9e4733910709050912i57ed7137o6abb02ee741d394b@mail.gmail.com>

Jon Smirl wrote:
> On 9/5/07, Julian Phillips <julian@quantumfyre.co.uk> wrote:
>> On Wed, 5 Sep 2007, Jon Smirl wrote:
>>
>>> On 9/5/07, Andreas Ericsson <ae@op5.se> wrote:
>>>> Jon Smirl wrote:
>>>>> The path name field needs to be moved back into the blobs to support
>>>>> alternative indexes. For example I want an index on the Signed-off-by
>>>>> field. I use this index to give me the SHAs for the blobs
>>>>> Signed-off-by a particular person. In the current design I have no way
>>>>> of recovering the path name for these blobs other than a brute force
>>>>> search following every path looking for the right SHA.
>>>>>
>>>> Ah, there we go. A use-case at last :)
>> But not a brilliant one.  You sign off on commits not blobs.  So you go
>> from the sign-off to paths, then to blobs.  There is no need to go from
>> blob to path unless you deliberately introduce such a need.
> 
> Use blame for an example. Blame has to crawl every commit to see if it
> touched the file. It keeps doing this until it figures out the last
> author for every line in the file. Worse case blame has to crawl every
> commit in the data store.
> 

Estimated daily uses of git-blame, world-wide: few
Estimated daily uses of git-{merge,diff}, worldwide: lots

Code and benchmarks, or I'm not buying it.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

^ permalink raw reply

* Re: [PATCH 2/3] Makefile: Add install-lib and install-include targets
From: Johannes Schindelin @ 2007-09-06  8:39 UTC (permalink / raw)
  To: Dmitry V. Levin; +Cc: Git Mailing List, Junio C Hamano
In-Reply-To: <20070905232213.GB331@nomad.office.altlinux.org>

Hi,

On Thu, 6 Sep 2007, Dmitry V. Levin wrote:

> Several external projects (e.g. parsecvs) need libgit library
> and related header files.

but does that not pretend that we have a stable API?  Which we have not at 
all, thank you very much.  However, Luiz created a thin libgit in his GSoC 
project, and IMHO this would be the way to continue.  If it is not 
complete enough, well, complete it.

Ciao,
Dscho

^ permalink raw reply

* Re: [RFC/PATCH] git-svn: add support for --first-parent
From: Lars Hjemli @ 2007-09-06  8:34 UTC (permalink / raw)
  To: Eric Wong; +Cc: git, Junio C Hamano
In-Reply-To: <20070906075104.GA10192@hand.yhbt.net>

On 9/6/07, Eric Wong <normalperson@yhbt.net> wrote:
> Lars Hjemli <hjemli@gmail.com> wrote:
> > On 9/5/07, Eric Wong <normalperson@yhbt.net> wrote:
> > > Lars Hjemli <hjemli@gmail.com> wrote:
> > > > When git-svn uses git-log to find embedded 'git-svn-id'-lines in commit
> > > > messages, it can get confused when local history contains merges with
> > > > other git-svn branches. But if --first-parent is supplied to git-log,
> > > > working_head_info() will only see 'branch-local' commits and thus the
> > > > first commit containing a 'git-svn-id' line should refer to the correct
> > > > subversion branch.
> > >
> > > Ideally, we'd probably stop, say something and give the user the choice
> > > of branches if multiple parents available.
> >
> > Could you elaborate? (I don't understand how following the first
> > parent of a merge could end up at the wrong svn branch)
>
> Well, if the user didn't know about --first-parent (like me yesterday
> :), they could still end up miscommitting to any branch.  That's been a
> complaint of users for a while now.  Thinking more about it,
> --first-parent should probably be the default.
>
> But, if they want to commit a different branch instead of the one they
> merged into (so the second/third/fourth parent), --first-parent would
> never give them that chance.

Ok, so maybe '--first-parent' should be the default unless the user
specified something like '--upstream <revspec>', like this:

diff --git a/git-svn.perl b/git-svn.perl
index d21eb7f..0590299 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -819,8 +819,13 @@ sub cmt_metadata {
 sub working_head_info {
        my ($head, $refs) = @_;
        my @args = ('log', '--no-color');
-       push @args, '--first-parent' if $_first_parent;
-       my ($fh, $ctx) = command_output_pipe(@args, $head);
+       if ($_revspec) {
+           push @args, $_revspec;
+       } else {
+           push @args, '--first-parent';
+           push @args, $head;
+       }
+       my ($fh, $ctx) = command_output_pipe(@args);
        my $hash;
        my %max;
        while (<$fh>) {

This should give the user plenty of rope ;-)

--
larsh

^ permalink raw reply related

* Re: [RFC/PATCH] git-svn: add support for --first-parent
From: David Kastrup @ 2007-09-06  8:05 UTC (permalink / raw)
  To: Eric Wong; +Cc: Lars Hjemli, git, Junio C Hamano
In-Reply-To: <20070906075104.GA10192@hand.yhbt.net>

Eric Wong <normalperson@yhbt.net> writes:

> Lars Hjemli <hjemli@gmail.com> wrote:
>> On 9/5/07, Eric Wong <normalperson@yhbt.net> wrote:
>> > Lars Hjemli <hjemli@gmail.com> wrote:
>> > > When git-svn uses git-log to find embedded 'git-svn-id'-lines in commit
>> > > messages, it can get confused when local history contains merges with
>> > > other git-svn branches. But if --first-parent is supplied to git-log,
>> > > working_head_info() will only see 'branch-local' commits and thus the
>> > > first commit containing a 'git-svn-id' line should refer to the correct
>> > > subversion branch.
>> >
>> > Ideally, we'd probably stop, say something and give the user the choice
>> > of branches if multiple parents available.
>> 
>> Could you elaborate? (I don't understand how following the first
>> parent of a merge could end up at the wrong svn branch)
>
> Well, if the user didn't know about --first-parent (like me yesterday
> :), they could still end up miscommitting to any branch.  That's been a
> complaint of users for a while now.  Thinking more about it,
> --first-parent should probably be the default.
>
> But, if they want to commit a different branch instead of the one they
> merged into (so the second/third/fourth parent), --first-parent would
> never give them that chance.

If they want to commit to a different branch, they can b****y well
check out that branch and merge to _that_.  That is the way all the
rest of git works and nobody whines that this is a restriction.

Quite the opposite: that git-svn does not feel constrained to actually
commit to the base of the checked-out branch is a complete nuisance.
_Why_ would anybody want to dcommit to a Subversion branch not
associated with the current branch?

Just yesterday, I _again_ had git-svn dcommit to a nonsensical branch
(this time, the commit was to branch instead of the trunk, while more
often the catastrophes happen the other way round).  And it is not
like git-svn gives you a chance to override this bad decision: you
have to rebase -i all of your commit messages from potential
cherrypicks or whatever else and remove the git-svn taglines manually
for every commit before git-svn will deign to dcommit to the same
branch as before.

Eric, this is not "flexibility".  This is madness.  If you think that
it is essential to dcommit to a branch unrelated to the current HEAD,
then create a sane command line interface for it that takes effect at
the time of dcommit.  But the current interface is just throwing dice
as far as the user is concerned, since the addition of git-svn tags to
commit messages happens behind his back, and any merge or cherrypick
or rebase 5 revisions back might come to bite you.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

^ permalink raw reply

* Re: [RFC/PATCH] git-svn: add support for --first-parent
From: Eric Wong @ 2007-09-06  7:51 UTC (permalink / raw)
  To: Lars Hjemli; +Cc: git, Junio C Hamano
In-Reply-To: <8c5c35580709060018p50398071s32b271d52f4dc7e3@mail.gmail.com>

Lars Hjemli <hjemli@gmail.com> wrote:
> On 9/5/07, Eric Wong <normalperson@yhbt.net> wrote:
> > Lars Hjemli <hjemli@gmail.com> wrote:
> > > When git-svn uses git-log to find embedded 'git-svn-id'-lines in commit
> > > messages, it can get confused when local history contains merges with
> > > other git-svn branches. But if --first-parent is supplied to git-log,
> > > working_head_info() will only see 'branch-local' commits and thus the
> > > first commit containing a 'git-svn-id' line should refer to the correct
> > > subversion branch.
> >
> > Ideally, we'd probably stop, say something and give the user the choice
> > of branches if multiple parents available.
> 
> Could you elaborate? (I don't understand how following the first
> parent of a merge could end up at the wrong svn branch)

Well, if the user didn't know about --first-parent (like me yesterday
:), they could still end up miscommitting to any branch.  That's been a
complaint of users for a while now.  Thinking more about it,
--first-parent should probably be the default.

But, if they want to commit a different branch instead of the one they
merged into (so the second/third/fourth parent), --first-parent would
never give them that chance.

-- 
Eric Wong

^ permalink raw reply

* Re: [RFC/PATCH] git-svn: add support for --first-parent
From: Lars Hjemli @ 2007-09-06  7:18 UTC (permalink / raw)
  To: Eric Wong; +Cc: git, Junio C Hamano
In-Reply-To: <20070905101929.GB11074@soma>

On 9/5/07, Eric Wong <normalperson@yhbt.net> wrote:
> Lars Hjemli <hjemli@gmail.com> wrote:
> > When git-svn uses git-log to find embedded 'git-svn-id'-lines in commit
> > messages, it can get confused when local history contains merges with
> > other git-svn branches. But if --first-parent is supplied to git-log,
> > working_head_info() will only see 'branch-local' commits and thus the
> > first commit containing a 'git-svn-id' line should refer to the correct
> > subversion branch.
>
> Ideally, we'd probably stop, say something and give the user the choice
> of branches if multiple parents available.

Could you elaborate? (I don't understand how following the first
parent of a merge could end up at the wrong svn branch)

--
larsh

^ permalink raw reply

* Re: Significant performance waste in git-svn and friends
From: Eric Wong @ 2007-09-06  7:04 UTC (permalink / raw)
  To: Mike Hommey; +Cc: git
In-Reply-To: <20070905184710.GA3632@glandium.org>

Mike Hommey <mh@glandium.org> wrote:
> Hi,

Hi Mike,

> Being a pervert abusing the way subversion doesn't deal with branches
> and tags, I'm actually not a user of git-svn or git-svnimport, because
> they just can't deal easily with my perversion. So I'm writing a script
> to do the conversion for me, and since I also like to learn new things
> when I'm coding, I'm writing it in ruby.
> 
> Anyways, one of the things I'm trying to convert is my svk repository
> for debian packaging of xulrunner (so, a significant subset of the
> mozilla tree), which doesn't involve a lot of revisions (around 280,
> because I only imported releases or CVS snapshots), but involves a lot
> of files (roughly 20k).
> 
> The first thing I noticed when twisting around the svk repo so that
> git-svn could somehow import it a while ago, is that running git-svn
> was in my case significantly slower than svnadmin dump | svnadmin load
> (more than 2 times slower).
> 
> And now, with my own script, I got the same kind of "slowdown". So I
> investigated it, and it didn't take long to realize that replacing
> git-hash-object by a simple reimplementation in ruby was *way* faster.
> git-hash-object being more than probably what you do the most when you
> import a remote repository, it is not much of a surprise that forking
> thousands of times is a huge performance waste.

I haven't looked at the times in a while, but I suspect that exec()
is the (much bigger) culprit.

Since I usually import off remote repositories, so I notice network
latency way before I notice local performance problems with git-svn.

> So, just for the record, I did a lame hack of git-svn to see what kind
> of speedup could happen in git-svn. You can find this lame hack as a
> patch below. I did some tests (with a 1.5.2.1 release) and here are the
> results, importing only the trunk (192 revisions), with no checkout, and
> redirecting stdout to /dev/null:
> 
> original git-svn:
> real    25m1.871s
> user    8m51.593s
> sys     12m31.659s
> 
> patched git-svn:
> real    14m45.870s
> user    7m31.928s
> sys     4m1.047s

That's awesome.

> - It might be worth testing if git-cat-file is called a lot. If so,
>   implementing a simple git-cat-file equivalent that would work for
>   unpacked objects could improve speed.

IIRC git-cat-file is called a lot.  Every modified file needs the
original cat-ed to make use of the delta.

> The same things obviously apply to git-cvsimport and other scripts
> calling git-hash-object a lot.

Making git-svn use fast-import would be very nice.  I've got a bunch
of other git-svn things that I need to work on, but having git-svn
converted to use fast-import would be nice.  Or allowing Git.pm
to access more of the git internals...

However, how well/poorly would fast-import work for incremental
fetches throughout the day?

-- 
Eric Wong

^ permalink raw reply

* Re: [PATCH] basic threaded delta search
From: Junio C Hamano @ 2007-09-06  7:01 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: git
In-Reply-To: <1189059193250-git-send-email-nico@cam.org>

Nicolas Pitre <nico@cam.org> writes:

> this is still rough, hence it is disabled by default.  You need to compile
> with "make THREADED_DELTA_SEARCH=1 ..." at the moment.
>
> Threading is done on different portions of the object list to be
> deltified. This is currently done by spliting the list into n parts and
> then a thread is spawned for each of them.  A better method would consist
> of spliting the list into more smaller parts and have the n threads
> pick the next part available.

Hmmm.  I wonder how the result is affected by such a partition;
aren't you going to have many objects that could have used
somebody else as a delta but gets stored as base because they
happen to be a very early part of their partition (and lacking
delta base candidates in the window)?  You cannot solve it with
overlapping partitions without busting the depth limit easily
either, I suspect.  Also how would this interact with the LRU
delta base window we discussed a week or two ago?

Separating the list into different object types would not have
any adverse impact coming from the "horizon" of delta base
candidates window (because we do not deltify across types), but
that is not very useful because we cannot gain much parallerism
from such a partition.

^ permalink raw reply

* Re: [PATCH] Include a git-push example for creating a remote branch
From: Junio C Hamano @ 2007-09-06  6:30 UTC (permalink / raw)
  To: Miles Bader; +Cc: Shawn O. Pearce, Junio C Hamano, git
In-Reply-To: <fc339e4a0709052257m4ddc5784obe64a8b75b79b19@mail.gmail.com>

"Miles Bader" <miles@gnu.org> writes:

> Maybe I"m weird, but I tend to think of the refs/... syntax as being
> for "only if you're doing something funny" cases.

The "refs/" syntax is there as the lowest level that is
universally usable to create and any ref.  It can be used to
push to branches, tags, or even remotes (aka "simulated fetch in
reverse").

It is just nobody felt strong enough reason to sugarcoat the
normalized syntax with something like:

	git push --create remote foo v1.2.0

You can be a hero by updating git-push to take such, and make it
interpret as if the user passed the normalized syntax which is:

	git push remote foo:refs/heads/foo v1.2.0:refs/tags/v1.2.0

^ permalink raw reply

* Re: [PATCH] basic threaded delta search
From: Nicolas Pitre @ 2007-09-06  6:23 UTC (permalink / raw)
  To: David Kastrup; +Cc: Junio C Hamano, git
In-Reply-To: <85ps0wfh8h.fsf@lola.goethe.zz>

On Thu, 6 Sep 2007, David Kastrup wrote:

> Nicolas Pitre <nico@cam.org> writes:
> 
> > this is still rough, hence it is disabled by default.  You need to compile
> > with "make THREADED_DELTA_SEARCH=1 ..." at the moment.
> >
> > Threading is done on different portions of the object list to be
> > deltified. This is currently done by spliting the list into n parts and
> > then a thread is spawned for each of them.  A better method would consist
> > of spliting the list into more smaller parts and have the n threads
> > pick the next part available.
> 
> In my experience, the worst performance hit happens when the real
> memory is exhausted and things start paging.  Threading on different
> portions of the object list is going to exacerbate the problem in the
> areas where it hits worst.

Just don't use it if you don't have 1) a SMP machine and 2) enough ram.
Threading will be enabled with a command line argument at some point.


Nicolas

^ permalink raw reply

* Re: [PATCH 2/2] git-tag -s must fail if gpg is broken and cannot sign tags
From: Junio C Hamano @ 2007-09-06  6:20 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Carlos Rica, git
In-Reply-To: <20070906042653.GQ18160@spearce.org>

"Shawn O. Pearce" <spearce@spearce.org> writes:

> "Shawn O. Pearce" <spearce@spearce.org> wrote:
>> If the user has misconfigured `user.signingkey` in their .git/config
>> or just doesn't have any secret keys on their keyring and they ask
>> for a signed tag with `git tag -s` we better make sure the resulting
>> tag was actually signed by gpg.
> ...
>>  I think this and my prior contrib/workdir patch should both go into
>>  maint.  This one in particular; it hurt us today when an automated
>>  tool that runs `git tag -s` didn't notice the GnuPG problems.
>
> I'm sorry, despite the subject of this email this is actually a
> *one* patch series.  The 2/2 is because I applied and tested this
> on top of the contrib/workdir patch I was talking about above and
> my email sending script thought it was a two patch series.

This seems to fail the test depending on the order processes
happen to be scheduled.  I haven't looked at it closely yet.

^ permalink raw reply

* Re: [PATCH] basic threaded delta search
From: David Kastrup @ 2007-09-06  6:19 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: Junio C Hamano, git
In-Reply-To: <1189059193250-git-send-email-nico@cam.org>

Nicolas Pitre <nico@cam.org> writes:

> this is still rough, hence it is disabled by default.  You need to compile
> with "make THREADED_DELTA_SEARCH=1 ..." at the moment.
>
> Threading is done on different portions of the object list to be
> deltified. This is currently done by spliting the list into n parts and
> then a thread is spawned for each of them.  A better method would consist
> of spliting the list into more smaller parts and have the n threads
> pick the next part available.

In my experience, the worst performance hit happens when the real
memory is exhausted and things start paging.  Threading on different
portions of the object list is going to exacerbate the problem in the
areas where it hits worst.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

^ permalink raw reply

* my recent patches
From: Nicolas Pitre @ 2007-09-06  6:19 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

I forgot to have them numbered, so here is the proper order:

1- "[PATCH] straighten the list of objects to deltify"
2- "[PATCH] localize window memory usage accounting"
3- "[PATCH] rearrange delta search progress reporting"
4- "[PATCH] basic threaded delta search"

Based on top of "next".


Nicolas

^ permalink raw reply

* [PATCH] basic threaded delta search
From: Nicolas Pitre @ 2007-09-06  6:13 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <11890591923270-git-send-email-nico@cam.org>

this is still rough, hence it is disabled by default.  You need to compile
with "make THREADED_DELTA_SEARCH=1 ..." at the moment.

Threading is done on different portions of the object list to be
deltified. This is currently done by spliting the list into n parts and
then a thread is spawned for each of them.  A better method would consist
of spliting the list into more smaller parts and have the n threads
pick the next part available.

Signed-off-by: Nicolas Pitre <nico@cam.org>
---
 Makefile               |    8 +++++
 builtin-pack-objects.c |   83 +++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 90 insertions(+), 1 deletions(-)

diff --git a/Makefile b/Makefile
index 51af531..a92fb31 100644
--- a/Makefile
+++ b/Makefile
@@ -122,6 +122,9 @@ all::
 # If not set it defaults to the bare 'wish'. If it is set to the empty
 # string then NO_TCLTK will be forced (this is used by configure script).
 #
+# Define THREADED_DELTA_SEARCH if you have pthreads and wish to exploit
+# parallel delta searching when packing objects.
+#
 
 GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
 	@$(SHELL_PATH) ./GIT-VERSION-GEN
@@ -662,6 +665,11 @@ ifdef NO_HSTRERROR
 	COMPAT_OBJS += compat/hstrerror.o
 endif
 
+ifdef THREADED_DELTA_SEARCH
+	BASIC_CFLAGS += -DTHREADED_DELTA_SEARCH
+	EXTLIBS += -lpthread
+endif
+
 ifeq ($(TCLTK_PATH),)
 NO_TCLTK=NoThanks
 endif
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 9d56592..1bcee23 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -15,6 +15,10 @@
 #include "list-objects.h"
 #include "progress.h"
 
+#ifdef THREADED_DELTA_SEARCH
+#include <pthread.h>
+#endif
+
 static const char pack_usage[] = "\
 git-pack-objects [{ -q | --progress | --all-progress }] \n\
 	[--max-pack-size=N] [--local] [--incremental] \n\
@@ -1290,6 +1294,25 @@ static int delta_cacheable(unsigned long src_size, unsigned long trg_size,
 	return 0;
 }
 
+#ifdef THREADED_DELTA_SEARCH
+
+static pthread_mutex_t read_mutex = PTHREAD_MUTEX_INITIALIZER;
+#define read_lock()		pthread_mutex_lock(&read_mutex)
+#define read_unlock()		pthread_mutex_unlock(&read_mutex)
+
+static pthread_mutex_t progress_mutex = PTHREAD_MUTEX_INITIALIZER;
+#define progress_lock()		pthread_mutex_lock(&progress_mutex)
+#define progress_unlock()	pthread_mutex_unlock(&progress_mutex)
+
+#else
+
+#define read_lock()		0
+#define read_unlock()		0
+#define progress_lock()		0
+#define progress_unlock()	0
+
+#endif
+
 /*
  * We search for deltas _backwards_ in a list sorted by type and
  * by size, so that we see progressively smaller and smaller files.
@@ -1348,7 +1371,9 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
 
 	/* Load data if not already done */
 	if (!trg->data) {
+		read_lock();
 		trg->data = read_sha1_file(trg_entry->idx.sha1, &type, &sz);
+		read_unlock();
 		if (!trg->data)
 			die("object %s cannot be read",
 			    sha1_to_hex(trg_entry->idx.sha1));
@@ -1358,7 +1383,9 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
 		*mem_usage += sz;
 	}
 	if (!src->data) {
+		read_lock();
 		src->data = read_sha1_file(src_entry->idx.sha1, &type, &sz);
+		read_unlock();
 		if (!src->data)
 			die("object %s cannot be read",
 			    sha1_to_hex(src_entry->idx.sha1));
@@ -1470,9 +1497,11 @@ static void find_deltas(struct object_entry **list, unsigned list_size,
 		if (entry->preferred_base)
 			goto next;
 
+		progress_lock();
 		(*processed)++;
 		if (progress)
 			display_progress(&progress_state, *processed);
+		progress_unlock();
 
 		/*
 		 * If the current object is at pack edge, take the depth the
@@ -1542,6 +1571,58 @@ static void find_deltas(struct object_entry **list, unsigned list_size,
 	free(array);
 }
 
+#ifdef THREADED_DELTA_SEARCH
+
+struct thread_params {
+	pthread_t thread;
+	struct object_entry **list;
+	unsigned list_size;
+	int window;
+	int depth;
+	unsigned *processed;
+};
+
+static void *threaded_find_deltas(void *arg)
+{
+	struct thread_params *p = arg;
+	if (p->list_size)
+		find_deltas(p->list, p->list_size,
+			    p->window, p->depth, p->processed);
+	return NULL;
+}
+
+#define NR_THREADS	8
+
+static void ll_find_deltas(struct object_entry **list, unsigned list_size,
+			   int window, int depth, unsigned *processed)
+{
+	struct thread_params p[NR_THREADS];
+	int i, ret;
+
+	for (i = 0; i < NR_THREADS; i++) {
+		unsigned sublist_size = list_size / (NR_THREADS - i);
+		p[i].list = list;
+		p[i].list_size = sublist_size;
+		p[i].window = window;
+		p[i].depth = depth;
+		p[i].processed = processed;
+		ret = pthread_create(&p[i].thread, NULL,
+				     threaded_find_deltas, &p[i]);
+		if (ret)
+			die("unable to create thread: %s", strerror(ret));
+		list += sublist_size;
+		list_size -= sublist_size;
+	}
+
+	for (i = 0; i < NR_THREADS; i++) {
+		pthread_join(p[i].thread, NULL);
+	}
+}
+
+#else
+#define ll_find_deltas find_deltas
+#endif
+
 static void prepare_pack(int window, int depth)
 {
 	struct object_entry **delta_list;
@@ -1583,7 +1664,7 @@ static void prepare_pack(int window, int depth)
 				       "Deltifying %u objects...", "",
 				       nr_deltas);
 		qsort(delta_list, n, sizeof(*delta_list), type_size_sort);
-		find_deltas(delta_list, n, window+1, depth, &nr_done);
+		ll_find_deltas(delta_list, n, window+1, depth, &nr_done);
 		if (progress)
 			stop_progress(&progress_state);
 		if (nr_done != nr_deltas)
-- 
1.5.3.1.844.g0a05-dirty

^ permalink raw reply related

* [PATCH] rearrange delta search progress reporting
From: Nicolas Pitre @ 2007-09-06  6:13 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <11890591923123-git-send-email-nico@cam.org>

This is to help threadification of the delta search code, with a bonus
consistency check.

Signed-off-by: Nicolas Pitre <nico@cam.org>
---
 builtin-pack-objects.c |   23 ++++++++++++++---------
 1 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index b8495bf..9d56592 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -1438,17 +1438,15 @@ static unsigned long free_unpacked(struct unpacked *n)
 }
 
 static void find_deltas(struct object_entry **list, unsigned list_size,
-			unsigned nr_deltas, int window, int depth)
+			int window, int depth, unsigned *processed)
 {
-	uint32_t i = list_size, idx = 0, count = 0, processed = 0;
+	uint32_t i = list_size, idx = 0, count = 0;
 	unsigned int array_size = window * sizeof(struct unpacked);
 	struct unpacked *array;
 	unsigned long mem_usage = 0;
 
 	array = xmalloc(array_size);
 	memset(array, 0, array_size);
-	if (progress)
-		start_progress(&progress_state, "Deltifying %u objects...", "", nr_deltas);
 
 	do {
 		struct object_entry *entry = list[--i];
@@ -1472,8 +1470,9 @@ static void find_deltas(struct object_entry **list, unsigned list_size,
 		if (entry->preferred_base)
 			goto next;
 
+		(*processed)++;
 		if (progress)
-			display_progress(&progress_state, ++processed);
+			display_progress(&progress_state, *processed);
 
 		/*
 		 * If the current object is at pack edge, take the depth the
@@ -1536,9 +1535,6 @@ static void find_deltas(struct object_entry **list, unsigned list_size,
 			idx = 0;
 	} while (i > 0);
 
-	if (progress)
-		stop_progress(&progress_state);
-
 	for (i = 0; i < window; ++i) {
 		free_delta_index(array[i].index);
 		free(array[i].data);
@@ -1581,8 +1577,17 @@ static void prepare_pack(int window, int depth)
 	}
 
 	if (nr_deltas) {
+		unsigned nr_done = 0;
+		if (progress)
+			start_progress(&progress_state,
+				       "Deltifying %u objects...", "",
+				       nr_deltas);
 		qsort(delta_list, n, sizeof(*delta_list), type_size_sort);
-		find_deltas(delta_list, n, nr_deltas, window+1, depth);
+		find_deltas(delta_list, n, window+1, depth, &nr_done);
+		if (progress)
+			stop_progress(&progress_state);
+		if (nr_done != nr_deltas)
+			die("inconsistency with delta count");
 	}
 	free(delta_list);
 }
-- 
1.5.3.1.844.g0a05-dirty

^ permalink raw reply related

* [PATCH] localize window memory usage accounting
From: Nicolas Pitre @ 2007-09-06  6:13 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <11890591912193-git-send-email-nico@cam.org>

This is to help threadification of delta searching.

Signed-off-by: Nicolas Pitre <nico@cam.org>
---
 builtin-pack-objects.c |   28 ++++++++++++++--------------
 1 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index b1c64be..b8495bf 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -78,7 +78,6 @@ static unsigned long delta_cache_size = 0;
 static unsigned long max_delta_cache_size = 0;
 static unsigned long cache_max_small_delta_size = 1000;
 
-static unsigned long window_memory_usage = 0;
 static unsigned long window_memory_limit = 0;
 
 /*
@@ -1300,7 +1299,7 @@ static int delta_cacheable(unsigned long src_size, unsigned long trg_size,
  * one.
  */
 static int try_delta(struct unpacked *trg, struct unpacked *src,
-		     unsigned max_depth)
+		     unsigned max_depth, unsigned long *mem_usage)
 {
 	struct object_entry *trg_entry = trg->entry;
 	struct object_entry *src_entry = src->entry;
@@ -1356,7 +1355,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
 		if (sz != trg_size)
 			die("object %s inconsistent object length (%lu vs %lu)",
 			    sha1_to_hex(trg_entry->idx.sha1), sz, trg_size);
-		window_memory_usage += sz;
+		*mem_usage += sz;
 	}
 	if (!src->data) {
 		src->data = read_sha1_file(src_entry->idx.sha1, &type, &sz);
@@ -1366,7 +1365,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
 		if (sz != src_size)
 			die("object %s inconsistent object length (%lu vs %lu)",
 			    sha1_to_hex(src_entry->idx.sha1), sz, src_size);
-		window_memory_usage += sz;
+		*mem_usage += sz;
 	}
 	if (!src->index) {
 		src->index = create_delta_index(src->data, src_size);
@@ -1376,7 +1375,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
 				warning("suboptimal pack - out of memory");
 			return 0;
 		}
-		window_memory_usage += sizeof_delta_index(src->index);
+		*mem_usage += sizeof_delta_index(src->index);
 	}
 
 	delta_buf = create_delta(src->index, trg->data, trg_size, &delta_size, max_size);
@@ -1423,18 +1422,19 @@ static unsigned int check_delta_limit(struct object_entry *me, unsigned int n)
 	return m;
 }
 
-static void free_unpacked(struct unpacked *n)
+static unsigned long free_unpacked(struct unpacked *n)
 {
-	window_memory_usage -= sizeof_delta_index(n->index);
+	unsigned long freed_mem = sizeof_delta_index(n->index);
 	free_delta_index(n->index);
 	n->index = NULL;
 	if (n->data) {
+		freed_mem += n->entry->size;
 		free(n->data);
 		n->data = NULL;
-		window_memory_usage -= n->entry->size;
 	}
 	n->entry = NULL;
 	n->depth = 0;
+	return freed_mem;
 }
 
 static void find_deltas(struct object_entry **list, unsigned list_size,
@@ -1443,7 +1443,7 @@ static void find_deltas(struct object_entry **list, unsigned list_size,
 	uint32_t i = list_size, idx = 0, count = 0, processed = 0;
 	unsigned int array_size = window * sizeof(struct unpacked);
 	struct unpacked *array;
-	int max_depth;
+	unsigned long mem_usage = 0;
 
 	array = xmalloc(array_size);
 	memset(array, 0, array_size);
@@ -1453,16 +1453,16 @@ static void find_deltas(struct object_entry **list, unsigned list_size,
 	do {
 		struct object_entry *entry = list[--i];
 		struct unpacked *n = array + idx;
-		int j, best_base = -1;
+		int j, max_depth, best_base = -1;
 
-		free_unpacked(n);
+		mem_usage -= free_unpacked(n);
 		n->entry = entry;
 
 		while (window_memory_limit &&
-		       window_memory_usage > window_memory_limit &&
+		       mem_usage > window_memory_limit &&
 		       count > 1) {
 			uint32_t tail = (idx + window - count) % window;
-			free_unpacked(array + tail);
+			mem_usage -= free_unpacked(array + tail);
 			count--;
 		}
 
@@ -1497,7 +1497,7 @@ static void find_deltas(struct object_entry **list, unsigned list_size,
 			m = array + other_idx;
 			if (!m->entry)
 				break;
-			ret = try_delta(n, m, max_depth);
+			ret = try_delta(n, m, max_depth, &mem_usage);
 			if (ret < 0)
 				break;
 			else if (ret > 0)
-- 
1.5.3.1.844.g0a05-dirty

^ permalink raw reply related

* [PATCH] straighten the list of objects to deltify
From: Nicolas Pitre @ 2007-09-06  6:13 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Not all objects are subject to deltification, so avoid carrying those
along, and provide the real count to progress display.

Signed-off-by: Nicolas Pitre <nico@cam.org>
---
 builtin-pack-objects.c |   77 ++++++++++++++++++++++++++----------------------
 1 files changed, 42 insertions(+), 35 deletions(-)

diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index e64e3a0..b1c64be 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -1313,12 +1313,6 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
 	if (trg_entry->type != src_entry->type)
 		return -1;
 
-	/* We do not compute delta to *create* objects we are not
-	 * going to pack.
-	 */
-	if (trg_entry->preferred_base)
-		return -1;
-
 	/*
 	 * We do not bother to try a delta that we discarded
 	 * on an earlier try, but only when reusing delta data.
@@ -1443,43 +1437,24 @@ static void free_unpacked(struct unpacked *n)
 	n->depth = 0;
 }
 
-static void find_deltas(struct object_entry **list, int window, int depth)
+static void find_deltas(struct object_entry **list, unsigned list_size,
+			unsigned nr_deltas, int window, int depth)
 {
-	uint32_t i = nr_objects, idx = 0, count = 0, processed = 0;
+	uint32_t i = list_size, idx = 0, count = 0, processed = 0;
 	unsigned int array_size = window * sizeof(struct unpacked);
 	struct unpacked *array;
 	int max_depth;
 
-	if (!nr_objects)
-		return;
 	array = xmalloc(array_size);
 	memset(array, 0, array_size);
 	if (progress)
-		start_progress(&progress_state, "Deltifying %u objects...", "", nr_result);
+		start_progress(&progress_state, "Deltifying %u objects...", "", nr_deltas);
 
 	do {
 		struct object_entry *entry = list[--i];
 		struct unpacked *n = array + idx;
 		int j, best_base = -1;
 
-		if (!entry->preferred_base)
-			processed++;
-
-		if (progress)
-			display_progress(&progress_state, processed);
-
-		if (entry->delta)
-			/* This happens if we decided to reuse existing
-			 * delta from a pack.  "!no_reuse_delta &&" is implied.
-			 */
-			continue;
-
-		if (entry->size < 50)
-			continue;
-
-		if (entry->no_try_delta)
-			continue;
-
 		free_unpacked(n);
 		n->entry = entry;
 
@@ -1491,6 +1466,15 @@ static void find_deltas(struct object_entry **list, int window, int depth)
 			count--;
 		}
 
+		/* We do not compute delta to *create* objects we are not
+		 * going to pack.
+		 */
+		if (entry->preferred_base)
+			goto next;
+
+		if (progress)
+			display_progress(&progress_state, ++processed);
+
 		/*
 		 * If the current object is at pack edge, take the depth the
 		 * objects that depend on the current object into account
@@ -1565,18 +1549,41 @@ static void find_deltas(struct object_entry **list, int window, int depth)
 static void prepare_pack(int window, int depth)
 {
 	struct object_entry **delta_list;
-	uint32_t i;
+	uint32_t i, n, nr_deltas;
 
 	get_object_details();
 
-	if (!window || !depth)
+	if (!nr_objects || !window || !depth)
 		return;
 
 	delta_list = xmalloc(nr_objects * sizeof(*delta_list));
-	for (i = 0; i < nr_objects; i++)
-		delta_list[i] = objects + i;
-	qsort(delta_list, nr_objects, sizeof(*delta_list), type_size_sort);
-	find_deltas(delta_list, window+1, depth);
+	nr_deltas = n = 0;
+
+	for (i = 0; i < nr_objects; i++) {
+		struct object_entry *entry = objects + i;
+
+		if (entry->delta)
+			/* This happens if we decided to reuse existing
+			 * delta from a pack.  "!no_reuse_delta &&" is implied.
+			 */
+			continue;
+
+		if (entry->size < 50)
+			continue;
+
+		if (entry->no_try_delta)
+			continue;
+
+		if (!entry->preferred_base)
+			nr_deltas++;
+
+		delta_list[n++] = entry;
+	}
+
+	if (nr_deltas) {
+		qsort(delta_list, n, sizeof(*delta_list), type_size_sort);
+		find_deltas(delta_list, n, nr_deltas, window+1, depth);
+	}
 	free(delta_list);
 }
 
-- 
1.5.3.1.844.g0a05-dirty

^ permalink raw reply related

* Re: [PATCH] Include a git-push example for creating a remote branch
From: Miles Bader @ 2007-09-06  5:57 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Junio C Hamano, git
In-Reply-To: <20070906050127.GS18160@spearce.org>

On 9/6/07, Shawn O. Pearce <spearce@spearce.org> wrote:
> Miles Bader <miles.bader@necel.com> wrote:
> > > Many users get confused when `git push origin master:foo` works
> > > when foo already exists on the remote repository but are confused
> > > when foo doesn't exist as a branch and this form does not create
> > > the branch foo.
> >
> > Hmm, what _does_ it do in that case...?
>
> error: dst refspec experimental does not match any existing ref on the remote and does not start with refs/.

Hmm, I'm assuming people don't want to default to just creating a new
remote ref ('cause it might be too easy to muck up a remote archive
that way), but it seems like it would be nice to have a "prettier" way
to create a remote ref than explicitly giving the whole ref path on
the remote side.

Maybe I"m weird, but I tend to think of the refs/... syntax as being
for "only if you're doing something funny" cases.

I'm thinking of something like:

  ... create new local branch "zoink" ...
  git push --create origin zoink

-Miles

-- 
Do not taunt Happy Fun Ball.

^ permalink raw reply


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