Git development
 help / color / mirror / Atom feed
* Re: [PATCH] Make sure an autogenerated version has at least four parts
From: Sam Vilain @ 2007-05-25  1:33 UTC (permalink / raw)
  To: Martin Waitz; +Cc: Sam Vilain, Junio C Hamano, git
In-Reply-To: <20070521073650.GV5412@admingilde.org>

Martin Waitz wrote:
> hoi :)
> 
> On Mon, May 21, 2007 at 02:52:21PM +1200, Sam Vilain wrote:
>> Otherwise, a custom "v1.5.2.42.gd00b" is considered newer than a
>> "v1.5.2.1.69.gcafe".
> 
> or just use git describe output without replacing "-" with "."?
> 

dpkg uses "-" in version numbers for its own uses - to delimit the
packager's packaging version from the software version.  The change I
posted keeps original behaviour - just fills out the .0's.

Perhaps the munging should go in git-describe instead?

Subject: [PATCH] describe: add --levels option

Some projects might want git describe to always give a result that
has a given number of version levels.  ie, if you say --levels=4
and describe finds a name like 'v1.5.2', the result will be 'v1.5.2.0'.

This does mean that on exact tag matches, the returned version
is not a resolvable ref - but that is probably caveat emptor.

Signed-off-by: Sam Vilain <sam@vilain.net>
---
 builtin-describe.c  |   50 ++++++++++++++++++++++++++++++++++++++++++++++----
 t/t6120-describe.sh |    8 ++++++++
 2 files changed, 54 insertions(+), 4 deletions(-)

diff --git a/builtin-describe.c b/builtin-describe.c
index 165917e..05eabc5 100644
--- a/builtin-describe.c
+++ b/builtin-describe.c
@@ -15,6 +15,7 @@ static int all;	/* Default to annotated tags only */
 static int tags;	/* But allow any tags if --tags is specified */
 static int abbrev = DEFAULT_ABBREV;
 static int max_candidates = 10;
+static int num_levels = 0;
 
 struct commit_name {
 	int prio; /* annotated tag = 2, tag = 1, head = 0 */
@@ -134,6 +135,7 @@ static void describe(const char *arg, int last_one)
 	struct possible_tag all_matches[MAX_TAGS];
 	unsigned int match_cnt = 0, annotated_cnt = 0, cur_match;
 	unsigned long seen_commits = 0;
+	char* chosen;
 
 	if (get_sha1(arg, sha1))
 		die("Not a valid object name %s", arg);
@@ -148,8 +150,9 @@ static void describe(const char *arg, int last_one)
 
 	n = cmit->util;
 	if (n) {
-		printf("%s\n", n->path);
-		return;
+		chosen = n->path;
+		abbrev = 0;
+		goto show;
 	}
 
 	if (debug)
@@ -228,10 +231,44 @@ static void describe(const char *arg, int last_one)
 				sha1_to_hex(gave_up_on->object.sha1));
 		}
 	}
+
+	chosen = all_matches[0].name->path;
+
+	/* make the described version have the desired number of
+	 * levels in it */
+ show:
+	if (num_levels) {
+		int found = 1;
+		char* idx = chosen;
+		int i;
+		while ((idx = index(idx, '.'))) {
+			found++;
+			idx++;
+		}
+		if (found > num_levels) {
+			idx = chosen;
+			for (i = 0; i < num_levels; i++) {
+				if (i)
+					idx++;
+				idx = index(idx, '.');
+			}
+			*idx = '\0';
+		}
+		else if (found < num_levels) {
+			int extra = 2 * (num_levels - found);
+			char* new = xmalloc(strlen(chosen) + extra + 1);
+			chosen = strcpy(new, chosen);
+			while (found < num_levels) {
+				strcat(chosen, ".0");
+				found++;
+			}
+		}
+	}
+
 	if (abbrev == 0)
-		printf("%s\n", all_matches[0].name->path );
+		printf("%s\n", chosen);
 	else
-		printf("%s-%d-g%s\n", all_matches[0].name->path,
+		printf("%s-%d-g%s\n", chosen,
 		       all_matches[0].depth,
 		       find_unique_abbrev(cmit->object.sha1, abbrev));
 
@@ -266,6 +303,11 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 			else if (max_candidates > MAX_TAGS)
 				max_candidates = MAX_TAGS;
 		}
+		else if (!prefixcmp(arg, "--levels=")) {
+			num_levels = strtoul(arg + 9, NULL, 10);
+			if (num_levels < 0) 
+				num_levels = 0;
+		}
 		else
 			usage(describe_usage);
 	}
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index 3e9edda..0336ddd 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -33,6 +33,7 @@ test_expect_success setup '
 
 	test_tick &&
 	echo two >file && git-add file && git-commit -m second &&
+	git-tag -a -m v1.1 v1.1 &&
 	two=$(git-rev-parse HEAD) &&
 
 	test_tick &&
@@ -94,4 +95,11 @@ check_describe D-* --tags HEAD^^
 check_describe A-* --tags HEAD^^2
 check_describe B --tags HEAD^^2^
 
+check_describe A.0-* --tags --levels=2 HEAD
+check_describe A.0.0-* --tags --levels=3 HEAD
+check_describe v1 --tags --levels=1 v1.1
+check_describe v1.1 --tags --levels=2 v1.1
+check_describe v1.1.0 --tags --levels=3 v1.1
+check_describe v1-* --tags --levels=1 A^1
+
 test_done
-- 
1.5.2.0.45.gfea6d-dirty

^ permalink raw reply related

* Re: Pulling from refs/remotes/ ?
From: Junio C Hamano @ 2007-05-25  1:53 UTC (permalink / raw)
  To: hanwen; +Cc: git
In-Reply-To: <46563D55.3070607@xs4all.nl>

Han-Wen Nienhuys <hanwen@xs4all.nl> writes:

> Yes, that works, thanks. Wouldn't it be more consistent with this
> reasoning to disallow 
>
>   git pull . LOCAL-BRANCH 
>
> too?

I do not think so.

If somebody else (or yourself) did:

	$ git pull $dir LOCAL-BRANCH

(replace $dir with the `pwd` you would get in your repository),
that would work.  Why shouldn't it work for yourself?

^ permalink raw reply

* Re: Make "git gc" pack all refs by default
From: Junio C Hamano @ 2007-05-25  2:04 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Git Mailing List
In-Reply-To: <alpine.LFD.0.98.0705241132400.26602@woody.linux-foundation.org>

Linus Torvalds <torvalds@linux-foundation.org> writes:

> Also, make the default for refs packing just be an unambiguous "do it", 
> rather than "do it by default only for non-bare repositories". If you want 
> that behaviour, you can always just add a
>
> 	[gc]
> 		packrefs = notbare
>
> in your ~/.gitconfig file, but I don't actually see why bare would be any 
> different (except for the broken reason that http-fetching used to be 
> totally broken, and not doing it just meant that it didn't even get 
> fixed in a timely manner!).

Boy, you are a lot more aggressive than me.

But the fix was in v1.5.0 and we had two feature releases since
then, so it's a good time to do this.  Thanks.

^ permalink raw reply

* [PATCH] Ensure git-repack -a -d --max-pack-size=N deletes correct packs
From: Dana How @ 2007-05-25  2:06 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List, danahow


The packfile portion of the "remove redundant" code
near the bottom of git-repack.sh is broken when
pack splitting occurs.  Particularly since this is
the only place where we automatically delete packfiles,
make sure it works properly for all cases,  old or new.

This is based on "next".

Signed-off-by: Dana L. How <danahow@gmail.com>
---
 git-repack.sh |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/git-repack.sh b/git-repack.sh
index 4ea6e5b..0591bd7 100755
--- a/git-repack.sh
+++ b/git-repack.sh
@@ -69,6 +69,7 @@ if [ -z "$names" ]; then
 	echo Nothing new to pack.
 fi
 for name in $names ; do
+	fullbases="$fullbases pack-$name"
 	chmod a-w "$PACKTMP-$name.pack"
 	chmod a-w "$PACKTMP-$name.idx"
 	if test "$quiet" != '-q'; then
@@ -105,8 +106,8 @@ then
 		( cd "$PACKDIR" &&
 		  for e in $existing
 		  do
-			case "$e" in
-			pack-$name) ;;
+			case " $fullbases " in
+			*\ $e\ *) ;;
 			*)	rm -f "$e.pack" "$e.idx" "$e.keep" ;;
 			esac
 		  done
-- 
1.5.2.762.gd8c6-dirty

^ permalink raw reply related

* Re: [PATCH] Prevent megablobs from gunking up git packs
From: Shawn O. Pearce @ 2007-05-25  2:06 UTC (permalink / raw)
  To: Dana How; +Cc: Junio C Hamano, Git Mailing List
In-Reply-To: <56b7f5510705241629n192a41adi4c0d63c53cf8472b@mail.gmail.com>

Dana How <danahow@gmail.com> wrote:
> On 5/24/07, Shawn O. Pearce <spearce@spearce.org> wrote:
> >Junio C Hamano <junkio@cox.net> wrote:
> >> "Dana How" <danahow@gmail.com> writes:
> >> > We have three options in this case:
> >> > (1) Drop the object (do not put it in the new pack(s)).
> >> > (2) Pass the object into the new pack(s).
> >> > (3) Write out the object as a new loose object.
> >> > Option (1) is unacceptable.  When you call git-repack -a,
> >> > it blindly deletes all the non-kept packs at the end.  So
> >> > the megablobs would be lost.
> >> Ok, I can buy that -- (1) nor (2) are unacceptable and (3) is
> >> the only sane thing to do for a previously packed objects that
> >> exceed the size limit.
> >
> >I still don't buy the idea that these megablobs shouldn't be packed.
> >I understand Dana's pain here (at least a little bit, my problems
> >aren't as bad as his are), but I also hate to see us run away from
> >packfiles for these really sick cases just because we have some
> >issues in our current packfile handling.
> >
> >Packfiles give us a lot of benefits:
> >
> > 1) less inode usage;
> I agree with Geert that blowing an inode on a 100MB+ object
> is no big deal.

You and me both.  If the size of the blob is high enough than
overhead associated with the inode and any tail-block wastage is
noise.  Filesystems are pretty good at tracking large-ish files.
My comment here wasn't so much about blowing an inode on a 100MiB+
object, but just in general that packfiles reduce inode usage,
which in the common metadata case (300,000 small objects) is a
big difference.

I think you are right; if we get an object in the >100MiB size
range we can certainly afford an inode for it.

> > 2) transport can write directly to local disk;
> > 3) transport can (quickly) copy from local disk;
> For (2) and (3) see comments on next para plus NFS discussion.
> > 4) testing for existance is *much* faster;
> This is true.  But I don't care about this cost if it
> is only incurred on large objects which are leaf nodes
> in the git "data relationship tree" (tags->commits->trees->blobs) anyway.

Yes, that's true.

> > 5) deltafication is possible;
> Again Geert made a good argument that didn't occur to me that
> you definitely DON'T want to do deltification on such large objects.
> Junio recently added delta/nodelta attribute; this would be useful
> to me,  but unfortunately I have several continua of files,  each with
> the same suffix,  but with largely varying sizes, so attributes won't
> help me unless the name globs in .gitattributes are expanded to full
> expressions similar to find(1) [i.e. include testing based on size,
> perms, type],  which I think would be insane.

