Git development
 help / color / mirror / Atom feed
* git submodules and diffing
From: Sven Herzberg @ 2007-11-09 21:19 UTC (permalink / raw)
  To: git-list

Hi,

when I started working with git submodules, I realized that git-diff  
only lists the revision ids of a submodule if it has changed. I have  
created a repository which includes a diff command for git-submodule,  
so you can use it like "gut submodule diff <modules...>"

I pushed my git tree at git://git.imendio.com/sven/git.git

Feel free to look into the changes and request improvements or merge  
it into your tree.

Regards,
   Sven

PS: Please CC me, I'm not on this list

^ permalink raw reply

* Re: [PATCH 2/2] --pretty=format: on-demand format expansion
From: Johannes Schindelin @ 2007-11-09 22:18 UTC (permalink / raw)
  To: René Scharfe
  Cc: Junio C Hamano, Paul Mackerras, Git Mailing List, Pierre Habouzit
In-Reply-To: <4734CD78.4000704@lsrfire.ath.cx>

Hi,

On Fri, 9 Nov 2007, Ren? Scharfe wrote:

> Johannes Schindelin schrieb:
> > Hi,
> > 
> > On Fri, 9 Nov 2007, Ren? Scharfe wrote:
> > 
> >>  strbuf.c |   24 ++++++
> >>  strbuf.h |    3 +
> >>  pretty.c |  276 ++++++++++++++++++++++++++++++++++----------------------------
> > 
> > I would be so grateful if you could (trivially) split up this patch into 
> > the addition of strbuf_expend() (with a small example in the commit 
> > message), and a patch that uses it in pretty.c.
> 
> Makes sense.  Will do next time.

You mean next time you write strbuf_expand()?

;-)  I saw that Junio already applied your patch as is.  Hmm.

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH 07/11] git-fetch: Limit automated tag following to only fetched objects
From: Junio C Hamano @ 2007-11-09 22:26 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: git
In-Reply-To: <20071109110631.GG19368@spearce.org>

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

> We now redefine the rule to be: "tags are fetched if they refer
> to an object that was just transferred; that is an object that is
> new to your repository".  This rule is quite simple to understand,
> you only get a tag if you just got the object it refers to.

In other words, if I do this:

	git fetch git-gui master

(which should not follow any tags) when your master is a bit
ahead of a new tag in git-gui I do not have, and then
immediately afterwards if I do:

	git fetch git-gui

I will not get the new tag followed?

If that is what the patch does, it feels like a regression.

The intended behaviour was "when tag following is enabled, they
are followed if they refer to an object that is reachable from
your existing refs".

But this is quite expensive to compute.  If a tag points at a
blob that is contained inside a commit that is reachable from a
ref, we would need to grep "git rev-list --objects -all" output
to find it out.  I do not offhand recall what the scripted
version did, but I would not be surprised if as an approximation
we did the auto-following by "does the pointee exist" check.

What "random behaviour" are you trying to fix? 

^ permalink raw reply

* Re: [PATCH 04/11] Allow pooled nodes to be recycled back onto a free list
From: Junio C Hamano @ 2007-11-09 22:27 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: git
In-Reply-To: <20071109110619.GD19368@spearce.org>

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

> In some cases and for some node types a caller may have used one of
> our allocated nodes for some temporary usage and then wants to return
> it back to the available free list.  We now define a function that
> will thread the object onto the front of a free list, which will be
> used only after the current block has been exhausted.
>
> We hold off on looking at the free list until we are sure the current
> block is empty.  This saves about 1000 tests of the (usually empty)
> free list per block.
>
> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>