Which brings up the comment I think I made (below) about skipping
deltas on very large objects.  Things over a certain size are not
likely to delta well, or in any reasonable time.  We probably should
default to not trying to delta those, but let the user force us to
do so with a .gitattributes option.  Maybe.

> >By pushing the megablob packs to the end of our packed_git search
> >list we won't tend to scan their indexes, as most of our objects
> >will be found earlier in the search list.  Hence we will generally
> >avoid any costs associated with their indexes.
> Good argument and I submitted a patch to do this.
> Let's see who chokes on the floating arithmetic ;-)

I actually had another thought in this area.  I'll try to work up a
patch to accompany yours.  I think we can avoid even touching the
alternate object databases half of the time, and I'd like to be
able to do that.  Why?  Because I started to setup this megablob
approach on my own Windows based repositories.  Unfortunately it
makes git-log about 1 second slower, and I suspect its in the
alternate repository initialization.
 
> >Huge packfiles probably should be scheduled for keeping with a .keep
> >automatically.  We probably should teach pack-objects to generate a
> >.keep file if the resulting .pack was over a certain size threshold
> >(say 1.5 GiB by default) and teach git-repack to rename the .keep
> >file as it also renames the .idx and .pack.
> I have experimented with this,  and Jakub Narebski made related
> suggestions.  I find this quite hokey,  but even if I do it in my central
> alternate,  I still do not want to be packing megablobs in individual user's
> repos EVER,  and need some way to exclude them.

Yes, that makes a lot of sense.

> >Better that we degrade gracefully when faced with massive inputs
> >than we do something stupid by default and make the poor user pay
> >for their mistake of not throughly reading plumbing documentation
> >before use.
> Unnecessary copying of several GB is not degrading gracefully in my view.
> In fact having repack.maxblobsize = 2000 (K) in the default "config"
> strikes me as degrading much more gracefully than what the code
> would currently do.

Sure.  But I think this goes back to #3 (network transport) and
how our loose object format now doesn't support it well.  And even
if that's fixed I don't think 2 MiB is a good default; its *far*
too low.  I have a number of blobs that are in the 12-16 MiB range
and they delta very well in a pretty reasonable time.

> This silly patch took my packfile sets from 12GB+ to 13MB,
> and it's difficult to describe how relieved I now feel.

I think I understand a little bit.  Today I took 3 repositories
that were about 70 MiB each and dropped them down to 16 MiB, 2
MiB and 4.5 MiB by creating a single 120 MiB "megablob" packfile
that spanned all 3 of them.  This isn't the same scale as what you
are dealing with, but now I have a current metadata pack for each
that isn't gummed up with large blobs, making repacking faster.
I also have a smaller working set size.  :-

> But I think you have an understandable motivation:
> you want packfiles to be as good as possible,  and any escape
> mechanism from them decreases the motivation to "fix" packing.

Yes, that's correct.  I'm not against stepping outside of
packfiles and making usage of loose objects for megablobs easier.
I just want to make sure its the best way to handle these things.
Generally we've made major improvements in things when we've been
pushed by large repositories/datasets.

> Now I agree with this, which is why I just submitted some other patches,
> but I don't share your goal of the universality of all packfiles --
> just the ones used for transport.  Don't your packv4 plans introduce
> mods which won't be used for transport as well?

Yes, at least initially we'd reencode from pack v4 down to pack v2
for transport, because transporting the dictionary with delta reuse
is an interesting problem.  However Nico and I have discussed it
at length and have plans for how to code a pack v4 based transport,
and pack v4's file format concepts are partially based upon making
pack v4 transport easier to implement.  But from a "start simple and
keep it simple, stupid" principle we'd like to avoid the complexity
early on.

> >Now I would agree that we should punt on deltification of anything
> >that is just too large, and let the user decide what too large means,
> >and default it around 500 or 1024 MiB.  But I would still stuff it
> >into a packfile.
> >
> >Maybe it still makes sense to have a limit on the maximum size of a
> >loose object to pack, but I think that's only to avoid the sick case
> >of a very simple no-argument "git repack" taking a long while because
> >there's 8 loose objects and 6 of them are 900 MiB image files.
> Perhaps we _will_ make progress if we all agree to describe
> my situation as "sick" ;-) .  In this paragraph you seem to agree that
> there is some argument for keeping megablobs from _entering_ packs?

Yes.  If your workflow is basically "git add HUGE; git commit; git push;
git prune-alternates" then you only have to pack the huge object once,
and can remove the loose object from the user's .git/objects directly
pretty quickly, because its available via your NFS alternate.  In such
a configuration yes, it does make some sense to never allow a megablob
from entering a pack.

So I guess I'm partially in agreement with you...

> >Once in a packfile, I'd keep it there, even if the user decreases
> >the threshold, as the advantages of it being in the packfile outweigh
> >the disadvantages of it being in the packfile.  And there's like no
> >advantage to being loose once packed.
> To (almost) follow this suggestion I would need git-fast-import to respect
> repack.maxblobsize as well.  Is that OK with you?

Yes I could implement that (or better accept a patch that does so)
but I'd actually wonder why not just categorize the objects into
two different packfiles.  Have one for "small stuff" and another
for "everything larger than small stuff".  Split the two packfiles
independently of each other.  Hence fast-import would produce more
packfiles, but each output packfile would probably have a couple
of megablobs in it, and you'd have one single packfile with all of
the smaller metadata.

And actually if you are trying to shove large objects through
fast-import we really can do a lot better.  Like avoiding
deltification attempts, adjusting the compression level to something
better suited to your blob (I don't know if its compressable or not)
and streaming to the output packfile, rather than holding the entire
thing in memory before writing the first byte.

Given the advantages discussed above about being in a packfile, and
that fast-import was writing specifically for creating packfiles
instead of loose objects during large IO transfers into Git, I
think it is sort of anti-fast-import to have it create loose objects.
 
> I previously offered to Junio that the "write loose object" thing
> could be restricted:  it would only happen if -f were supplied to
> git-repack,  otherwise the bad blob would pass through to the new pack.
> Does this "reduction in strength" make this feature more palatable to you?

Yes.  But go back to the .keep discussion above where I suggest
we automatically .keep any "large" packfile.  Once you get a huge
packfile you probably don't want to redo the disk IO associated with
repacking it, unless you really are trying to force a large reorg.
So I'd agree with the idea of making a -f needed to eject a megablob,
but I think you'd need more than that as you'd also be trying to
bypass the usual .keep logic.
 
> If the stats on a repo change significantly,  "write loose object"
> becomes more important if you have to make a significant reduction
> to repack.maxblobsize (or specify it for the first time).

I'm not sure users should be tweaking this...  Its fine to make
the knob available, but we really should have the knob adjust
itself somewhat intelligently.  Don't ever add a knob that you
cannot write a rule to control; if you can write a rule than write
it dammit and don't make the user do your job for you.  Knobs are
good for when your case is just so far away from the normal that
the rule is utterly wrong...

Guess what, your repository is such a repository (its far away from
our normal rules).  But I think its problems are also common enough
that we really should attempt to make our rules handle it better.
 
> I don't agree that once in a packfile,  a blob should stay there.
> Its presence is degrading access to "normal" blobs co-habiting with it.
> So you will want to repack to separate them in different packs
> (the various .keep-related ideas) or just write them out loose.

If we're evicting a megablob from one packfile to a loose object
(because its degrading access to the other objects in its current
packfile) we're already committed to doing the massive disk IO
required for that eviction.  We might as well write it back out
to a file format that we can more easily work with, than one that
we cannot.

But I have to circle back here and say "why is a megablob degrading
access in a packfile"?  This goes right back to your point above
about my wanting to stay in the packfile format just to make the
packfile format better.  What's so wrong with the packfile format
(and the code that writes/reads it) that makes access for a small
metadata more expensive when there are megablobs attached in the
same packfile?

Or is it just because we like to repack the smaller metadata
frequently, but that's horribly expensive because the megablobs
are in the same packfile?  If its really just about repacking then
.keep marked megablob packs are the way to go.

-- 
Shawn.

^ permalink raw reply

* Re: [PATCH] fix memory leak in parse_object when check_sha1_signature fails
From: Shawn O. Pearce @ 2007-05-25  2:09 UTC (permalink / raw)
  To: Carlos Rica; +Cc: git, Junio C Hamano
In-Reply-To: <1b46aba20705241846u615785eeh7c3ebeaf840b2180@mail.gmail.com>

Carlos Rica <jasampler@gmail.com> wrote:
> When check_sha1_signature fails, program is not terminated:
> it prints an error message and returns NULL, so the
> buffer returned by read_sha1_file should be freed before.
...
> 		if (check_sha1_signature(sha1, buffer, size, typename(type)) 
> 		< 0) {
...

gmail strikes again.  The above line is wrapped, which means your
patch is whitespace damaged and won't apply properly.

-- 
Shawn.

^ permalink raw reply

* Re: git-svn and SVK mirror between two repositories
From: Sam Vilain @ 2007-05-25  2:13 UTC (permalink / raw)
  To: Vinubalaji Gopal; +Cc: git
In-Reply-To: <7d8fb81e0705241004u1c52fa7aub42d3793d4bfeaa7@mail.gmail.com>

Vinubalaji,

You should be able to track both of the svn repositories as different
git-svn remotes.  You can then move patches between them with
git-format-patch and git-apply (or git-cherry-pick).

git-merge-base calculations won't work when operating like this - so
git-merge won't work - however the simple merge base token used by SVK
to track this would be easy to implement using git-tag and
git-update-ref, so you could get yourself something as useful as svk
smerge (which is really just mass cherry picking, using a token to
remember what it last picked).

A better implementation would be to allow git-svn to spot that the
repositories are tracking the same history and make sure they end up
with the same commits, then git-merge could work.

However, you are in a relatively obscure use case, most projects
wouldn't do this.  Note also that the merge tickets SVK would use are
not portable between different SVK mirrors so the merge information is
not retrievable for anyone other than the person who did the merge.  Use
"svn pg svk:merge svn://svn.paris.fr/" if you don't believe me... the
UUID and revision numbers in the property will not refer to revisions in
svn://svn.paris.fr/ but to the (private) SVN repository in the SVK depot.

Sam.


Vinubalaji Gopal wrote:
> Hi all,
>     I have been trying hard to find if it is possible to mirror (or
> clone in git-svn terms) two svn repositories and update changes from
> one to other or do even more complex operations with these two
> repositories. I did check the git-svn man page, but was lost without a
> proper example. Can someone please provide me with an example of using
> two svn repositories in git-svn and doing merge operations, etc .
> 
> I have used SVK for a long time and it was very much possible to use
> two svn repositories using the SVK FAQ entry as shown below:
> 
> Repository ONE in Paris, repository TWO in London and be able to
> create 2 mirrors then smerge both, doing it on a node in Berlin and
> using the mirror function?
> Sure. Simply do this:
> 
> svk mirror svn://svn.paris.fr/ //paris
> svk mirror svn://svn.london.uk/ //london
> 
> # pick a sensible base, or use --baseless
> svk smerge --base=1234 //paris //london
> 
> # ... and smerge between them normally ...
> svk smerge -I //london //paris
> svk smerge -I //paris //london
> 
> 
> 

^ permalink raw reply

* Re: Make "git gc" pack all refs by default
From: Linus Torvalds @ 2007-05-25  2:20 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <7vy7jdu08k.fsf@assigned-by-dhcp.cox.net>



On Thu, 24 May 2007, Junio C Hamano wrote:
> 
> Boy, you are a lot more aggressive than me.

Heh. 

I don't like the http interfaces, so I have a much easier time saying 
"they were broken, deal with it" ;)

I also think that we mis-calculated earlier in assuming that prople don't 
have lots of branches, and that packing branches was thus much less 
important than packing tags.

It's true that in sane git-only environment, you don't have lots of 
branches (fifty isn't "lots"). But when importing things from other 
environments, I seem to recall people talking about thousands of branches 
(since they cannot be merged and they are project-wide rather than some 
local entity, they cannot disappear).

So I think it's better to just pack branches aggressively too, and in 
fact, once you do that, and http-fetch knows about it, then that also 
means that info/refs becomes pointless, because afaik, it doesn't actually 
contain anything more than what a modern "packed-refs" file contains.

So in order to take that _next_ step, we need to encourage people to pack 
branches, and then at some point we can hopefully just make http-fetch 
start ignoring info/refs..

So yeah, I think being aggressive here is a good idea. I really also 
wanted to make update-server-info do the pack-refs thing, but to do it 
properly we'd need to make the whole pack-refs thing have a nice library 
interface, so it was a much bigger (although probably fairly 
straightforward) thing.

		Linus

^ permalink raw reply

* Re: Pulling from refs/remotes/ ?
From: Han-Wen Nienhuys @ 2007-05-25  2:24 UTC (permalink / raw)
  To: git; +Cc: git
In-Reply-To: <7v3b1lvfc5.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano escreveu:
> Han-Wen Nienhuys <hanwen@xs4all.nl> writes:
> 
>> Yes, that works, thanks. Wouldn't it be more consistent with this
>> reasoning to disallow 
>>
>>   git pull . LOCAL-BRANCH 
>>
>> too?
> 
> I do not think so.
> 
> If somebody else (or yourself) did:
> 
> 	$ git pull $dir LOCAL-BRANCH
> 
> (replace $dir with the `pwd` you would get in your repository),
> that would work.  Why shouldn't it work for yourself?
 
Because

"You are treating your local repository as if it is a remote
repository somewhere else, namely, '.' (current repository)."

that was the justification for not being able to pull in a remote
branch.  This justification (which I disagree with) applies to this
case as well.

I understand that we don't want people committing to
remotes, because fetches will then later fail, but other than 
that, why should there be limitations on using a remote?

-- 
 Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen

^ permalink raw reply

* [PATCH] Remove git-applypatch
From: Junio C Hamano @ 2007-05-25  2:33 UTC (permalink / raw)
  To: git; +Cc: Petr Baudis
In-Reply-To: <7vejl719vf.fsf@assigned-by-dhcp.cox.net>

The previous one removed git-applymbox, which was the sole user
of this tool.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---
 .gitignore                       |    1 -
 Documentation/SubmittingPatches  |    4 +-
 Documentation/cmd-list.perl      |    1 -
 Documentation/git-am.txt         |    2 +-
 Documentation/git-applypatch.txt |   53 ----------
 Documentation/git-mailinfo.txt   |    2 +-
 Documentation/hooks.txt          |   13 +--
 Makefile                         |    2 +-
 git-applypatch.sh                |  212 --------------------------------------
 9 files changed, 10 insertions(+), 280 deletions(-)
 delete mode 100644 Documentation/git-applypatch.txt
 delete mode 100755 git-applypatch.sh

diff --git a/.gitignore b/.gitignore
index 76c0e1b..b4e72f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,7 +7,6 @@ git-add--interactive
 git-am
 git-annotate
 git-apply
-git-applypatch
 git-archimport
 git-archive
 git-bisect
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index b94d9a8..b5f2ecd 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -239,7 +239,7 @@ One test you could do yourself if your MUA is set up correctly is:
     $ git fetch http://kernel.org/pub/scm/git/git.git master:test-apply
     $ git checkout test-apply
     $ git reset --hard
-    $ git applymbox a.patch
+    $ git am a.patch
 
 If it does not apply correctly, there can be various reasons.
 
@@ -247,7 +247,7 @@ If it does not apply correctly, there can be various reasons.
   does not have much to do with your MUA.  Please rebase the
   patch appropriately.
 
-* Your MUA corrupted your patch; applymbox would complain that
+* Your MUA corrupted your patch; "am" would complain that
   the patch does not apply.  Look at .dotest/ subdirectory and
   see what 'patch' file contains and check for the common
   corruption patterns mentioned above.
diff --git a/Documentation/cmd-list.perl b/Documentation/cmd-list.perl
index 0bca346..645e437 100755
--- a/Documentation/cmd-list.perl
+++ b/Documentation/cmd-list.perl
@@ -72,7 +72,6 @@ __DATA__
 git-add                                 mainporcelain
 git-am                                  mainporcelain
 git-annotate                            ancillaryinterrogators
-git-applypatch                          purehelpers
 git-apply                               plumbingmanipulators
 git-archimport                          foreignscminterface
 git-archive                             mainporcelain
diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 049e46f..7658fbd 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -145,7 +145,7 @@ names.
 
 SEE ALSO
 --------
-gitlink:git-applypatch[1], gitlink:git-apply[1].
+gitlink:git-apply[1].
 
 
 Author
diff --git a/Documentation/git-applypatch.txt b/Documentation/git-applypatch.txt
deleted file mode 100644
index 451434a..0000000
--- a/Documentation/git-applypatch.txt
+++ /dev/null
@@ -1,53 +0,0 @@
-git-applypatch(1)
-=================
-
-NAME
-----
-git-applypatch - Apply one patch extracted from an e-mail
-
-
-SYNOPSIS
---------
-'git-applypatch' <msg> <patch> <info> [<signoff>]
-
-DESCRIPTION
------------
-This is usually not what an end user wants to run directly.  See
-gitlink:git-am[1] instead.
-
-Takes three files <msg>, <patch>, and <info> prepared from an
-e-mail message by 'git-mailinfo', and creates a commit.  It is
-usually not necessary to use this command directly.
-
-This command can run `applypatch-msg`, `pre-applypatch`, and
-`post-applypatch` hooks.  See link:hooks.html[hooks] for more
-information.
-
-
-OPTIONS
--------
-<msg>::
-	Commit log message (sans the first line, which comes
-	from e-mail Subject stored in <info>).
-
-<patch>::
-	The patch to apply.
-
-<info>::
-	Author and subject information extracted from e-mail,
-	used on "author" line and as the first line of the
-	commit log message.
-
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
-GIT
----
-Part of the gitlink:git[7] suite
-
diff --git a/Documentation/git-mailinfo.txt b/Documentation/git-mailinfo.txt
index 8eadceb..1695695 100644
--- a/Documentation/git-mailinfo.txt
+++ b/Documentation/git-mailinfo.txt
@@ -16,7 +16,7 @@ DESCRIPTION
 Reading a single e-mail message from the standard input, and
 writes the commit log message in <msg> file, and the patches in
 <patch> file.  The author name, e-mail and e-mail subject are
-written out to the standard output to be used by git-applypatch
+written out to the standard output to be used by git-am
 to create a commit.  It is usually not necessary to use this
 command directly.  See gitlink:git-am[1] instead.
 
diff --git a/Documentation/hooks.txt b/Documentation/hooks.txt
index aad1744..6836477 100644
--- a/Documentation/hooks.txt
+++ b/Documentation/hooks.txt
@@ -12,11 +12,10 @@ This document describes the currently defined hooks.
 applypatch-msg
 --------------
 
-This hook is invoked by `git-applypatch` script, which is
-typically invoked by `git-am`.  It takes a single
+This hook is invoked by `git-am` script.  It takes a single
 parameter, the name of the file that holds the proposed commit
 log message.  Exiting with non-zero status causes
-`git-applypatch` to abort before applying the patch.
+`git-am` to abort before applying the patch.
 
 The hook is allowed to edit the message file in place, and can
 be used to normalize the message into some project standard
@@ -29,8 +28,7 @@ The default 'applypatch-msg' hook, when enabled, runs the
 pre-applypatch
 --------------
 
-This hook is invoked by `git-applypatch` script, which is
-typically invoked by `git-am`.  It takes no parameter,
+This hook is invoked by `git-am`.  It takes no parameter,
 and is invoked after the patch is applied, but before a commit
 is made.  Exiting with non-zero status causes the working tree
 after application of the patch not committed.
@@ -44,12 +42,11 @@ The default 'pre-applypatch' hook, when enabled, runs the
 post-applypatch
 ---------------
 
-This hook is invoked by `git-applypatch` script, which is
-typically invoked by `git-am`.  It takes no parameter,
+This hook is invoked by `git-am`.  It takes no parameter,
 and is invoked after the patch is applied and a commit is made.
 
 This hook is meant primarily for notification, and cannot affect
-the outcome of `git-applypatch`.
+the outcome of `git-am`.
 
 pre-commit
 ----------
diff --git a/Makefile b/Makefile
index 870179b..4e63a69 100644
--- a/Makefile
+++ b/Makefile
@@ -206,7 +206,7 @@ SCRIPT_SH = \
 	git-repack.sh git-request-pull.sh git-reset.sh \
 	git-sh-setup.sh \
 	git-tag.sh git-verify-tag.sh \
-	git-applypatch.sh git-am.sh \
+	git-am.sh \
 	git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
 	git-merge-resolve.sh git-merge-ours.sh \
 	git-lost-found.sh git-quiltimport.sh
diff --git a/git-applypatch.sh b/git-applypatch.sh
deleted file mode 100755
index 8df2aee..0000000
--- a/git-applypatch.sh
+++ /dev/null
@@ -1,212 +0,0 @@
-#!/bin/sh
-##
-## applypatch takes four file arguments, and uses those to
-## apply the unpacked patch (surprise surprise) that they
-## represent to the current tree.
-##
-## The arguments are:
-##	$1 - file with commit message
-##	$2 - file with the actual patch
-##	$3 - "info" file with Author, email and subject
-##	$4 - optional file containing signoff to add
-##
-
-USAGE='<msg> <patch> <info> [<signoff>]'
-. git-sh-setup
-
-case "$#" in 3|4) ;; *) usage ;; esac
-
-final=.dotest/final-commit
-##
-## If this file exists, we ask before applying
-##
-query_apply=.dotest/.query_apply
-
-## We do not munge the first line of the commit message too much
-## if this file exists.
-keep_subject=.dotest/.keep_subject
-
-## We do not attempt the 3-way merge fallback unless this file exists.
-fall_back_3way=.dotest/.3way
-
-MSGFILE=$1
-PATCHFILE=$2
-INFO=$3
-SIGNOFF=$4
-EDIT=${VISUAL:-${EDITOR:-vi}}
-
-export GIT_AUTHOR_NAME="$(sed -n '/^Author/ s/Author: //p' "$INFO")"
-export GIT_AUTHOR_EMAIL="$(sed -n '/^Email/ s/Email: //p' "$INFO")"
-export GIT_AUTHOR_DATE="$(sed -n '/^Date/ s/Date: //p' "$INFO")"
-export SUBJECT="$(sed -n '/^Subject/ s/Subject: //p' "$INFO")"
-
-if test '' != "$SIGNOFF"
-then
-	if test -f "$SIGNOFF"
-	then
-		SIGNOFF=`cat "$SIGNOFF"` || exit
-	elif case "$SIGNOFF" in yes | true | me | please) : ;; *) false ;; esac
-	then
-		SIGNOFF=`git-var GIT_COMMITTER_IDENT | sed -e '
-				s/>.*/>/
-				s/^/Signed-off-by: /'
-		`
-	else
-		SIGNOFF=
-	fi
-	if test '' != "$SIGNOFF"
-	then
-		LAST_SIGNED_OFF_BY=`
-			sed -ne '/^Signed-off-by: /p' "$MSGFILE" |
-			tail -n 1
-		`
-		test "$LAST_SIGNED_OFF_BY" = "$SIGNOFF" || {
-		    test '' = "$LAST_SIGNED_OFF_BY" && echo
-		    echo "$SIGNOFF"
-		} >>"$MSGFILE"
-	fi
-fi
-
-patch_header=
-test -f "$keep_subject" || patch_header='[PATCH] '
-
-{
-	echo "$patch_header$SUBJECT"
-	if test -s "$MSGFILE"
-	then
-		echo
-		cat "$MSGFILE"
-	fi
-} >"$final"
-
-interactive=yes
-test -f "$query_apply" || interactive=no
-
-while [ "$interactive" = yes ]; do
-	echo "Commit Body is:"
-	echo "--------------------------"
-	cat "$final"
-	echo "--------------------------"
-	printf "Apply? [y]es/[n]o/[e]dit/[a]ccept all "
-	read reply
-	case "$reply" in
-		y|Y) interactive=no;;
-		n|N) exit 2;;	# special value to tell dotest to keep going
-		e|E) "$EDIT" "$final";;
-		a|A) rm -f "$query_apply"
-		     interactive=no ;;
-	esac
-done
-
-if test -x "$GIT_DIR"/hooks/applypatch-msg
-then
-	"$GIT_DIR"/hooks/applypatch-msg "$final" || exit
-fi
-
-echo
-echo Applying "'$SUBJECT'"
-echo
-
-git-apply --index "$PATCHFILE" || {
-
-	# git-apply exits with status 1 when the patch does not apply,
-	# but it die()s with other failures, most notably upon corrupt
-	# patch.  In the latter case, there is no point to try applying
-	# it to another tree and do 3-way merge.
-	test $? = 1 || exit 1
-
-	test -f "$fall_back_3way" || exit 1
-
-	# Here if we know which revision the patch applies to,
-	# we create a temporary working tree and index, apply the
-	# patch, and attempt 3-way merge with the resulting tree.
-
-	O_OBJECT=`cd "$GIT_OBJECT_DIRECTORY" && pwd`
-	rm -fr .patch-merge-*
-
-	if git-apply -z --index-info "$PATCHFILE" \
-		>.patch-merge-index-info 2>/dev/null &&
-		GIT_INDEX_FILE=.patch-merge-tmp-index \
-		git-update-index -z --index-info <.patch-merge-index-info &&
-		GIT_INDEX_FILE=.patch-merge-tmp-index \
-		git-write-tree >.patch-merge-tmp-base &&
-		(
-			mkdir .patch-merge-tmp-dir &&
-			cd .patch-merge-tmp-dir &&
-			GIT_INDEX_FILE="../.patch-merge-tmp-index" \
-			GIT_OBJECT_DIRECTORY="$O_OBJECT" \
-			git-apply $binary --index
-		) <"$PATCHFILE"
-	then
-		echo Using index info to reconstruct a base tree...
-		mv .patch-merge-tmp-base .patch-merge-base
-		mv .patch-merge-tmp-index .patch-merge-index
-	else
-	(
-		N=10
-
-		# Otherwise, try nearby trees that can be used to apply the
-		# patch.
-		git-rev-list --max-count=$N HEAD
-
-		# or hoping the patch is against known tags...
-		git-ls-remote --tags .
-	) |
-	    while read base junk
-	    do
-		# Try it if we have it as a tree.
-		git-cat-file tree "$base" >/dev/null 2>&1 || continue
-
-		rm -fr .patch-merge-tmp-* &&
-		mkdir .patch-merge-tmp-dir || break
-		(
-			cd .patch-merge-tmp-dir &&
-			GIT_INDEX_FILE=../.patch-merge-tmp-index &&
-			GIT_OBJECT_DIRECTORY="$O_OBJECT" &&
-			export GIT_INDEX_FILE GIT_OBJECT_DIRECTORY &&
-			git-read-tree "$base" &&
-			git-apply --index &&
-			mv ../.patch-merge-tmp-index ../.patch-merge-index &&
-			echo "$base" >../.patch-merge-base
-		) <"$PATCHFILE"  2>/dev/null && break
-	    done
-	fi
-
-	test -f .patch-merge-index &&
-	his_tree=$(GIT_INDEX_FILE=.patch-merge-index git-write-tree) &&
-	orig_tree=$(cat .patch-merge-base) &&
-	rm -fr .patch-merge-* || exit 1
-
-	echo Falling back to patching base and 3-way merge using $orig_tree...
-
-	# This is not so wrong.  Depending on which base we picked,
-	# orig_tree may be wildly different from ours, but his_tree
-	# has the same set of wildly different changes in parts the
-	# patch did not touch, so resolve ends up canceling them,
-	# saying that we reverted all those changes.
-
-	if git-merge-resolve $orig_tree -- HEAD $his_tree
-	then
-		echo Done.
-	else
-		echo Failed to merge in the changes.
-		exit 1
-	fi
-}
-
-if test -x "$GIT_DIR"/hooks/pre-applypatch
-then
-	"$GIT_DIR"/hooks/pre-applypatch || exit
-fi
-
-tree=$(git-write-tree) || exit 1
-echo Wrote tree $tree
-parent=$(git-rev-parse --verify HEAD) &&
-commit=$(git-commit-tree $tree -p $parent <"$final") || exit 1
-echo Committed: $commit
-git-update-ref -m "applypatch: $SUBJECT" HEAD $commit $parent || exit
-
-if test -x "$GIT_DIR"/hooks/post-applypatch
-then
-	"$GIT_DIR"/hooks/post-applypatch
-fi
-- 
1.5.2.70.g17b3ac