> +void free_##name##_node(void *n)				\
> +{								\
> +	*((void**)n) = name##_pool.free_list;			\
> +	name##_pool.free_list = n;				\
> +}								\
>  static void report_##name(void)					\
>  {								\
>  	report(#name, &name##_pool, sizeof(t));			\

I wonder how well this will interact with object scrubbing.  A
freed node is still in the array in the block bucket and the
scrubber walks the array without skipping any freed node, but
the threading pointer already scribbled on the first
sizeof(void**) bytes on the object memory.  Worse, the caller
may say "Hey, I am freeing this node, so I'll bzero() it before
returning it to the pool", without realizing that the scrubber
may still act on that freed node buffer.

The rules for a "class designer" on freeing a temporary node
with this implementation as I understand it is:

 - do assume free_all will call scrubber on freed nodes;

 - do not have anything your scrubber needs to access near the
   beginning of the nodes managed by alloc.c API;

 - do not clobber anything scrubber needs to access when freeing
   a node.

For struct object and its descendant classes, I think this is a
non issue -- the first bytes in the structure are the flags and
sha1[] and the current implementation of the scrubbers would not
look at these fields.

But it does look like a risk in the future.

^ permalink raw reply

* Re: [PATCH 06/11] git-fetch: Release objects used by a prior transport
From: Junio C Hamano @ 2007-11-09 22:27 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: git
In-Reply-To: <20071109110626.GF19368@spearce.org>

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

> Some transports allocate objects in the internal object hashtable
> during the fetch process (e.g. the HTTP commit walker and also the
> native protocol).  These shouldn't be visible to another transport
> call running in the same fetch process when we fetch the tags during
> automated tag following.  By deallocating the object table (if it
> has anything in it) we ensure the second transport execution will
> be from a clean slate.
>
> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
> ---
>  builtin-fetch.c |    5 ++++-
>  1 files changed, 4 insertions(+), 1 deletions(-)
>
> diff --git a/builtin-fetch.c b/builtin-fetch.c
> index 847db73..18f123e 100644
> --- a/builtin-fetch.c
> +++ b/builtin-fetch.c
> @@ -337,7 +337,10 @@ static void store_updated_refs(const char *url, struct ref *ref_map)
>  
>  static int fetch_refs(struct transport *transport, struct ref *ref_map)
>  {
> -	int ret = transport_fetch_refs(transport, ref_map);
> +	int ret;
> +
> +	free_all_objects();
> +	ret = transport_fetch_refs(transport, ref_map);
>  	if (!ret)
>  		store_updated_refs(transport->url, ref_map);
>  	transport_unlock_pack(transport);

This sounds a very heavy-handed approach.

Is it the callers responsibility to know what function does call
free_all_objects() and makes sure there is no pointer to objects
obtained before the call that is used after the call returns?

^ permalink raw reply

* Re: [PATCH 2/2] --pretty=format: on-demand format expansion
From: Junio C Hamano @ 2007-11-09 22:30 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: René Scharfe, Paul Mackerras, Git Mailing List,
	Pierre Habouzit
In-Reply-To: <Pine.LNX.4.64.0711092218150.4362@racer.site>

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> You mean next time you write strbuf_expand()?
>
> ;-)  I saw that Junio already applied your patch as is.  Hmm.

Which only means we expect incremental improvements on top of it
from now on, it does not mean "it is perfect and cast in stone".

^ permalink raw reply

* Re: [PATCH 01/11] Fix memory leak in traverse_commit_list
From: Junio C Hamano @ 2007-11-09 22:43 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: git
In-Reply-To: <20071109110610.GA19368@spearce.org>

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

> diff --git a/list-objects.c b/list-objects.c
> index e5c88c2..713bef9 100644
> --- a/list-objects.c
> +++ b/list-objects.c
> @@ -170,4 +170,11 @@ void traverse_commit_list(struct rev_info *revs,
>  	}
>  	for (i = 0; i < objects.nr; i++)
>  		show_object(&objects.objects[i]);
> +	free(objects.objects);
> +	if (revs->pending.nr) {
> +		revs->pending.nr = 0;
> +		revs->pending.alloc = 0;
> +		revs->pending.objects = NULL;
> +		free(revs->pending.objects);
> +	}
>  }

It is locally verifiable that objects.objects are no longer
needed after this point, but it made me a bit nervous about
freeing of revs->pending.objects.

I think the existing callers are all Ok, but somebody else
should double check.

^ permalink raw reply

* Re: git submodules and diffing
From: Jakub Narebski @ 2007-11-09 22:57 UTC (permalink / raw)
  To: Sven Herzberg, git; +Cc: Jakub Narebski
In-Reply-To: <4D079E0B-D6FB-4FBA-B449-2EFBFD5A5DE4@imendio.com>

Sven Herzberg wrote:

> When I started working with git submodules, I realized that git-diff  
> only lists the revision ids of a submodule if it has changed. I have  
> created a repository which includes a diff command for git-submodule,  
> so you can use it like "gut submodule diff <modules...>"
> 
> I pushed my git tree at git://git.imendio.com/sven/git.git

I have checked it int the gitweb at
  http://git.imendio.com/?p=sven/git.git

> Feel free to look into the changes and request improvements or merge  
> it into your tree.

As far as I can see that is single patch (single commit) on top of
git.git repository, so you could have send this patch to the list,
to be commented upon.

Although having "git submodule diff" is quite nice, I'd rather have
"git diff --recurse-submodules" (or something like that) if I want to
get diff of submodules.

>From browsing commitdiff
  http://git.imendio.com/?p=sven/git.git;a=commitdiff;h=7fa1d4911d1ac2590ab1eccd84a7f235aca7878e
I'd like to mention that instead of

  (unset GIT_DIR && cd "$path" && git diff $flag "$sha1..HEAD")

you can simply use

  git --git-dir="$path" diff $flag "$sha1..HEAD"

Note that you can write "$sha1.." (but it is a bit cryptic)

> PS: Please CC me, I'm not on this list

You can always read list using NNTP / news / Usenet interface at
  nntp://news.gmane.org/gmane.comp.version-control.git
or one of the mailing list archives, see
  http://git.or.cz/gitwiki/GitCommunity

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

^ permalink raw reply

* git on ancient compilers.
From: Jon Smirl @ 2007-11-09 23:14 UTC (permalink / raw)
  To: Git Mailing List

My hosting company is using: gcc (GCC) 3.3.5 (Debian 1:3.3.5-13)

git is using a link parameter not available in 3.3.5

   LINK git-mktree
gcc: unrecognized option `-R/home/jonsmirl1/lib'
    LINK git-patch-id
gcc: unrecognized option `-R/home/jonsmirl1/lib'
    LINK git-peek-remote
gcc: unrecognized option `-R/home/jonsmirl1/lib'
    LINK git-receive-pack
gcc: unrecognized option `-R/home/jonsmirl1/lib'
    LINK git-send-pack
gcc: unrecognized option `-R/home/jonsmirl1/lib'
    LINK git-shell
gcc: unrecognized option `-R/home/jonsmirl1/lib'
    LINK git-show-index



-- 
Jon Smirl
jonsmirl@gmail.com

^ permalink raw reply

* Re: [PATCH 2/2] --pretty=format: on-demand format expansion
From: René Scharfe @ 2007-11-09 23:16 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Paul Mackerras, Git Mailing List, Pierre Habouzit,
	Johannes Schindelin
In-Reply-To: <20071109045040.GC31760@sigill.intra.peff.net>

Jeff King schrieb:
> - formatting expensive items multiple times will incur work 
> proportional to the number of times the item is used (in the old 
> code, it was calculated just once).  e.g., "%h%h%h%h"
> 
> - formatting some items goes to some work that can be re-used by
> other items (e.g., %ad and %ar both need to parse the author date)
> 
> And we could obviously overcome both by caching the results of
> expensive operations.  I'm not sure if these will be a problem in
> practice. For the first one, the new code is so much faster that I
> needed to do
> 
> git-log --pretty=format:%h%h%h%h%h%h%h%h
> 
> to get a performance regression from the old code, which seems rather
>  unlikely. For the second, it is easy to imagine multiple "person"
> items being used together, although their cost to produce is not all
> that high. It looks like about .05 seconds to parse a date (over all
> commits in git.git):
> 
> $ time ./git-log --pretty='format:' >/dev/null real    0m0.441s user
> 0m0.424s sys     0m0.004s
> 
> $ time ./git-log --pretty='format:%ad' >/dev/null real    0m0.477s 
> user    0m0.472s sys     0m0.000s
> 
> $ time ./git-log --pretty='format:%ad %aD' >/dev/null real
> 0m0.527s user    0m0.520s sys     0m0.004s
> 
> where the last two could probably end up costing about the same if we
> cached the author parsing (but the caching will have a cost, too, so
> it might not end up being a big win).
> 
> So it might make sense to cache some items as we figure them out.
> This should be done by the calling code and not by strbuf_expand
> (since it doesn't know which things are worth caching (and for fast
> things, allocating memory for a cache entry is likely to be slower),
> or how the expansions relate to each other).