^ permalink raw reply related

* Re: [PATCH] Split packs from git-repack should have descending timestamps
From: Dana How @ 2007-05-25  2:33 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Shawn O. Pearce, Git Mailing List, danahow
In-Reply-To: <7vbqg9vhlf.fsf@assigned-by-dhcp.cox.net>

On 5/24/07, Junio C Hamano <junkio@cox.net> wrote:
> "Shawn O. Pearce" <spearce@spearce.org> writes:
> > Dana How <danahow@gmail.com> wrote:
> >>
> >> If git-repack produces multiple split packs because
> >> --max-pack-size was in effect,  the first pack written
> >> should have the latest timestamp because:
> >> (1) sha1_file.c:rearrange_packed_git() puts more recent
> >>     pack files at the beginning of the search list;  and
> >> (2) the most recent objects are written out first
> >>     while packing.
> >
> > Ack.  Given our mtime based sorting routine, even without your
> > recent patch to improve it, I think we definately want this type
> > of behavior built into git-repack.sh.  Good follow-on to your
> > --max-pack-size series.
>
> Gee, I do not want to touch this, unless we can do something
> about that sleep 2, even if you have & at the end (actually,
> especially because you have that -- it makes me worried).
>
> At the minimum, I think you do not have to restamp at all if the
> result is a single pack (i.e. the usual case), like so:
>
> case "$restamp" in
> ?*' '?*)
>         # we have more than one.
>         # for split packs,  the first created should have most recent timestamp
>         for file in $restamp ; do touch $file; sleep 2; done &
>         ;;
> esac
>
> Come to think of it, can't you do this "re-touching" business at
> the end of pack-objects without sleeping?  You could keep track
> of the names of the packs you produced, and if you have produced
> 5, like so:
>
>         1
>         2
>         3
>         4
>         5
>
> you would swap timestamp of #1 and #5, #2 and #4 using stat()
> and utime(), and you are done.  Each of these huge packs would
> take more than one second to write it out, but if that is not
> the case, you could even start with timestamp of #5, subtract 1
> and stamp #4, subtract 1 and stamp #3, ... You may end up using
> timestamp from the past, but that would not be a problem.
OK,  this triggered the following argument which convinces me:
git-pack-objects really should guarantee the correct timestamp
order,  otherwise some other caller will have to repeat the stuff
I tried to put in git-repack.sh .  So I will resubmit following Junio's
suggestions.  This won't be for a few days.

Also,  if there are rules on allowable bash constructs
(POSIX only, no &, etc),  perhaps they should go in
SubmittingPatches near the new C99 comments?

> And I am really hoping that the other "use object density in
> reordering" patch would make this irrelevant.  You would have
> commit and then the rest in the normal input object stream, and
> recenty ordering done by git-pack-objects should keep commits
> together early in the resulting split pack, and earlier parts
> that have the commits would be hopefully denser.
I understand your point,  but for a "normal" yet extremely
large repository this may not be the case.  The "object density"
patch is designed so that the density component of the sort
key is extremely weak -- I think the timestamp is very revealing,
and should be followed in the absence of large variations
in object density.  Correcting the timestamps makes sure
that the timestamp order corresponds sensibly to recency order
when packs are split.  A sequence of user commands producing
packfiles results in sensible and usable timestamps;
i"d just like to make sure this is also true when packs are
split.

Anyway,  I'm not going to submit anything more about
timestamps or object density until I see reactions to both patches,
since they interact.
-- 
Dana L. How  danahow@gmail.com  +1 650 804 5991 cell

^ permalink raw reply

* Re: [PATCH] Add option to cvs update before export
From: Junio C Hamano @ 2007-05-25  2:34 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git
In-Reply-To: <20070524150655.15030.13626.stgit@lathund.dewire.com>

Looks good; will queue for 'next'.

^ permalink raw reply

* Re: [PATCH] fix memory leak in parse_object when check_sha1_signature fails
From: Junio C Hamano @ 2007-05-25  2:38 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Carlos Rica, git
In-Reply-To: <20070525020939.GT28023@spearce.org>

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

> Carlos Rica <jasampler@gmail.com> wrote:
>> When check_sha1_signature fails, program is not terminated:
>> it prints an error message and returns NULL, so the
>> buffer returned by read_sha1_file should be freed before.
> ...
>> 		if (check_sha1_signature(sha1, buffer, size, typename(type)) 
>> 		< 0) {
> ...
>
> gmail strikes again.  The above line is wrapped, which means your
> patch is whitespace damaged and won't apply properly.

That is only between your eyes, imagination and your MUA (hint:
"format: flowed").

For applying after saving it in mbox it does not pose a problem,
but it _does_ affect people who want to comment on the patch
while in MUA.

Is there a way to turn that "format: flawed" off?

^ permalink raw reply

* Re: Pulling from refs/remotes/ ?
From: Junio C Hamano @ 2007-05-25  3:06 UTC (permalink / raw)
  To: hanwen; +Cc: git
In-Reply-To: <465648EA.8070608@xs4all.nl>

Han-Wen Nienhuys <hanwen@xs4all.nl> writes:

>> If somebody else (or yourself) did:
>> 
>> 	$ git pull $dir LOCAL-BRANCH
>> 
>> (replace $dir with the `pwd` you would get in your repository),
>> that would work.  Why shouldn't it work for yourself?
>  
> Because
>
> "You are treating your local repository as if it is a remote
> repository somewhere else, namely, '.' (current repository)."
>
> that was the justification for not being able to pull in a remote
> branch.  This justification (which I disagree with) applies to this
> case as well.

Ah, so "forbidding a pull of local branch" was tongue-in-cheek
comment, and what you really wanted was to allow pulling remote
tracking branch with pull, either inside or outside of a
repository, like...

	$ git pull $somebody_elses_repo remotes/origin/master

without having to say "remotes/"?

That one comes from a different design issue.  refs/remotes/
hierarchy is local to your repository, and is not subject to
remote operation.

> I understand that we don't want people committing to
> remotes, because fetches will then later fail, but other than 
> that, why should there be limitations on using a remote?

My stance on this is that what I track as my upstream to
maintain my repository is none of other people's business.  I
have remote tracking branches because I use them to track
others; I do not necessarily have them with an intention to
publish them.

You could pull from my remote tracking branches using the fuller
refspec ("remotes/origin/master" in the example above) if you
really wanted to, and ls-remote lets you take a peek at them, so
the above "none of your business" is not in the sense of being
secretive, but is to reduce clutter and to avoid potential
confusion.

But this is an ancient design choice, and I am open to
suggestions loosening it, as long as we are aware of
implications.

One thing that comes to mind if we allow it is if a clone should
have refs/remotes/origin/remotes/origin/* that keeps track of
the remote that is being tracked by your origin.

I think it is insane to do so, but if somebody says "git pull
somewhere-else origin/master", we would not know if he meant
remotes/origin/master or remotes/origin/remotes/origin/master.

And the reason it is "insane" is the same as why we currently do
not interpret "git pull $repo origin/master" as a request to
pull from remotes/origin/master.  It really is none of your
business what kind of remote branches the other end is
interacting with.

^ permalink raw reply

* Re: [PATCH] Split packs from git-repack should have descending timestamps
From: Junio C Hamano @ 2007-05-25  3:18 UTC (permalink / raw)
  To: Dana How; +Cc: Shawn O. Pearce, Git Mailing List
In-Reply-To: <56b7f5510705241933x67fd4ed9h6d0e24341c19a9d4@mail.gmail.com>

"Dana How" <danahow@gmail.com> writes:

> Also,  if there are rules on allowable bash constructs
> (POSIX only, no &, etc),  perhaps they should go in
> SubmittingPatches near the new C99 comments?

No bash arrays, no "function" noisewords, limiting <funky> in
${word<funky>word} constructs to POSIX (that means +,-,#,##,%,%%
but no regexps), prefer "test" over "[" (the last one is just for
readability).

But the reason I barfed on "&" is not about the syntax nor
portability.  I was afraid of somebody else manipulating things
long after the parent "git-repack" returns (but still the
stamper sleeping and waiting to restamp the next one) and gets
confused.  In this particular case, the restamping is only about
the performance so it is not _too_ bad, but in general I really
do not like leftover processes still doing something in the
background when the user thinks everything is done.

> I understand your point,  but for a "normal" yet extremely
> large repository this may not be the case.  The "object density"
> patch is designed so that the density component of the sort
> key is extremely weak -- I think the timestamp is very revealing,
> and should be followed in the absence of large variations
> in object density.

I still think "a pack that has ONLY megablobs and mark it with
.keep" is much simpler approach, and there is no question that
density would work extremely well with that kind of arrangement.

^ permalink raw reply

* [PATCH] Move refspec pattern matching to match_refs().
From: Daniel Barkalow @ 2007-05-25  5:20 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

This means that send-pack and http-push will support pattern refspecs,
so builtin-push.c doesn't have to expand them, and also git push can
just turn --tags into "refs/tags/*", further simplifying
builtin-push.c

check_ref_format() gets a third "conditionally okay" result for
something that's valid as a pattern but not as a particular ref.

Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
---
On top of my "remote" series. Shouldn't change any significant behavior, 
and simplifies a lot of logic. This version takes into account the 
comments from the previous round (assuming that the ruling on coding style 
is that:

if (condition)
	/* Comment */
	statement;

shouldn't have braces).

 builtin-push.c |  133 +++++++++----------------------------------------------
 refs.c         |   27 ++++++++---
 remote.c       |   31 ++++++++++++-
 send-pack.c    |    1 +
 4 files changed, 70 insertions(+), 122 deletions(-)

diff --git a/builtin-push.c b/builtin-push.c
index 6084899..2612f07 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -9,7 +9,7 @@
 
 static const char push_usage[] = "git-push [--all] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]";
 
-static int all, tags, force, thin = 1, verbose;
+static int all, force, thin = 1, verbose;
 static const char *receivepack;
 
 static const char **refspec;
@@ -23,114 +23,24 @@ static void add_refspec(const char *ref)
 	refspec_nr = nr;
 }
 
-static int expand_one_ref(const char *ref, const unsigned char *sha1, int flag, void *cb_data)
-{
-	/* Ignore the "refs/" at the beginning of the refname */
-	ref += 5;
-
-	if (!prefixcmp(ref, "tags/"))
-		add_refspec(xstrdup(ref));
-	return 0;
-}
-
-static void expand_refspecs(void)
-{
-	if (all) {
-		if (refspec_nr)
-			die("cannot mix '--all' and a refspec");
-
-		/*
-		 * No need to expand "--all" - we'll just use
-		 * the "--all" flag to send-pack
-		 */
-		return;
-	}
-	if (!tags)
-		return;
-	for_each_ref(expand_one_ref, NULL);
-}
-
-struct wildcard_cb {
-	const char *from_prefix;
-	int from_prefix_len;
-	const char *to_prefix;
-	int to_prefix_len;
-	int force;
-};
-
-static int expand_wildcard_ref(const char *ref, const unsigned char *sha1, int flag, void *cb_data)
-{
-	struct wildcard_cb *cb = cb_data;
-	int len = strlen(ref);
-	char *expanded, *newref;
-
-	if (len < cb->from_prefix_len ||
-	    memcmp(cb->from_prefix, ref, cb->from_prefix_len))
-		return 0;
-	expanded = xmalloc(len * 2 + cb->force +
-			   (cb->to_prefix_len - cb->from_prefix_len) + 2);
-	newref = expanded + cb->force;
-	if (cb->force)
-		expanded[0] = '+';
-	memcpy(newref, ref, len);
-	newref[len] = ':';
-	memcpy(newref + len + 1, cb->to_prefix, cb->to_prefix_len);
-	strcpy(newref + len + 1 + cb->to_prefix_len,
-	       ref + cb->from_prefix_len);
-	add_refspec(expanded);
-	return 0;
-}
-
-static int wildcard_ref(const char *ref)
-{
-	int len;
-	const char *colon;
-	struct wildcard_cb cb;
-
-	memset(&cb, 0, sizeof(cb));
-	if (ref[0] == '+') {
-		cb.force = 1;
-		ref++;
-	}
-	len = strlen(ref);
-	colon = strchr(ref, ':');
-	if (! (colon && ref < colon &&
-	       colon[-2] == '/' && colon[-1] == '*' &&
-	       /* "<mine>/<asterisk>:<yours>/<asterisk>" is at least 7 bytes */
-	       7 <= len &&
-	       ref[len-2] == '/' && ref[len-1] == '*') )
-		return 0 ;
-	cb.from_prefix = ref;
-	cb.from_prefix_len = colon - ref - 1;
-	cb.to_prefix = colon + 1;
-	cb.to_prefix_len = len - (colon - ref) - 2;
-	for_each_ref(expand_wildcard_ref, &cb);
-	return 1;
-}
-
 static void set_refspecs(const char **refs, int nr)
 {
-	if (nr) {
-		int i;
-		for (i = 0; i < nr; i++) {
-			const char *ref = refs[i];
-			if (!strcmp("tag", ref)) {
-				char *tag;
-				int len;
-				if (nr <= ++i)
-					die("tag shorthand without <tag>");
-				len = strlen(refs[i]) + 11;
-				tag = xmalloc(len);
-				strcpy(tag, "refs/tags/");
-				strcat(tag, refs[i]);
-				ref = tag;
-			}
-			else if (wildcard_ref(ref))
-				continue;
-			add_refspec(ref);
+	int i;
+	for (i = 0; i < nr; i++) {
+		const char *ref = refs[i];
+		if (!strcmp("tag", ref)) {
+			char *tag;
+			int len;
+			if (nr <= ++i)
+				die("tag shorthand without <tag>");
+			len = strlen(refs[i]) + 11;
+			tag = xmalloc(len);
+			strcpy(tag, "refs/tags/");
+			strcat(tag, refs[i]);
+			ref = tag;
 		}
+		add_refspec(ref);
 	}
-	expand_refspecs();
 }
 
 static int do_push(const char *repo)
@@ -149,11 +59,9 @@ static int do_push(const char *repo)
 		sprintf(rp, "--receive-pack=%s", remote->receivepack);
 		receivepack = rp;
 	}
-	if (!refspec && !all && !tags && remote->push_refspec_nr) {
-		for (i = 0; i < remote->push_refspec_nr; i++) {
-			if (!wildcard_ref(remote->push_refspec[i]))
-				add_refspec(remote->push_refspec[i]);
-		}
+	if (!refspec && !all && remote->push_refspec_nr) {
+		refspec = remote->push_refspec;
+		refspec_nr = remote->push_refspec_nr;
 	}
 
 	argv = xmalloc((refspec_nr + 10) * sizeof(char *));
@@ -240,7 +148,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 			continue;
 		}
 		if (!strcmp(arg, "--tags")) {
-			tags = 1;
+			add_refspec("refs/tags/*");
 			continue;
 		}
 		if (!strcmp(arg, "--force") || !strcmp(arg, "-f")) {
@@ -266,5 +174,8 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 		usage(push_usage);
 	}
 	set_refspecs(argv + i, argc - i);
+	if (all && refspec)
+		usage(push_usage);
+
 	return do_push(repo);
 }