I fully agree with the above.

> A partial patch on top of yours is below (it caches commit and tree 
> abbreviations; parent abbreviations and person-parsing are probably 
> worth doing). Some timings:

... but I object to the choice of items to cache.  Are there real-world
formats containing the same placeholder twice or even more often?

There is probably more to gain from the interdependencies of different
placeholders.  The patch below attempts to avoid parsing the commit
twice, by saving pointers to the different parts.

(next)
$ time git log --pretty=format:"* %cd %cn%n%n%s%n%b" >/dev/null

real    0m0.631s
user    0m0.584s
sys     0m0.040s

(next+patch)
$ time git log --pretty=format:"* %cd %cn%n%n%s%n%b" >/dev/null

real    0m0.570s
user    0m0.512s
sys     0m0.044s

The format is from http://svn.tue.mpg.de/tentakel/trunk/tentakel/Makefile
which I found while googling for real-world use cases.

While the code size is increased by the patch, most of the code gets
simplified.


 pretty.c |  128 ++++++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 86 insertions(+), 42 deletions(-)

diff --git a/pretty.c b/pretty.c
index 9fbd73f..b2f10a3 100644
--- a/pretty.c
+++ b/pretty.c
@@ -354,14 +354,69 @@ static void format_person_part(struct strbuf *sb, char part,
 	}
 }
 