diff --git a/refs.c b/refs.c
index 2ae3235..ef4484d 100644
--- a/refs.c
+++ b/refs.c
@@ -603,15 +603,20 @@ int get_ref_sha1(const char *ref, unsigned char *sha1)
 
 static inline int bad_ref_char(int ch)
 {
-	return (((unsigned) ch) <= ' ' ||
-		ch == '~' || ch == '^' || ch == ':' ||
-		/* 2.13 Pattern Matching Notation */
-		ch == '?' || ch == '*' || ch == '[');
+	if (((unsigned) ch) <= ' ' ||
+	    ch == '~' || ch == '^' || ch == ':')
+		return 1;
+	/* 2.13 Pattern Matching Notation */
+	if (ch == '?' || ch == '[') /* Unsupported */
+		return 1;
+	if (ch == '*') /* Supported at the end */
+		return 2;
+	return 0;
 }
 
 int check_ref_format(const char *ref)
 {
-	int ch, level;
+	int ch, level, bad_type;
 	const char *cp = ref;
 
 	level = 0;
@@ -622,13 +627,19 @@ int check_ref_format(const char *ref)
 			return -1; /* should not end with slashes */
 
 		/* we are at the beginning of the path component */
-		if (ch == '.' || bad_ref_char(ch))
+		if (ch == '.')
 			return -1;
+		bad_type = bad_ref_char(ch);
+		if (bad_type) {
+			return (bad_type == 2 && !*cp) ? -3 : -1;
+		}
 
 		/* scan the rest of the path component */
 		while ((ch = *cp++) != 0) {
-			if (bad_ref_char(ch))
-				return -1;
+			bad_type = bad_ref_char(ch);
+			if (bad_type) {
+				return (bad_type == 2 && !*cp) ? -3 : -1;
+			}
 			if (ch == '/')
 				break;
 			if (ch == '.' && *cp == '.')
diff --git a/remote.c b/remote.c
index 46fe8d9..d904616 100644
--- a/remote.c
+++ b/remote.c
@@ -415,6 +415,10 @@ static int match_explicit_refs(struct ref *src, struct ref *dst,
 		struct ref *matched_src, *matched_dst;
 
 		const char *dst_value = rs[i].dst;
+
+		if (rs[i].pattern)
+			continue;
+
 		if (dst_value == NULL)
 			dst_value = rs[i].src;
 
@@ -497,22 +501,43 @@ static struct ref *find_ref_by_name(struct ref *list, const char *name)
 	return NULL;
 }
 
+static int check_pattern_match(struct refspec *rs, int rs_nr, struct ref *src)
+{
+	int i;
+	if (!rs_nr)
+		return 1;
+	for (i = 0; i < rs_nr; i++) {
+		if (rs[i].pattern && !prefixcmp(src->name, rs[i].src))
+			return 1;
+	}
+	return 0;
+}
+
 int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
 	       int nr_refspec, char **refspec, int all)
 {
 	struct refspec *rs =
 		parse_ref_spec(nr_refspec, (const char **) refspec);
 
-	if (nr_refspec)
-		return match_explicit_refs(src, dst, dst_tail, rs, nr_refspec);
+	if (match_explicit_refs(src, dst, dst_tail, rs, nr_refspec))
+		return -1;
 
 	/* pick the remainder */
 	for ( ; src; src = src->next) {
 		struct ref *dst_peer;
 		if (src->peer_ref)
 			continue;
+		if (!check_pattern_match(rs, nr_refspec, src))
+			continue;
+
 		dst_peer = find_ref_by_name(dst, src->name);
-		if ((dst_peer && dst_peer->peer_ref) || (!dst_peer && !all))
+		if (dst_peer && dst_peer->peer_ref)
+			/* We're already sending something to this ref. */
+			continue;
+		if (!dst_peer && !nr_refspec && !all)
+			/* Remote doesn't have it, and we have no
+			 * explicit pattern, and we don't have
+			 * --all. */
 			continue;
 		if (!dst_peer) {
 			/* Create a new one and link it */
diff --git a/send-pack.c b/send-pack.c
index 59352c8..697dbbc 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -354,6 +354,7 @@ static void verify_remote_names(int nr_heads, char **heads)
 		case -2: /* ok but a single level -- that is fine for
 			  * a match pattern.
 			  */
+		case -3: /* ok but ends with a pattern-match character */
 			continue;
 		}
 		die("remote part of refspec is not a valid name in %s",
-- 
1.5.2.rc2.90.gc593-dirty

^ permalink raw reply related

* Re: [PATCH] Prevent megablobs from gunking up git packs
From: Nicolas Pitre @ 2007-05-25  5:44 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Dana How, Junio C Hamano, Git Mailing List
In-Reply-To: <20070525020642.GS28023@spearce.org>


OK..... I ignore git@vger.kernel.org for a day or two and things really 
start to go wild!  ;-)

I'll try to cover only those points that are still debatable.  I think 
everybody agrees with huge blobs as loose objects using extra inodes 
being the least of our worries.

On Thu, 24 May 2007, Shawn O. Pearce wrote:

> Dana How <danahow@gmail.com> wrote:
> > On 5/24/07, Shawn O. Pearce <spearce@spearce.org> wrote:
> > >Junio C Hamano <junkio@cox.net> wrote:
> > >> "Dana How" <danahow@gmail.com> writes:
> > >> > We have three options in this case:
> > >> > (1) Drop the object (do not put it in the new pack(s)).
> > >> > (2) Pass the object into the new pack(s).
> > >> > (3) Write out the object as a new loose object.
> > >> > Option (1) is unacceptable.  When you call git-repack -a,
> > >> > it blindly deletes all the non-kept packs at the end.  So
> > >> > the megablobs would be lost.
> > >> Ok, I can buy that -- (1) nor (2) are unacceptable and (3) is
> > >> the only sane thing to do for a previously packed objects that
> > >> exceed the size limit.

OK... I sort of agree, but not entirely.

First, let's examine the reasons for wanting to expulse a big blob out 
of a pack.

The first reason I've seen is that big blobs put surrounding objects way 
apart and pack access performance gets bad, especially tree walking.  
The solution to this problem is trivial: let's simply store big blobs 
together at the end of the pack!  Problem solved.

The other reason for keeping huge blobs out is that they bring repack 
performance down and create unnecessary IO.  Well, in that case I think 
that you should simply avoid (re)packing them in the first place.  I 
think it should be possible to combine both features: the split packs 
and the big-blobs-go-at-the-end solution I mentioned above so that those 
big blobs could end up in one or more packs of their own.

But writing loose objects from git-pack-objects... Nah, this is just too 
hacky and ugly.  The tool is about packing objects and starting to 
create loose objects from there is pushing the packing concept a bit too 
far for my taste.

I wouldn't mind a _separate_ tool that would load a pack index, 
determine object sizes from it, and then extract big objects to write 
them as loose objects (although I question its usefulness).  But not 
within pack-objects please.

So I think the best solution really involves a new parameter to 
git-pack-objects allowing for objects which size exceed a certain 
treshold to go at the end of the pack.  If they end up in a different 
pack because of pack size limit then so be it, at which point you could 
always explode that huge-blob pack into loose objects, avoiding the need 
for the extra tool I mention above, but again I don't think that would 
be that useful.

> > Again Geert made a good argument that didn't occur to me that
> > you definitely DON'T want to do deltification on such large objects.
> > Junio recently added delta/nodelta attribute; this would be useful
> > to me,  but unfortunately I have several continua of files,  each with
> > the same suffix,  but with largely varying sizes, so attributes won't
> > help me unless the name globs in .gitattributes are expanded to full
> > expressions similar to find(1) [i.e. include testing based on size,
> > perms, type],  which I think would be insane.

I think having a parameter to exclude object which size exceed a 
specified size treshold from deltification attempts would also be a 
valid option. But...

> Which brings up the comment I think I made (below) about skipping
> deltas on very large objects.  Things over a certain size are not
> likely to delta well, or in any reasonable time.  We probably should
> default to not trying to delta those, but let the user force us to
> do so with a .gitattributes option.  Maybe.

I don't agree with the presumption that huge objects are unlikely to 
delta well.  It really depends on the data you have.  If, for example, 
you want to store, say, different versions of a filesystem image, then 
those different images have the potential to be really huge. Yet they 
might delta extremely well against each other and provide a tremendous 
space saving.

It all depends on the kind of data you work with.
It is good to have the possibility to skip deltification based on a file 
attribute.  It is also good to have the possibility to skip 
deltification based on object size (through a command line switch or 
config entry).  But those must remain _options_.

> > >Huge packfiles probably should be scheduled for keeping with a .keep
> > >automatically.  We probably should teach pack-objects to generate a
> > >.keep file if the resulting .pack was over a certain size threshold
> > >(say 1.5 GiB by default) and teach git-repack to rename the .keep
> > >file as it also renames the .idx and .pack.

Nah.  Those kind of arbitrary defaults are most likely to be fine for 
some cases and bad for many others.  These "sick" cases such as Dana's 
are so special that they better be manually tuned for best operations 
according to the data set, and more importantly to the work flow used, 
because different work flows are likely to require different "defaults".  
Better not put any arbitrary default and create a "Advanced tuning for 
best performances with insane repositories" section in the documentation 
instead.

> > >Better that we degrade gracefully when faced with massive inputs
> > >than we do something stupid by default and make the poor user pay
> > >for their mistake of not throughly reading plumbing documentation
> > >before use.

Well, I think that if someone is seriously considering GIT for a 
multi-gigabyte repository, that person has better read a little 
documentation before starting to play.  Of course this advanced tuning 
for huge repository section I'm suggesting should stand out in the main 
index.  And most "poor users" usually don't have such a big repo to 
fool themselves with.

> > >Now I would agree that we should punt on deltification of anything
> > >that is just too large, and let the user decide what too large means,
> > >and default it around 500 or 1024 MiB.  But I would still stuff it
> > >into a packfile.

Well, thing is, once deltified, those huge objects won't be subject to 
deltification attempts anymore, unless -f is used.  So the deltification 
cost will happen only once anyway.  Then it is only the issue of 
flagging a particular pack with .keep to exclude it from any further 
repacking which would simply end up wasting disk IO anyway.

There is certainly a hard default on deltification attempt that we 
should impose right now though, which is 4GB.  The reason is that the 
delta encoding doesn't do offsets larger than 32 bits at the moment.

> > I previously offered to Junio that the "write loose object" thing
> > could be restricted:  it would only happen if -f were supplied to
> > git-repack,  otherwise the bad blob would pass through to the new pack.
> > Does this "reduction in strength" make this feature more palatable to you?

Not really.

Like I said before, I'd much prefer to have a split pack for huge 
objects, and a separate unpack-object pass on it if you really want them 
loose.  If you want to deny entry of loose objects into a pack based on 
their size that's understandable, but only if they're already loose.

> > I don't agree that once in a packfile,  a blob should stay there.
> > Its presence is degrading access to "normal" blobs co-habiting with it.

As mentioned at the top I don't think this is a big issue.

> Or is it just because we like to repack the smaller metadata
> frequently, but that's horribly expensive because the megablobs
> are in the same packfile?  If its really just about repacking then
> .keep marked megablob packs are the way to go.

I think so as well.


Nicolas

^ permalink raw reply

* [PATCH] Enhance unpack-objects for extracting large objects
From: Dana How @ 2007-05-25  8:20 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List, danahow


Nicolas Pitre wrote:
> I wouldn't mind a _separate_ tool that would load a pack index,
> determine object sizes from it, and then extract big objects to write
> them as loose objects ...

Below we add two new options to git-unpack-objects:

--min-blob-size=<n>::  Unpacking is only done for objects
larger than or equal to n kB (uncompressed size by Junio).

--force::  Loose objects will be created even if they
already exist in the repository packed.  This is an option
I've wanted before for other reasons.

This passes the tests in "t" but has not yet been used on my large repos.
Based on "next" but should apply to "master" as well.

Signed-off-by: Dana L. How <danahow@gmail.com>
---
 Documentation/git-unpack-objects.txt |   17 +++++++++++++----
 builtin-unpack-objects.c             |   20 ++++++++++++++++++--
 cache.h                              |    2 ++
 sha1_file.c                          |   11 +++++++++--
 4 files changed, 42 insertions(+), 8 deletions(-)

diff --git a/Documentation/git-unpack-objects.txt b/Documentation/git-unpack-objects.txt
index ff6184b..4513d8d 100644
--- a/Documentation/git-unpack-objects.txt
+++ b/Documentation/git-unpack-objects.txt
@@ -8,7 +8,7 @@ git-unpack-objects - Unpack objects from a packed archive
 
 SYNOPSIS
 --------
-'git-unpack-objects' [-n] [-q] [-r] <pack-file
+'git-unpack-objects' [-n] [-q] [-r] [--force] [--min-blob-size=N] <pack-file
 
 
 DESCRIPTION
@@ -17,9 +17,10 @@ Read a packed archive (.pack) from the standard input, expanding
 the objects contained within and writing them into the repository in
 "loose" (one object per file) format.
 
-Objects that already exist in the repository will *not* be unpacked
-from the pack-file.  Therefore, nothing will be unpacked if you use
-this command on a pack-file that exists within the target repository.
+By default,  objects that already exist in the repository will *not*
+be unpacked from the pack-file.  Therefore, nothing will be unpacked
+if you use this command on a pack-file that exists within the target
+repository,  unless you specify --force.
 
 Please see the `git-repack` documentation for options to generate
 new packs and replace existing ones.
@@ -40,6 +41,14 @@ OPTIONS
 	and make the best effort to recover as many objects as
 	possible.
 
+--force::
+	Allow loose objects to be created in the same repository that
+	contains the packfile.
+
+--min-blob-size=<n>::
+	Smallest loose object to create,  expressed in kB.
+	Blobs smaller than this will not be unpacked.  Default is 0.
+
 
 Author
 ------
diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c
index a6ff62f..a42bf0d 100644
--- a/builtin-unpack-objects.c
+++ b/builtin-unpack-objects.c
@@ -10,13 +10,16 @@
 #include "progress.h"
 
 static int dry_run, quiet, recover, has_errors;
-static const char unpack_usage[] = "git-unpack-objects [-n] [-q] [-r] < pack-file";
+static const char unpack_usage[] =
+"git-unpack-objects [-n] [-q] [-r] [--force] [--min-blob-size=N] < pack-file";
 
 /* We always read in 4kB chunks. */
 static unsigned char buffer[4096];
 static unsigned int offset, len;
 static off_t consumed_bytes;
 static SHA_CTX ctx;
+static int force = 0;
+uint32_t min_blob_size;
 
 /*
  * Make sure at least "min" bytes are available in the buffer, and
@@ -131,7 +134,9 @@ static void added_object(unsigned nr, enum object_type type,
 static void write_object(unsigned nr, enum object_type type,
 			 void *buf, unsigned long size)
 {
-	if (write_sha1_file(buf, size, typename(type), obj_list[nr].sha1) < 0)
+	int force2 = size < min_blob_size ? -1 : force;
+	if (write_sha1_file_maybe(buf, size, typename(type),
+				  force2, obj_list[nr].sha1) < 0)
 		die("failed to write object");
 	added_object(nr, type, buf, size);
 }
@@ -361,6 +366,17 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
 				recover = 1;
 				continue;
 			}
+			if (!strcmp(arg, "--force")) {
+				force = 1;
+				continue;
+			}
+			if (!prefixcmp(arg, "--min-blob-size=")) {
+				char *end;
+				min_blob_size = strtoul(arg+16, &end, 0) * 1024;
+				if (!arg[16] || *end)
+					usage(unpack_usage);
+				continue;
+			}
 			if (!prefixcmp(arg, "--pack_header=")) {
 				struct pack_header *hdr;
 				char *c;
diff --git a/cache.h b/cache.h
index ec85d93..d0c3030 100644
--- a/cache.h
+++ b/cache.h
@@ -343,6 +343,8 @@ extern int sha1_object_info(const unsigned char *, unsigned long *);
 extern void * read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size);
 extern int hash_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1);
 extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *return_sha1);
+extern int write_sha1_file_maybe(void *buf, unsigned long len, const char *type,
+				 int ignore, unsigned char *return_sha1);
 extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);
 
 extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type);
diff --git a/sha1_file.c b/sha1_file.c
index 12d2ef2..68b8db8 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1979,7 +1979,8 @@ int hash_sha1_file(const void *buf, unsigned long len, const char *type,
 	return 0;
 }
 
-int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *returnsha1)
+int write_sha1_file_maybe(void *buf, unsigned long len, const char *type,
+			  int ignore, unsigned char *returnsha1)
 {
 	int size, ret;
 	unsigned char *compressed;
@@ -1997,7 +1998,7 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha
 	filename = sha1_file_name(sha1);
 	if (returnsha1)
 		hashcpy(returnsha1, sha1);
-	if (has_sha1_file(sha1))
+	if (ignore < 0 || !ignore && has_sha1_file(sha1))
 		return 0;
 	fd = open(filename, O_RDONLY);
 	if (fd >= 0) {
@@ -2062,6 +2063,12 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha
 	return move_temp_to_file(tmpfile, filename);
 }
 
+int write_sha1_file(void *buf, unsigned long len, const char *type,
+		    unsigned char *returnsha1)
+{
+	return write_sha1_file_maybe(buf, len, type, 0, returnsha1);
+}
+
 /*
  * We need to unpack and recompress the object for writing
  * it out to a different file.
-- 
1.5.2.762.gd8c6-dirty

^ permalink raw reply related

* MinGW port updated to 1.5.2
From: Johannes Sixt @ 2007-05-25  8:26 UTC (permalink / raw)
  To: git

This minute I've pushed the MinGW port, which is now at 1.5.2 to:

gitweb:     http://repo.or.cz/w/git/mingw.git
pull/clone: git://repo.or.cz/git/mingw.git

In addition to the 1.5.2 features, the progress indicator is shown in
more places (most notably when "Counting objects"), and
GIT_EXTERNAL_DIFF works now.

-- Hannes

^ permalink raw reply

* Re: GIT on MinGW problem
From: Johannes Sixt @ 2007-05-25  8:49 UTC (permalink / raw)
  To: git
In-Reply-To: <464534EE.30904@xs4all.nl>

Han-Wen Nienhuys wrote:
> 
> Aaron Gray escreveu:
> > Hello,
> >
> > I have installed the git-1.5.1-1.mingw.exe from
> > http://lilypond.org/git/binaries/mingw/.
> >
> > On typing 'git' I get a message box saying :-
> >
> >        The procedure entry point libiconv could not be located in the
> > dynamic link library libiconv-2.dll.
> >
> > I cannot seem to find libiconv-2.dll anywhere either.
> 
> This should be fixed in
> 
> http://lilypond.org/git/binaries/mingw/git-1.5.1-2.mingw.exe
> 
> it should also set $PATH.

I gave this some more testing and it turns out to be a well working
toolset. Thank you very much!

There were still some issues remaining. These are the ones that should
be fixable easily:

* git version reports just:

	git version -dirty

Since git-gui parses the output of git version, but does not expect it
to be of this format, and fails with an error message that it cannot
parse the version.

* git without an correct git subcommand should list 20 or so commands,
but it doesn't. The list is just empty.

* I personally think that the files should go into

	$PROGRAMFILES/Git/{bin,share,lib}
instead of
	$PROGRAMFILES/Git/usr/{bin,share,lib}

The more difficult to solve problems are:

* git-gui and gitk don't work out of the box because they have the path
to wish hardcoded. They can't be started from CMD at all. I have written
wrappers gitk.cmd and git-gui.cmd with these 2 lines:

@echo off
start wish84 D:/MSYS/1.0/git/bin/gitk %*

But as you can see, the path is still hard-coded (but it is good enough
for me for the moment).

* perl scripts like git-remote contain a hard-coded path to the
installation directory and don't work for this reason.

-- Hannes

^ permalink raw reply

* Re: GIT on MinGW problem
From: Marco Costalba @ 2007-05-25  9:45 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: git
In-Reply-To: <4656A304.AF39A0B6@eudaptics.com>

On 5/25/07, Johannes Sixt <J.Sixt@eudaptics.com> wrote:
> Han-Wen Nienhuys wrote:
> >
> > Aaron Gray escreveu:
> > > Hello,
> > >
> > > I have installed the git-1.5.1-1.mingw.exe from
> > > http://lilypond.org/git/binaries/mingw/.
> > >
> > > On typing 'git' I get a message box saying :-
> > >
> > >        The procedure entry point libiconv could not be located in the
> > > dynamic link library libiconv-2.dll.
> > >
> > > I cannot seem to find libiconv-2.dll anywhere either.
> >
> > This should be fixed in
> >
> > http://lilypond.org/git/binaries/mingw/git-1.5.1-2.mingw.exe
> >
> > it should also set $PATH.
>
> I gave this some more testing and it turns out to be a well working
> toolset. Thank you very much!
>
> There were still some issues remaining. These are the ones that should
> be fixable easily:
>
> * git version reports just:
>
>         git version -dirty
>
> Since git-gui parses the output of git version, but does not expect it
> to be of this format, and fails with an error message that it cannot
> parse the version.
>

Yes, an error message at startup is shown also with qgit.

Also 'git status' seems to have some issues.


 Marco

^ permalink raw reply

* Re: [PATCH] Make sure an autogenerated version has at least four parts
From: Martin Waitz @ 2007-05-25  9:47 UTC (permalink / raw)
  To: Sam Vilain; +Cc: Sam Vilain, Junio C Hamano, git
In-Reply-To: <46563CE1.9020007@vilain.net>

[-- Attachment #1: Type: text/plain, Size: 1210 bytes --]

hoi :)

On Fri, May 25, 2007 at 01:33:21PM +1200, Sam Vilain wrote:
> Martin Waitz wrote:
> > On Mon, May 21, 2007 at 02:52:21PM +1200, Sam Vilain wrote:
> >> Otherwise, a custom "v1.5.2.42.gd00b" is considered newer than a
> >> "v1.5.2.1.69.gcafe".
> > 
> > or just use git describe output without replacing "-" with "."?
> 
> dpkg uses "-" in version numbers for its own uses - to delimit the
> packager's packaging version from the software version.

But you can also have "-" in the upstream version without problems.
Only the last "-" is used as deliminator and therefore the Debian
version part must not contain a "-"; it's no problem for the upstream
part.


> The change I posted keeps original behaviour - just fills out the
> .0's.
> Perhaps the munging should go in git-describe instead?

If we want to be able to separate the software version as it is defined
by the project maintainer from the additional Git information we should
do so with a clear separator, not by changing the software version.

Maybe have some Makefile magic which creates a nice version,
but interpreting and changing the tagged version in git-describe sounds
wrong to me.

-- 
Martin Waitz

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH] Add git-submodule command
From: Lars Hjemli @ 2007-05-25  9:51 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano

This command can be used to initialize, update and inspect submodules. It
uses a .gitmodules file, readable by git-config, in the top level directory
of the 'superproject' to specify a mapping between submodule paths and
repository url. There is currently no way to override the mappings in the
.gitmodules file, except by manually creating the subproject repository.

Example .gitmodules layout:

[module "git"]
	url = git://git.kernel.org/pub/scm/git/git.git

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---

On 5/24/07, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> On Thu, 24 May 2007, Lars Hjemli wrote:
> > What I think would be nice is some porcelain support to manually init,
> > update and see the checked out version of selected subprojects, but as
> > standalone commands.
>
> Yes, a la git-remote. I'd be much happier with that, too, especially since
> I think that this can be a relatively small and easy-to-review script.

So, here it is. Please be kind :)

Btw: I've never managed to get asciidoc working on my machine, so the doc
isn't checked in any other format than plain text.


 Documentation/git-submodule.txt |   49 ++++++++++++
 Makefile                        |    2 +-
 git-submodule.sh                |  163 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 213 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/git-submodule.txt
 create mode 100755 git-submodule.sh

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
new file mode 100644
index 0000000..6ec917c
--- /dev/null
+++ b/Documentation/git-submodule.txt
@@ -0,0 +1,49 @@
+git-submodule(1)
+================
+
+NAME
+----
+git-submodule - Initialize, update or inspect submodules
+
+
+SYNOPSIS
+--------
+'git-submodule' [--init | --update | --cached] [--quiet] <path>...
+
+DESCRIPTION
+-----------
+The command shows the status of each specified submodule path, or all
+submodules if none is specified. Each submodule sha1 is prefixed with '-'
+if the submodule is uninitialized and '+' if the checked out version of
+the submodule is different from the commit sha1 stored in the index.
+
+
+OPTIONS
+-------
+<path>::
+	Path to submodule
+
+-i, --init::
+	Initialize the specified submodules, i.e. clone the git repository
+	specified in .gitmodules and checkout the sha1 specified in the
+	index.
+
+-u, --update::
+	Update the specified submodules, i.e. checkout the sha1 specified
+	in the index
+
+--cached::
+	Display the sha1 stored in the index, not the currently checked
+	out revsion.
+
+-q, --quiet::
+	Be quiet
+
+
+Author
+------
+Written by Lars Hjemli <hjemli@gmail.com>
+
+GIT
+---
+Part of the gitlink:git[7] suite
diff --git a/Makefile b/Makefile
index 29243c6..5cf2169 100644
--- a/Makefile
+++ b/Makefile
@@ -209,7 +209,7 @@ SCRIPT_SH = \
 	git-applymbox.sh git-applypatch.sh git-am.sh \
 	git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
 	git-merge-resolve.sh git-merge-ours.sh \
-	git-lost-found.sh git-quiltimport.sh
+	git-lost-found.sh git-quiltimport.sh git-submodule.sh
 
 SCRIPT_PERL = \
 	git-add--interactive.perl \
diff --git a/git-submodule.sh b/git-submodule.sh
new file mode 100755
index 0000000..c4a1cc3
--- /dev/null
+++ b/git-submodule.sh
@@ -0,0 +1,163 @@
+#!/bin/sh
+#
+# git-submodule.sh: init, update or list git submodules
+#
+# Copyright (c) 2007 Lars Hjemli
+
+USAGE='[-i | --init | -u | --update] [-q | --quiet] [--cached] <path>...'
+. git-sh-setup
+require_work_tree
+
+init=
+update=
+quiet=
+cached=
+
+#
+# print stuff on stdout unless -q was specified
+#
+say()
+{
+	if test -z "$quiet"
+	then
+		echo -e "$@"
+	fi
+}
+
+#
+# Find all (requested) submodules, run clone + checkout on missing paths
+#
+# $@ = requested paths (default to all)
+#
+modules_init()
+{
+	git ls-files --stage -- $@ | grep -e '^160000 ' |
+	while read mode sha1 stage path
+	do
+		test -d "$path/.git" && continue
+
+		if test -d "$path"
+		then
+			rmdir "$path" 2>/dev/null ||
+			die "Directory '$path' exist, but not as a submodule"
+		fi
+
+		test -e "$path" &&
+		die "A file already exist at path '$path'"
+
+		url=$(GIT_CONFIG=.gitmodules git-config module."$path".url)
+		test -z "$url" &&
+		die "No url found for submodule '$path' in .gitmodules"
+
+		git-clone "$url" "$path" ||
+		die "Clone of submodule '$path' failed"
+
+		$(cd "$path" && git-checkout -q "$sha1") ||
+		die "Checkout of submodule '$path' failed"
+
+		say "Submodule '$path' initialized"
+	done
+}
+
+#
+# Checkout correct revision of each initialized submodule
+#
+# $@ = requested paths (default to all)
+#
+modules_update()
+{
+	git ls-files --stage -- $@ | grep -e '^160000 ' |
+	while read mode sha1 stage path
+	do
+		if ! test -d "$path/.git"
+		then
+			say "Submodule '$path' not initialized"
+			continue;
+		fi
+		subsha1=$(cd "$path" && git-rev-parse --verify HEAD) ||
+		die "Unable to find current revision of submodule '$path'"
+
+		if test "$subsha1" != "$sha1"
+		then
+			$(cd "$path" && git-fetch && git-checkout -q "$sha1") ||
+			die "Unable to checkout revision $sha1 of submodule '$path'"
+
+			say "Submodule '$path' reset to revision $sha1"
+		fi
+	done
+}
+
+#
+# List all registered submodules, prefixed with:
+#  - submodule not initialized
+#  + different version checked out
+#
+# If --cached was specified the revision in the index will be printed
+# instead of the currently checked out revision.
+#
+# $@ = requested paths (default to all)
+#
+modules_list()
+{
+	git ls-files --stage -- $@ | grep -e '^160000 ' |
+	while read mode sha1 stage path
+	do
+		if ! test -d "$path/.git"
+		then
+			say "-$sha1 $path"
+			continue;
+		fi
+		revname=$(cd "$path" && git-describe $sha1)
+		if git diff-files --quiet -- "$path"
+		then
+			say " $sha1 $path\t($revname)"
+		else
+			if test -z "$cached"
+			then
+				sha1=$(cd "$path" && git-rev-parse --verify HEAD)
+				revname=$(cd "$path" && git-describe $sha1)
+			fi
+			say "+$sha1 $path\t($revname)"
+		fi
+	done
+}
+
+
+while case "$#" in 0) break ;; esac
+do
+	case "$1" in
+	-i|--init)
+		init=1
+		;;
+	-u|--update)
+		update=1
+		;;
+	-q|--quiet)
+		quiet=1
+		;;
+	--cached)
+		cached=1
+		;;
+	--)
+		break
+		;;
+	-*)
+		usage
+		;;
+	*)
+		break
+		;;
+	esac
+	shift
+done
+
+
+if test "$init" = "1"
+then
+	modules_init $@
+elif test "$update" = "1"
+then
+	modules_update $@
+else
+	modules_list $@
+fi
-- 
1.5.2.73.g18bece-dirty

^ permalink raw reply related

* News reader woes (was: Re: [3/4] What's not in 1.5.2 (new topics))
From: Jakub Narebski @ 2007-05-25  9:55 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Julian Phillips, Junio C Hamano, git
In-Reply-To: <20070520001610.GD4489@pasky.or.cz>

On Sun, 20 May 2007, Petr Baudis <pasky@suse.cz> wrote:
> On Fri, May 18, 2007 at 08:45:16PM CEST, Junio C Hamano wrote:
>> Julian Phillips <julian@quantumfyre.co.uk> writes:
>>> On Fri, 18 May 2007, Junio C Hamano wrote:
>>>> Jakub Narebski <jnareb@gmail.com> writes:
>>>>
>>>>> [Cc: Petr Baudis <pasky@suse.cz>, Josef Weidendorfer
>>>>> <Josef.Weidendorfer@gmx.de>, "Michael S. Tsirkin" <mst@dev.mellanox.co.il>,
>>>>> Junio C Hamano <junkio@cox.net>, Andy Parkins <andyparkins@gmail.com>,
>>>>> Nicolas Pitre <nico@cam.org>, git@vger.kernel.org]
>>>>
>>>> Offtopic.  Why do you do this, and what benefit are you or
>>>> anybody in the above list, which is in body part of the message,
>>>> getting?
>>>
>>> It looks like he is posting through gmane using a news reader ... so
>>> the list post comes from gmane while the CCs go out directly (I
>>> assume).
>> 
>> Ah, I see.  The names listed on that in-body CC: do appear on
>> the To: in the copy of the message that came via e-mail.  If
>> that is how gmane operates then there is nothing Jakub to do to
>> improve it, I guess...
>> 
>> Thanks for the clarification.
> 
> Actually, Jakub, if it can be turned off, could you, please?
> 
> Not getting cc'd on replies is slightly annoying. But this is highly
> confusing - suddenly I must take care _not_ to reply to the private
> copies, and we actually do have a parallel subthread of replies to your
> mail not cc'd to the mailing list. :-(

The problem, and mentioned above trying to overcome it, lies in
complicated interaction between the GMane news to email gateway,
vger mail filtering (spam protection rules) and the _news_ reader
I use, namely KNode 0.10.2 from KDE 3.5.3.

I read git mailing list via GMane NNTP (Usenet, news) interface:
  nntp://gmane.comp.version-control.git
as I respond only rarely. I start new threads using email, and
if I get reply via email I try to reply also from mail client, not
via news. However, when replying to message which I read only via
NNTP interface, replying in news client, I have option of sending
reply only to gmane.comp.version-control.git which means sending
email only to git mailing list and breaking Cc: list. 

Another option is to copy Cc: list manually to To: field (no Cc:
in this version of KNode), and have gmane.comp.version-control.git
in the Group: field.  The fact that there is no Cc: to set is the
problem of KNode.  The problem with GMane and vger interaction lies
in the fact that I _cannot_ put git@vger.kernel.org in the To: list,
as somehow vger rejects mails sent via GMane (it does not rejects
news messages send via GMane).

I could also copy whole message to mail client, but this would break
In-Reply-To: and references: headers, thus breaking threading.


Do I understand correctly that you prefer 1st option, namely replying
only to newsgroup / git mailing list?


Note that changing news client is as hard as changing email client:
you would like to migrate configuration, news state (read/unread
articles) and sent/drafts folders to new news client. Not that easy.

-- 
Jakub Narebski
Poland

^ permalink raw reply

* Re: [RFC] Fourth round of support for cloning submodules
From: Sven Verdoolaege @ 2007-05-25 10:00 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: Junio C Hamano, Lars Hjemli, Shawn O. Pearce, git, Martin Waitz,
	Alex Riesen
In-Reply-To: <Pine.LNX.4.64.0705241908040.4648@racer.site>

I'm obviously not going to stop anyone from putting URLs in .gitmodules
and I can see that it would be useful in practice, but I still think
that it doesn't matter where the submodule was located at any
given point in history (from the point of view of the superproject).
It only matters where the submodule is located now.

You may be bisecting a problem and you may need to clone a submodule
for a point in history when the submodule was placed somewhere else.
(You may not have had a need to checkout the submodule before,
or it may simply not be used in the current version of the supermodule.)
So, I think it would still be useful to have an optional additional
out-of-tree mechanism of getting usable URLs if the URLs in .gitmodules
or your local config don't work.

On Thu, May 24, 2007 at 07:11:31PM +0100, Johannes Schindelin wrote:
> On Thu, 24 May 2007, Sven Verdoolaege wrote:
> > If you allow an override, then I don't see how having the initial
> > information in the tree is any better.
> 
> Isn't that obvious? _Most_ people will _not_ override the information.

You may be asked to.

	"Please clone from a mirror close to you and after cloning,
	 please change the URLs of these 54 submodules to a mirror
	 close to you."

> Plus, it is an easy solution to your problem, without having to touch a 
> lot of real core parts of Git. Simple is beautiful. And less buggy.

I'll take your word for it.

> > He needs to modify .gitmodules, but when the changes go upstream,
> > this .gitmodules changes get merged as well.
> 
> If you change the superproject, that is.

That's what I meant.  Plus, other users may want to pull from such forks too.

skimo

^ 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