+struct parsed_commit_header {
+	int parsed;
+	const char *subject_start;
+	const char *author_start;
+	const char *committer_start;
+	const char *encoding_start;
+	const char *body_start;
+	size_t subject_len;
+	size_t author_len;
+	size_t committer_len;
+	size_t encoding_len;
+};
+
+struct format_commit_context {
+	const struct commit *commit;
+	struct parsed_commit_header *parsed_commit_header;
+};
+
+static void parse_commit_header(struct parsed_commit_header *pch,
+                                const struct commit *commit)
+{
+	const char *msg = commit->buffer;
+	int i;
+	enum { HEADER, SUBJECT, BODY } state;
+
+	for (i = 0, state = HEADER; msg[i] && state < BODY; i++) {
+		int eol;
+		for (eol = i; msg[eol] && msg[eol] != '\n'; eol++)
+			; /* do nothing */
+
+		if (state == SUBJECT) {
+			pch->subject_start = msg + i;
+			pch->subject_len = eol - i;
+			i = eol;
+		}
+		if (i == eol) {
+			state++;
+			/* strip empty lines */
+			while (msg[eol + 1] == '\n')
+				eol++;
+		} else if (!prefixcmp(msg + i, "author ")) {
+			pch->author_start = msg + i + 7;
+			pch->author_len = eol - i - 7;
+		} else if (!prefixcmp(msg + i, "committer ")) {
+			pch->committer_start = msg + i + 10;
+			pch->committer_len = eol - i - 10;
+		} else if (!prefixcmp(msg + i, "encoding ")) {
+			pch->encoding_start = msg + i + 9;
+			pch->encoding_len = eol - i - 9;
+		}
+		i = eol;
+	}
+	pch->body_start = msg + i;
+	pch->parsed = 1;
+}
+
 static void format_commit_item(struct strbuf *sb, const char *placeholder,
                                void *context)
 {
-	const struct commit *commit = context;
+	struct format_commit_context *c = context;
+	const struct commit *commit = c->commit;
+	struct parsed_commit_header *pch = c->parsed_commit_header;
 	struct commit_list *p;
-	int i;
-	enum { HEADER, SUBJECT, BODY } state;
-	const char *msg = commit->buffer;
 
 	/* these are independent of the commit */
 	switch (placeholder[0]) {
@@ -429,45 +484,28 @@ static void format_commit_item(struct strbuf *sb, const char *placeholder,
 	}
 
 	/* For the rest we have to parse the commit header. */
-	for (i = 0, state = HEADER; msg[i] && state < BODY; i++) {
-		int eol;
-		for (eol = i; msg[eol] && msg[eol] != '\n'; eol++)
-			; /* do nothing */
+	if (!pch->parsed)
+		parse_commit_header(pch, commit);
 
-		if (state == SUBJECT) {
-			if (placeholder[0] == 's') {
-				strbuf_add(sb, msg + i, eol - i);
-				return;
-			}
-			i = eol;
-		}
-		if (i == eol) {
-			state++;
-			/* strip empty lines */
-			while (msg[eol + 1] == '\n')
-				eol++;
-		} else if (!prefixcmp(msg + i, "author ")) {
-			if (placeholder[0] == 'a') {
-				format_person_part(sb, placeholder[1],
-				                   msg + i + 7, eol - i - 7);
-				return;
-			}
-		} else if (!prefixcmp(msg + i, "committer ")) {
-			if (placeholder[0] == 'c') {
-				format_person_part(sb, placeholder[1],
-				                   msg + i + 10, eol - i - 10);
-				return;
-			}
-		} else if (!prefixcmp(msg + i, "encoding ")) {
-			if (placeholder[0] == 'e') {
-				strbuf_add(sb, msg + i + 9, eol - i - 9);
-				return;
-			}
-		}
-		i = eol;
+	switch (placeholder[0]) {
+	case 's':
+		strbuf_add(sb, pch->subject_start, pch->subject_len);
+		return;
+	case 'a':
+		format_person_part(sb, placeholder[1],
+		                   pch->author_start, pch->author_len);
+		return;
+	case 'c':
+		format_person_part(sb, placeholder[1],
+		                   pch->committer_start, pch->committer_len);
+		return;
+	case 'e':
+		strbuf_add(sb, pch->encoding_start, pch->encoding_len);
+		return;
+	case 'b':
+		strbuf_addstr(sb, pch->body_start);
+		return;
 	}
-	if (msg[i] && placeholder[0] == 'b')	/* body */
-		strbuf_addstr(sb, msg + i);
 }
 
 void format_commit_message(const struct commit *commit,
@@ -505,7 +543,13 @@ void format_commit_message(const struct commit *commit,
 		"m",		/* left/right/bottom */
 		NULL
 	};
-	strbuf_expand(sb, format, placeholders, format_commit_item, (void *)commit);
+	struct parsed_commit_header pch;
+	struct format_commit_context context;
+
+	memset(&pch, 0, sizeof(pch));
+	context.commit = commit;
+	context.parsed_commit_header = &pch;
+	strbuf_expand(sb, format, placeholders, format_commit_item, &context);
 }
 
 static void pp_header(enum cmit_fmt fmt,

^ permalink raw reply related

* Re: git on ancient compilers.
From: Jon Smirl @ 2007-11-09 23:19 UTC (permalink / raw)
  To: Git Mailing List
In-Reply-To: <9e4733910711091514k55473201jf29434961f01e46c@mail.gmail.com>

jonsmirl@terra:~$ ld --version
GNU ld (GNU Binutils for Ubuntu) 2.18

-- 
Jon Smirl
jonsmirl@gmail.com

^ permalink raw reply

* Re: [PATCH 2/2] --pretty=format: on-demand format expansion
From: René Scharfe @ 2007-11-09 23:20 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Paul Mackerras, Git Mailing List, Pierre Habouzit,
	Johannes Schindelin
In-Reply-To: <20071109045256.GD31760@sigill.intra.peff.net>

Jeff King schrieb:
> On Fri, Nov 09, 2007 at 01:49:42AM +0100, René Scharfe wrote:
> 
>> +	strbuf_expand(sb, format, placeholders, format_commit_item, (void *)commit);
> 
> This void cast is pointless, since all pointers types convert implicitly
> to void pointers anyway. At best, it does nothing, and at worst, it
> hides an actual type error if the function signature or the type of
> 'commit' change.

When commit (of type const struct commit*) is implicitly converted to
void *, gcc complains because the "const" qualifier is silently dropped.

^ permalink raw reply

* Re: git 1.5.3.5 error over NFS
From: Alex Riesen @ 2007-11-09 23:21 UTC (permalink / raw)
  To: Bill Lear; +Cc: git
In-Reply-To: <18228.32091.865519.312011@lisa.zopyra.com>

Bill Lear, Fri, Nov 09, 2007 16:31:39 +0100:
> I've brought this up before, but I don't recall a resolution to it.
> 
> We have an NFS-mounted filesystem, and git pull is choking on it.
> 
> % uname -a
> Linux uhlr.zopyra.com 2.6.9-42.0.2.ELsmp #1 SMP Wed Aug 23 13:38:27 BST 2006 x86_64 x86_64 x86_64 GNU/Linux
> 
> % git --version
> git version 1.5.3.5
> 
> % git pull
> remote: Generating pack...
> remote: Done counting 998 objects.
> remote: Result has 836 objects.
> remote: Deltifying 836 objects.
> remote:  100% (836/836) done
> Indexing 836 objects...
> remote: Total 836 (delta 526), reused 688 (delta 380)
>   100% (836/836) done
> Resolving 526 deltas...
> fatal: cannot pread pack file: No such file or directory

Could you please strace it? With strace -ff?

> fatal: index-pack died with error code 128
> fatal: Fetch failure: git://source/repo
> 
> I looked through the archives of this list and did not see a final
> resolution, other than a suspected bug in the OS NFS code.

Strace, just to be on the safe side

^ permalink raw reply

* Re: git on ancient compilers.
From: Jon Smirl @ 2007-11-09 23:22 UTC (permalink / raw)
  To: Git Mailing List
In-Reply-To: <9e4733910711091519r75692418hec2fbd7ccea5771b@mail.gmail.com>

I found this option...

# Define NO_R_TO_GCC_LINKER if your gcc does not like "-R/path/lib"
# that tells runtime paths to dynamic libraries;
# "-Wl,-rpath=/path/lib" is used instead.

-- 
Jon Smirl
jonsmirl@gmail.com

^ permalink raw reply

* git push mirror mode V4 (replacement stack)
From: Andy Whitcroft @ 2007-11-09 23:30 UTC (permalink / raw)
  To: git, Junio C Hamano; +Cc: Johannes Schindelin

Following this mail is a complete replacement git push mirror mode
stack (V4).  It folds down all the various patches into a logical
sequence (thanks Dscho).  This stack passes the entire test suite,
and I have been using the same code for real work here.

Please replace what you have in pu with this stack.

-apw

^ permalink raw reply

* [PATCH 1/4] Teach send-pack a mirror mode
From: Andy Whitcroft @ 2007-11-09 23:32 UTC (permalink / raw)
  To: git
In-Reply-To: <20071109233041.GC301@shadowen.org>


Existing "git push --all" is almost perfect for backing up to
another repository, except that "--all" only means "all
branches" in modern git, and it does not delete old branches and
tags that exist at the back-up repository that you have removed
from your local repository.

This teaches "git-send-pack" a new "--mirror" option.  The
difference from the "--all" option are that (1) it sends all
refs, not just branches, and (2) it deletes old refs you no
longer have on the local side from the remote side.

Original patch by Junio C Hamano.

Signed-off-by: Andy Whitcroft <apw@shadowen.org>
---
 builtin-send-pack.c |   46 ++++++++++++++++++++++++++++++++++------------
 http-push.c         |    4 ++--
 remote.c            |   15 ++++++++++-----
 remote.h            |    7 +++++++
 send-pack.h         |    1 +
 5 files changed, 54 insertions(+), 19 deletions(-)
diff --git a/builtin-send-pack.c b/builtin-send-pack.c
index 5a0f5c6..d42164e 100644
--- a/builtin-send-pack.c
+++ b/builtin-send-pack.c
@@ -8,7 +8,7 @@
 #include "send-pack.h"
 
 static const char send_pack_usage[] =
-"git-send-pack [--all] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
+"git-send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
 "  --all and explicit <ref> specification are mutually exclusive.";
 
 static struct send_pack_args args = {
@@ -227,6 +227,12 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
 	int allow_deleting_refs = 0;
 	int expect_status_report = 0;
 	int shown_dest = 0;
+	int flags = MATCH_REFS_NONE;
+
+	if (args.send_all)
+		flags |= MATCH_REFS_ALL;
+	if (args.send_mirror)
+		flags |= MATCH_REFS_MIRROR;
 
 	/* No funny business with the matcher */
 	remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL);
@@ -242,7 +248,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
 	if (!remote_tail)
 		remote_tail = &remote_refs;
 	if (match_refs(local_refs, remote_refs, &remote_tail,
-		       nr_refspec, refspec, args.send_all))
+					       nr_refspec, refspec, flags))
 		return -1;
 
 	if (!remote_refs) {
@@ -259,20 +265,28 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
 		char old_hex[60], *new_hex;
 		int will_delete_ref;
 		const char *pretty_ref;
-		const char *pretty_peer;
+		const char *pretty_peer = NULL; /* only used when not deleting */
+		const unsigned char *new_sha1;
 
-		if (!ref->peer_ref)
-			continue;
+		if (!ref->peer_ref) {
+			if (!args.send_mirror)
+				continue;
+			new_sha1 = null_sha1;
+		}
+		else
+			new_sha1 = ref->peer_ref->new_sha1;
 
 		if (!shown_dest) {
 			fprintf(stderr, "To %s\n", dest);
 			shown_dest = 1;
 		}
 
+		will_delete_ref = is_null_sha1(new_sha1);
+
 		pretty_ref = prettify_ref(ref->name);
-		pretty_peer = prettify_ref(ref->peer_ref->name);
+		if (!will_delete_ref)
+			pretty_peer = prettify_ref(ref->peer_ref->name);
 
-		will_delete_ref = is_null_sha1(ref->peer_ref->new_sha1);
 		if (will_delete_ref && !allow_deleting_refs) {
 			fprintf(stderr, " ! %-*s %s (remote does not support deleting refs)\n",
 					SUMMARY_WIDTH, "[rejected]", pretty_ref);
@@ -280,7 +294,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
 			continue;
 		}
 		if (!will_delete_ref &&
-		    !hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) {
+		    !hashcmp(ref->old_sha1, new_sha1)) {
 			if (args.verbose)
 				fprintf(stderr, " = %-*s %s -> %s\n",
 					SUMMARY_WIDTH, "[up to date]",
@@ -312,8 +326,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
 		    !is_null_sha1(ref->old_sha1) &&
 		    !ref->force) {
 			if (!has_sha1_file(ref->old_sha1) ||
-			    !ref_newer(ref->peer_ref->new_sha1,
-				       ref->old_sha1)) {
+			    !ref_newer(new_sha1, ref->old_sha1)) {
 				/* We do not have the remote ref, or
 				 * we know that the remote ref is not
 				 * an ancestor of what we are trying to
@@ -328,7 +341,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
 				continue;
 			}
 		}
-		hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
+		hashcpy(ref->new_sha1, new_sha1);
 		if (!will_delete_ref)
 			new_refs++;
 		strcpy(old_hex, sha1_to_hex(ref->old_sha1));
@@ -459,6 +472,10 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
 				args.dry_run = 1;
 				continue;
 			}
+			if (!strcmp(arg, "--mirror")) {
+				args.send_mirror = 1;
+				continue;
+			}
 			if (!strcmp(arg, "--force")) {
 				args.force_update = 1;
 				continue;
@@ -483,7 +500,12 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
 	}
 	if (!dest)
 		usage(send_pack_usage);
-	if (heads && args.send_all)
+	/*
+	 * --all and --mirror are incompatible; neither makes sense
+	 * with any refspecs.
+	 */
+	if ((heads && (args.send_all || args.send_mirror)) ||
+					(args.send_all && args.send_mirror))
 		usage(send_pack_usage);
 
 	if (remote_name) {
diff --git a/http-push.c b/http-push.c
index 99328f5..66b81f1 100644
--- a/http-push.c
+++ b/http-push.c
@@ -78,7 +78,7 @@ static struct curl_slist *no_pragma_header;
 static struct curl_slist *default_headers;
 
 static int push_verbosely;
-static int push_all;
+static int push_all = MATCH_REFS_NONE;
 static int force_all;
 static int dry_run;
 
@@ -2300,7 +2300,7 @@ int main(int argc, char **argv)
 
 		if (*arg == '-') {
 			if (!strcmp(arg, "--all")) {
-				push_all = 1;
+				push_all = MATCH_REFS_ALL;
 				continue;
 			}
 			if (!strcmp(arg, "--force")) {
diff --git a/remote.c b/remote.c
index 59defdb..09b7aad 100644
--- a/remote.c
+++ b/remote.c
@@ -722,10 +722,12 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,
  * without thinking.
  */
 int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
-	       int nr_refspec, const char **refspec, int all)
+	       int nr_refspec, const char **refspec, int flags)
 {
 	struct refspec *rs =
 		parse_ref_spec(nr_refspec, (const char **) refspec);
+	int send_all = flags & MATCH_REFS_ALL;
+	int send_mirror = flags & MATCH_REFS_MIRROR;
 
 	if (match_explicit_refs(src, dst, dst_tail, rs, nr_refspec))
 		return -1;
@@ -742,7 +744,7 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
 			if (!pat)
 				continue;
 		}
-		else if (prefixcmp(src->name, "refs/heads/"))
+		else if (!send_mirror && prefixcmp(src->name, "refs/heads/"))
 			/*
 			 * "matching refs"; traditionally we pushed everything
 			 * including refs outside refs/heads/ hierarchy, but
@@ -763,10 +765,13 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
 		if (dst_peer && dst_peer->peer_ref)
 			/* We're already sending something to this ref. */
 			goto free_name;
-		if (!dst_peer && !nr_refspec && !all)
-			/* Remote doesn't have it, and we have no
+
+		if (!dst_peer && !nr_refspec && !(send_all || send_mirror))
+			/*
+			 * Remote doesn't have it, and we have no
 			 * explicit pattern, and we don't have
-			 * --all. */
+			 * --all nor --mirror.
+			 */
 			goto free_name;
 		if (!dst_peer) {
 			/* Create a new one and link it */
diff --git a/remote.h b/remote.h
index 6a4c7a0..b10036c 100644
--- a/remote.h
+++ b/remote.h
@@ -102,4 +102,11 @@ struct branch *branch_get(const char *name);
 int branch_has_merge_config(struct branch *branch);
 int branch_merge_matches(struct branch *, int n, const char *);
 
+/* Flags to match_refs. */
+enum match_refs_flags {
+	MATCH_REFS_NONE		= 0,
+	MATCH_REFS_ALL 		= (1 << 0),
+	MATCH_REFS_MIRROR	= (1 << 1),
+};
+
 #endif
diff --git a/send-pack.h b/send-pack.h
index 7a24f71..8ff1dc3 100644
--- a/send-pack.h
+++ b/send-pack.h
@@ -5,6 +5,7 @@ struct send_pack_args {
 	const char *receivepack;
 	unsigned verbose:1,
 		send_all:1,
+		send_mirror:1,
 		force_update:1,
 		use_thin_pack:1,
 		dry_run:1;

^ permalink raw reply related

* [PATCH 2/4] git-push: plumb in --mirror mode
From: Andy Whitcroft @ 2007-11-09 23:32 UTC (permalink / raw)
  To: git
In-Reply-To: <20071109233041.GC301@shadowen.org>


Plumb in the --mirror mode for git-push.

Signed-off-by: Andy Whitcroft <apw@shadowen.org>
---
 builtin-push.c |   14 ++++++++++++--
 transport.c    |    7 +++++++
 transport.h    |    1 +
 3 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/builtin-push.c b/builtin-push.c
index 2c56195..d49157c 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -10,7 +10,7 @@
 #include "parse-options.h"
 
 static const char * const push_usage[] = {
-	"git-push [--all] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]",
+	"git-push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]",
 	NULL,
 };
 
@@ -91,6 +91,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 {
 	int flags = 0;
 	int all = 0;
+	int mirror = 0;
 	int dry_run = 0;
 	int force = 0;
 	int tags = 0;
@@ -100,6 +101,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 		OPT__VERBOSE(&verbose),
 		OPT_STRING( 0 , "repo", &repo, "repository", "repository"),
 		OPT_BOOLEAN( 0 , "all", &all, "push all refs"),
+		OPT_BOOLEAN( 0 , "mirror", &mirror, "mirror all refs"),
 		OPT_BOOLEAN( 0 , "tags", &tags, "push tags"),
 		OPT_BOOLEAN( 0 , "dry-run", &dry_run, "dry run"),
 		OPT_BOOLEAN('f', "force", &force, "force updates"),
@@ -119,13 +121,21 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 		add_refspec("refs/tags/*");
 	if (all)
 		flags |= TRANSPORT_PUSH_ALL;
+	if (mirror)
+		flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
 
 	if (argc > 0) {
 		repo = argv[0];
 		set_refspecs(argv + 1, argc - 1);
 	}
-	if ((flags & TRANSPORT_PUSH_ALL) && refspec)
+	if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) && refspec)
 		usage_with_options(push_usage, options);
 
+	if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
+				(TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
+		error("--all and --mirror are incompatible");
+		usage_with_options(push_usage, options);
+	}
+
 	return do_push(repo, flags);
 }
diff --git a/transport.c b/transport.c
index 83677fc..fad97d7 100644
--- a/transport.c
+++ b/transport.c
@@ -284,6 +284,9 @@ static int rsync_transport_push(struct transport *transport,
 	struct child_process rsync;
 	const char *args[10];
 
+	if (flags & TRANSPORT_PUSH_MIRROR)
+		return error("rsync transport does not support mirror mode");
+
 	/* first push the objects */
 
 	strbuf_addstr(&buf, transport->url);
@@ -387,6 +390,9 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons
 	int argc;
 	int err;
 
+	if (flags & TRANSPORT_PUSH_MIRROR)
+		return error("http transport does not support mirror mode");
+
 	argv = xmalloc((refspec_nr + 11) * sizeof(char *));
 	argv[0] = "http-push";
 	argc = 1;
@@ -655,6 +661,7 @@ static int git_transport_push(struct transport *transport, int refspec_nr, const
 
 	args.receivepack = data->receivepack;
 	args.send_all = !!(flags & TRANSPORT_PUSH_ALL);
+	args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
 	args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
 	args.use_thin_pack = data->thin;
 	args.verbose = transport->verbose;
diff --git a/transport.h b/transport.h
index d27f562..7f337d2 100644
--- a/transport.h
+++ b/transport.h
@@ -30,6 +30,7 @@ struct transport {
 #define TRANSPORT_PUSH_ALL 1
 #define TRANSPORT_PUSH_FORCE 2
 #define TRANSPORT_PUSH_DRY_RUN 4
+#define TRANSPORT_PUSH_MIRROR 8
 
 /* Returns a transport suitable for the url */
 struct transport *transport_get(struct remote *, const char *);

^ permalink raw reply related

* [PATCH 3/4] Add tests for git push'es mirror mode
From: Andy Whitcroft @ 2007-11-09 23:32 UTC (permalink / raw)
  To: git
In-Reply-To: <20071109233041.GC301@shadowen.org>


Add some tests for git push --mirror mode.

Signed-off-by: Andy Whitcroft <apw@shadowen.org>
---
 t/t5517-push-mirror.sh |  228 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 228 insertions(+), 0 deletions(-)
diff --git a/t/t5517-push-mirror.sh b/t/t5517-push-mirror.sh
new file mode 100755
index 0000000..0fc6778
--- /dev/null
+++ b/t/t5517-push-mirror.sh
@@ -0,0 +1,228 @@
+#!/bin/sh
+
+test_description='pushing to a mirror repository'
+
+. ./test-lib.sh
+
+D=`pwd`
+
+invert () {
+	if "$@"; then
+		return 1
+	else
+		return 0
+	fi
+}
+
+mk_repo_pair () {
+	rm -rf master mirror &&
+	mkdir mirror &&
+	(
+		cd mirror &&
+		git init
+	) &&
+	mkdir master &&
+	(
+		cd master &&
+		git init &&
+		git config remote.up.url ../mirror
+	)
+}
+
+
+# BRANCH tests
+test_expect_success 'push mirror does not create new branches' '
+
+	mk_repo_pair &&
+	(
+		cd master &&
+		echo one >foo && git add foo && git commit -m one &&
+		git push --mirror up
+	) &&
+	master_master=$(cd master && git show-ref -s --verify refs/heads/master) &&
+	mirror_master=$(cd mirror && git show-ref -s --verify refs/heads/master) &&
+	test "$master_master" = "$mirror_master"
+
+'
+
+test_expect_success 'push mirror does not update existing branches' '
+
+	mk_repo_pair &&
+	(
+		cd master &&
+		echo one >foo && git add foo && git commit -m one &&
+		git push --mirror up &&
+		echo two >foo && git add foo && git commit -m two &&
+		git push --mirror up
+	) &&
+	master_master=$(cd master && git show-ref -s --verify refs/heads/master) &&
+	mirror_master=$(cd mirror && git show-ref -s --verify refs/heads/master) &&
+	test "$master_master" = "$mirror_master"
+
+'
+
+test_expect_success 'push mirror does not force update existing branches' '
+
+	mk_repo_pair &&
+	(
+		cd master &&
+		echo one >foo && git add foo && git commit -m one &&
+		git push --mirror up &&
+		echo two >foo && git add foo && git commit -m two &&
+		git push --mirror up &&
+		git reset --hard HEAD^
+		git push --mirror up
+	) &&
+	master_master=$(cd master && git show-ref -s --verify refs/heads/master) &&
+	mirror_master=$(cd mirror && git show-ref -s --verify refs/heads/master) &&
+	test "$master_master" = "$mirror_master"
+
+'
+
+test_expect_success 'push mirror does not remove branches' '
+
+	mk_repo_pair &&
+	(
+		cd master &&
+		echo one >foo && git add foo && git commit -m one &&
+		git branch remove master &&
+		git push --mirror up &&
+		git branch -D remove
+		git push --mirror up
+	) &&
+	(
+		cd mirror &&
+		invert git show-ref -s --verify refs/heads/remove
+	)
+
+'
+
+test_expect_success 'push mirror does not add, update and remove branches together' '
+
+	mk_repo_pair &&
+	(
+		cd master &&
+		echo one >foo && git add foo && git commit -m one &&
+		git branch remove master &&
+		git push --mirror up &&
+		git branch -D remove &&
+		git branch add master &&
+		echo two >foo && git add foo && git commit -m two &&
+		git push --mirror up
+	) &&
+	master_master=$(cd master && git show-ref -s --verify refs/heads/master) &&
+	master_add=$(cd master && git show-ref -s --verify refs/heads/add) &&
+	mirror_master=$(cd mirror && git show-ref -s --verify refs/heads/master) &&
+	mirror_add=$(cd mirror && git show-ref -s --verify refs/heads/add) &&
+	test "$master_master" = "$mirror_master" &&
+	test "$master_add" = "$mirror_add" &&
+	(
+		cd mirror &&
+		invert git show-ref -s --verify refs/heads/remove
+	)
+
+'
+
+
+# TAG tests
+test_expect_success 'push mirror does not create new tags' '
+
+	mk_repo_pair &&
+	(
+		cd master &&
+		echo one >foo && git add foo && git commit -m one &&
+		git tag -f tmaster master &&
+		git push --mirror up
+	) &&
+	master_master=$(cd master && git show-ref -s --verify refs/tags/tmaster) &&
+	mirror_master=$(cd mirror && git show-ref -s --verify refs/tags/tmaster) &&
+	test "$master_master" = "$mirror_master"
+
+'
+
+test_expect_success 'push mirror does not update existing tags' '
+
+	mk_repo_pair &&
+	(
+		cd master &&
+		echo one >foo && git add foo && git commit -m one &&
+		git tag -f tmaster master &&
+		git push --mirror up &&
+		echo two >foo && git add foo && git commit -m two &&
+		git tag -f tmaster master &&
+		git push --mirror up
+	) &&
+	master_master=$(cd master && git show-ref -s --verify refs/tags/tmaster) &&
+	mirror_master=$(cd mirror && git show-ref -s --verify refs/tags/tmaster) &&
+	test "$master_master" = "$mirror_master"
+
+'
+
+test_expect_success 'push mirror does not force update existing tags' '
+
+	mk_repo_pair &&
+	(
+		cd master &&
+		echo one >foo && git add foo && git commit -m one &&
+		git tag -f tmaster master &&
+		git push --mirror up &&
+		echo two >foo && git add foo && git commit -m two &&
+		git tag -f tmaster master &&
+		git push --mirror up &&
+		git reset --hard HEAD^
+		git tag -f tmaster master &&
+		git push --mirror up
+	) &&
+	master_master=$(cd master && git show-ref -s --verify refs/tags/tmaster) &&
+	mirror_master=$(cd mirror && git show-ref -s --verify refs/tags/tmaster) &&
+	test "$master_master" = "$mirror_master"
+
+'
+
+test_expect_success 'push mirror does not remove tags' '
+
+	mk_repo_pair &&
+	(
+		cd master &&
+		echo one >foo && git add foo && git commit -m one &&
+		git tag -f tremove master &&
+		git push --mirror up &&
+		git tag -d tremove
+		git push --mirror up
+	) &&
+	(
+		cd mirror &&
+		invert git show-ref -s --verify refs/tags/tremove
+	)
+
+'
+
+test_expect_success 'push mirror does not add, update and remove tags together' '
+
+	mk_repo_pair &&
+	(
+		cd master &&
+		echo one >foo && git add foo && git commit -m one &&
+		git tag -f tmaster master &&
+		git tag -f tremove master &&
+		git push --mirror up &&
+		git tag -d tremove &&
+		git tag tadd master &&
+		echo two >foo && git add foo && git commit -m two &&
+		git tag -f tmaster master &&
+		git push --mirror up
+	) &&
+	master_master=$(cd master && git show-ref -s --verify refs/tags/tmaster) &&
+	master_add=$(cd master && git show-ref -s --verify refs/tags/tadd) &&
+	mirror_master=$(cd mirror && git show-ref -s --verify refs/tags/tmaster) &&
+	mirror_add=$(cd mirror && git show-ref -s --verify refs/tags/tadd) &&
+	test "$master_master" = "$mirror_master" &&
+	test "$master_add" = "$mirror_add" &&
+	(
+		cd mirror &&
+		invert git show-ref -s --verify refs/tags/tremove
+	)
+
+'
+
+test_done

^ permalink raw reply related

* [PATCH 4/4] git-push: add documentation for the newly added --mirror mode
From: Andy Whitcroft @ 2007-11-09 23:32 UTC (permalink / raw)
  To: git
In-Reply-To: <20071109233041.GC301@shadowen.org>


Add some basic documentation on the --mirror mode for git-push.

Signed-off-by: Andy Whitcroft <apw@shadowen.org>
---
 Documentation/git-push.txt |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index e5dd4c1..3fa5992 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -63,6 +63,14 @@ the remote repository.
 	Instead of naming each ref to push, specifies that all
 	refs under `$GIT_DIR/refs/heads/` be pushed.
 
+\--mirror::
+	Instead of naming each ref to push, specifies that all
+	refs under `$GIT_DIR/refs/heads/` and `$GIT_DIR/refs/tags/`
+	be mirrored to the remote repository.  Newly created local
+	refs will be pushed to the remote end, locally updated refs
+	will be force updated on the remote end, and deleted refs
+	will be removed from the remote end.
+
 \--dry-run::
 	Do everything except actually send the updates.
 

^ permalink raw reply related

* Reducing the memory footprint
From: Jon Smirl @ 2007-11-09 23:38 UTC (permalink / raw)
  To: Git Mailing List

I'm using this config file:

[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
        packedGitWindowSize = 1M
        packedGitLimit = 1M
        deltaBaseCacheLimit = 1M
[pack]
        windowMemory = 1M
        deltaCacheSize = 1M

And I have NO_MMAP compiled in.

git is still using over 200MB of memory or address space, my process
gets killed either way.

Ideas on how to reduce the foot print more?

-- 
Jon Smirl
jonsmirl@gmail.com

^ permalink raw reply

* Re: [PATCH 2/2] --pretty=format: on-demand format expansion
From: Paul Mackerras @ 2007-11-09 23:39 UTC (permalink / raw)
  To: René Scharfe
  Cc: Junio C Hamano, Git Mailing List, Pierre Habouzit,
	Johannes Schindelin
In-Reply-To: <4733AEA6.1040802@lsrfire.ath.cx>

Thanks for doing this.

Could I ask for a couple more things?  I would find it useful to have
format codes for the number of characters in the commit body.  Having
a code for the number of bytes in the commit body would also be
useful.  When reading commits in with Tcl, the number of characters is
more useful, but I can use the number of bytes (and I imagine others
would find that useful).

Paul.

^ permalink raw reply

* Re: [PATCH 01/11] Fix memory leak in traverse_commit_list
From: Johannes Schindelin @ 2007-11-09 23:51 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Shawn O. Pearce, git
In-Reply-To: <7vmytnqbu2.fsf@gitster.siamese.dyndns.org>

Hi,

On Fri, 9 Nov 2007, Junio C Hamano wrote:

> "Shawn O. Pearce" <spearce@spearce.org> writes:
> 
> > diff --git a/list-objects.c b/list-objects.c
> > index e5c88c2..713bef9 100644
> > --- a/list-objects.c
> > +++ b/list-objects.c
> > @@ -170,4 +170,11 @@ void traverse_commit_list(struct rev_info *revs,
> >  	}
> >  	for (i = 0; i < objects.nr; i++)
> >  		show_object(&objects.objects[i]);
> > +	free(objects.objects);
> > +	if (revs->pending.nr) {
> > +		revs->pending.nr = 0;
> > +		revs->pending.alloc = 0;
> > +		revs->pending.objects = NULL;
> > +		free(revs->pending.objects);

Umm. Isn't this the wrong way around?  Should you not free() first, and 
then set to NULL?

Ciao,
Dscho

^ permalink raw reply

* `git-send-email' doesn't specify `Content-Type'
From: Ludovic Courtès @ 2007-11-10  0:14 UTC (permalink / raw)
  To: git

Hi,

Apparently, `git-send-email' doesn't specify the email's `Content-Type',
notably its charset, while it should really add something like:

  Content-Type: text/plain; charset=UTF-8

Or did I miss an option or something?

Thanks,
Ludovic.

^ permalink raw reply

* Re: [PATCH 2/2] --pretty=format: on-demand format expansion
From: Johannes Schindelin @ 2007-11-10  0:31 UTC (permalink / raw)
  To: René Scharfe
  Cc: Jeff King, Junio C Hamano, Paul Mackerras, Git Mailing List,
	Pierre Habouzit
In-Reply-To: <4734EA4E.8070405@lsrfire.ath.cx>

Hi,

On Sat, 10 Nov 2007, Ren? Scharfe wrote:

> (next)
> $ time git log --pretty=format:"* %cd %cn%n%n%s%n%b" >/dev/null
> 
> real    0m0.631s
> user    0m0.584s
> sys     0m0.040s
> 
> (next+patch)
> $ time git log --pretty=format:"* %cd %cn%n%n%s%n%b" >/dev/null
> 
> real    0m0.570s
> user    0m0.512s
> sys     0m0.044s

Wow.

If you keep going like that, "git log" will be slower than "git log 
--pretty=format:bla" soon.

Ciao,
Dscho

^ permalink raw reply

* Re: git pull opinion
From: Linus Torvalds @ 2007-11-10  0:36 UTC (permalink / raw)
  To: Aghiles; +Cc: Bill Lear, Junio C Hamano, git
In-Reply-To: <3abd05a90711071325y397434efq7d4e50cb7a1cf07e@mail.gmail.com>



On Wed, 7 Nov 2007, Aghiles wrote:

> > [...]
> > Now, I do think that we could relax the rule so that "files that are
> > modified must be clean in the working tree" could instead become "files
> > that actually don't merge _trivially_ must be clean in the working tree".
> > But basically, if it's not a trivial merge, then since it's done in the
> > working tree, the working tree has to be clean (or the merge would
> > overwrite it).
> >[...]
> 
> I really think this is a good idea. It seems to me that the first "bad"
> surprise a svn/cvs/bk user will have is the result of a "git pull" command
> on a dirty tree. With the proposed change, and if I understand correctly:
>   - users that are used to commit often and fetch into clean trees
> will never be bothered by this change.
>   - users that are used to "update" often are expecting to resolve
> conflicts in their working copy anyway.
> 
> In both cases git does not get in your way and everyone is happy.

Well, there will still be cases where people won't be happy.

That said, all fast-forward cases (which is, I guess, a fairly common way 
of operating for anybody who has ever just uses anoncvs to track others) 
would be handled by the "three-way-merge dirty data for trivial merges". 

So even if it would only handle that special case (and it handles a *lot* 
of other cases too!) it probably would be useful to some people.

That said, I still don't think I have the energy to actually try to do it. 
I do suspect it's not that hard, and I outlined where it would go, but 
it's really quite core and important code... IOW, this needs *lots* of 
deep thought and care.

			Linus

^ 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