Git development
 help / color / mirror / Atom feed
* Re: git only one file
From: Giuseppe Bilotta @ 2009-08-26  4:30 UTC (permalink / raw)
  To: syn hedionn; +Cc: git
In-Reply-To: <a7c6f4d60908251605l5fb771a5t79b27cf688fab205@mail.gmail.com>

On Wed, Aug 26, 2009 at 1:05 AM, syn hedionn<synhedionn@gmail.com> wrote:
> ok , but if I put,
> git add index.htm
> I have:
> fatal: Not a git repository

You need to initialize the repository before you can add files to it, so:

git init
git add index.htm
git commit -m "Initial commit"

The zit way would be:

zit track index.htm
zit commit -m "Initial commit" index.htm

-- 
Giuseppe "Oblomov" Bilotta

^ permalink raw reply

* Re: gitosis-lite
From: Sitaram Chamarty @ 2009-08-26  5:01 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: Git Mailing List
In-Reply-To: <200908251405.17644.jnareb@gmail.com>

On Tue, Aug 25, 2009 at 5:35 PM, Jakub Narebski<jnareb@gmail.com> wrote:
> Sitaram Chamarty wrote:
>> On Tue, Aug 25, 2009 at 12:14 AM, Jakub Narebski<jnareb@gmail.com> wrote:

>> > Wouldn't it be better to use "use warnings" instead of 'perl -w'?

>> I'm not sure what is the minimum perl required for git

> I think that git requires Perl at least version 5.6

thanks; I'll change "-w" to "use warnings"

>> > It would be, I think, better if you have used POD for such
>> > documentation.  One would be able to generate manpage using pod2man,
>> > and it is no less readable in source code.  See e.g. perl/Git.pm or
>> > contrib/hooks/update-paranoid.
>>
>> Hmm... I've been spoiled by Markdown's sane bullet list
>> handling.  Visually, POD forces everything other than code
>> to be flush left -- any sort of list is definitely less
>> readable in source code as a result.  IMHO of course.
>
> How it is relevant to the issue at hand?  I was talking about replacing
> documentation comments in the header with POD markup.
>
> Also you usually document top-level structures with POD.

Forget I mentioned markdown :)  All I'm saying is that even in the
documentation you speak of, I have a couple of small "lists".  And I
like lists to be properly indented, that's all -- I am mentally unable
to edit them if they are all flush left :-( just like it's irritating
to edit code that's mis-indented or not indented.  Sorry...!

And yes, one of my python friends has then asked "why do you not like
python".  I have no answer.  As Whitman said
(http://www.quotationspage.com/quote/26914.html):

    Do I contradict myself?
    Very well then I contradict myself,
    (I am large, I contain multitudes.)

:-)

Regards,

-- 
Sitaram "not normally given to quoting poets" Chamarty

^ permalink raw reply

* [PATCH] Re: Teach mailinfo to ignore everything before -- >8 -- mark
From: Nicolas Sebrecht @ 2009-08-26  5:02 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Nicolas Sebrecht, Nanako Shiraishi, Thell Fowler, git,
	Johannes.Schindelin
In-Reply-To: <7veiqzjmy7.fsf@alter.siamese.dyndns.org>

The 25/08/09, Junio C Hamano wrote:

> I therefore conclude that using the "remove above scissors" should be a
> conscious decision, and should not be enabled by default.  --obey-scissors
> would be a good option for this reason.

I'm not sure what between --obey or --ignore will help most to write
good commit message.  I (as a maintainer myself or as a contributor)
usually prefer to --amend a commit rather than play with copy/paste or
starting from scratch. So, I tend to agree even if the reasons are not
exactly the same. :-)

That said, I don't bother what is the default that much. The main
purpose is to have the choice.

For people who _really_ want to obey to scissors by default I'll add an
option to git-config. Whithout more comments, I'll add

  scissors.obey

.

-- 
Nicolas Sebrecht

^ permalink raw reply

* Re: [PATCH] fix simple deepening of a repo
From: Johannes Sixt @ 2009-08-26  7:08 UTC (permalink / raw)
  To: Shawn O. Pearce
  Cc: Junio C Hamano, Nicolas Pitre, Julian Phillips, Daniel Barkalow,
	Johannes Schindelin, git
In-Reply-To: <20090826021057.GL1033@spearce.org>

Shawn O. Pearce schrieb:
>  static void upload_pack(void)
>  {
>  	reset_timeout();
> -	head_ref(send_ref, NULL);
> -	for_each_ref(send_ref, NULL);
> -	packet_flush(1);
> +	head_ref(scan_ref, NULL);
> +	for_each_ref(scan_ref, NULL);
> +
> +	push_advertise("HEAD");
> +	push_advertise("refs/heads/*");
> +	push_advertise("refs/tags/*");
> +	send_refs();
> +

How will this mesh with 'git clone --mirror'? Is the client expected to
ask with 'expand refs/*'?

-- Hannes

^ permalink raw reply

* Re: [PATCH] fix simple deepening of a repo
From: Shawn O. Pearce @ 2009-08-26  8:22 UTC (permalink / raw)
  To: Johannes Sixt
  Cc: Junio C Hamano, Nicolas Pitre, Julian Phillips, Daniel Barkalow,
	Johannes Schindelin, git
In-Reply-To: <4A94DF84.4050906@viscovery.net>

Johannes Sixt <j.sixt@viscovery.net> wrote:
> Shawn O. Pearce schrieb:
> >  static void upload_pack(void)
> >  {
> >  	reset_timeout();
> > -	head_ref(send_ref, NULL);
> > -	for_each_ref(send_ref, NULL);
> > -	packet_flush(1);
> > +	head_ref(scan_ref, NULL);
> > +	for_each_ref(scan_ref, NULL);
> > +
> > +	push_advertise("HEAD");
> > +	push_advertise("refs/heads/*");
> > +	push_advertise("refs/tags/*");
> > +	send_refs();
> > +
> 
> How will this mesh with 'git clone --mirror'?

Not well.

> Is the client expected to
> ask with 'expand refs/*'?

If the client is new enough to understand the "expand" extension,
yes, it would ask for "expand refs/*" and get everthing, allowing
it to complete a full mirror.

If the client is older and doesn't know this extension, then it
is hopeless.  The server isn't advertising refs/*, doesn't know
that the client can't ask for refs/*, and the client doesn't know
it is missing refs when it makes the mirror.

This backwards incompatible breakage is something I have no real
solution for.  :-|

-- 
Shawn.

^ permalink raw reply

* [PATCH] git-bisect: call the found commit "*the* first bad commit"
From: Nanako Shiraishi @ 2009-08-26  8:38 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano

.. as we learned in the school ;-)

Signed-off-by: Nanako Shiraishi <nanako3@lavabit.com>
---
 bisect.c                    |    2 +-
 git-bisect.sh               |    2 +-
 t/t6030-bisect-porcelain.sh |   18 +++++++++---------
 3 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/bisect.c b/bisect.c
index 7f20acb..dc18db8 100644
--- a/bisect.c
+++ b/bisect.c
@@ -991,7 +991,7 @@ int bisect_next_all(const char *prefix)
 
 	if (!hashcmp(bisect_rev, current_bad_sha1)) {
 		exit_if_skipped_commits(tried, current_bad_sha1);
-		printf("%s is first bad commit\n", bisect_rev_hex);
+		printf("%s is the first bad commit\n", bisect_rev_hex);
 		show_diff_tree(prefix, revs.commits->item);
 		/* This means the bisection process succeeded. */
 		exit(10);
diff --git a/git-bisect.sh b/git-bisect.sh
index 8969553..6f6f039 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -405,7 +405,7 @@ bisect_run () {
 	  exit $res
       fi
 
-      if grep "is first bad commit" "$GIT_DIR/BISECT_RUN" > /dev/null; then
+      if grep "is the first bad commit" "$GIT_DIR/BISECT_RUN" > /dev/null; then
 	  echo "bisect run success"
 	  exit 0;
       fi
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 1315bab..def397c 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -175,7 +175,7 @@ test_expect_success 'bisect skip: successfull result' '
 	git bisect start $HASH4 $HASH1 &&
 	git bisect skip &&
 	git bisect bad > my_bisect_log.txt &&
-	grep "$HASH2 is first bad commit" my_bisect_log.txt &&
+	grep "$HASH2 is the first bad commit" my_bisect_log.txt &&
 	git bisect reset
 '
 
@@ -261,7 +261,7 @@ test_expect_success \
      git bisect good $HASH1 &&
      git bisect bad $HASH4 &&
      git bisect run ./test_script.sh > my_bisect_log.txt &&
-     grep "$HASH3 is first bad commit" my_bisect_log.txt &&
+     grep "$HASH3 is the first bad commit" my_bisect_log.txt &&
      git bisect reset'
 
 # We want to automatically find the commit that
@@ -274,7 +274,7 @@ test_expect_success \
      chmod +x test_script.sh &&
      git bisect start $HASH4 $HASH1 &&
      git bisect run ./test_script.sh > my_bisect_log.txt &&
-     grep "$HASH4 is first bad commit" my_bisect_log.txt &&
+     grep "$HASH4 is the first bad commit" my_bisect_log.txt &&
      git bisect reset'
 
 # $HASH1 is good, $HASH5 is bad, we skip $HASH3
@@ -287,14 +287,14 @@ test_expect_success 'bisect skip: add line and then a new test' '
 	git bisect start $HASH5 $HASH1 &&
 	git bisect skip &&
 	git bisect good > my_bisect_log.txt &&
-	grep "$HASH5 is first bad commit" my_bisect_log.txt &&
+	grep "$HASH5 is the first bad commit" my_bisect_log.txt &&
 	git bisect log > log_to_replay.txt &&
 	git bisect reset
 '
 
 test_expect_success 'bisect skip and bisect replay' '
 	git bisect replay log_to_replay.txt > my_bisect_log.txt &&
-	grep "$HASH5 is first bad commit" my_bisect_log.txt &&
+	grep "$HASH5 is the first bad commit" my_bisect_log.txt &&
 	git bisect reset
 '
 
@@ -335,7 +335,7 @@ test_expect_success 'bisect run & skip: find first bad' '
 	chmod +x test_script.sh &&
 	git bisect start $HASH7 $HASH1 &&
 	git bisect run ./test_script.sh > my_bisect_log.txt &&
-	grep "$HASH6 is first bad commit" my_bisect_log.txt
+	grep "$HASH6 is the first bad commit" my_bisect_log.txt
 '
 
 test_expect_success 'bisect skip only one range' '
@@ -385,7 +385,7 @@ test_expect_success 'bisect does not create a "bisect" branch' '
 	rev_hash6=$(git rev-parse --verify HEAD) &&
 	test "$rev_hash6" = "$HASH6" &&
 	git bisect good > my_bisect_log.txt &&
-	grep "$HASH7 is first bad commit" my_bisect_log.txt &&
+	grep "$HASH7 is the first bad commit" my_bisect_log.txt &&
 	git bisect reset &&
 	rev_hash6=$(git rev-parse --verify bisect) &&
 	test "$rev_hash6" = "$HASH6" &&
@@ -534,7 +534,7 @@ test_expect_success 'restricting bisection on one dir' '
 	para1=$(git rev-parse --verify HEAD) &&
 	test "$para1" = "$PARA_HASH1" &&
 	git bisect bad > my_bisect_log.txt &&
-	grep "$PARA_HASH1 is first bad commit" my_bisect_log.txt
+	grep "$PARA_HASH1 is the first bad commit" my_bisect_log.txt
 '
 
 test_expect_success 'restricting bisection on one dir and a file' '
@@ -552,7 +552,7 @@ test_expect_success 'restricting bisection on one dir and a file' '
 	para1=$(git rev-parse --verify HEAD) &&
 	test "$para1" = "$PARA_HASH1" &&
 	git bisect good > my_bisect_log.txt &&
-	grep "$PARA_HASH4 is first bad commit" my_bisect_log.txt
+	grep "$PARA_HASH4 is the first bad commit" my_bisect_log.txt
 '
 
 test_expect_success 'skipping away from skipped commit' '
-- 
1.6.4.1

-- 
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/

^ permalink raw reply related

* Re: [PATCH] upload-pack: add a trigger for post-upload-pack hook
From: Johannes Schindelin @ 2009-08-26  8:44 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jeff King, Tom Werner, Tom Preston-Werner, git
In-Reply-To: <7vprajmp16.fsf@alter.siamese.dyndns.org>

Hi,

On Tue, 25 Aug 2009, Junio C Hamano wrote:

> If we are allowed to talk about asking for the moon,

How about

 	run_hook(NULL, "post-upload-pack",
         	 create_full_pack ? "clone" : "fetch,
		 "the moon",
                 NULL);

then?

> and if one of the primary reason for this new hook is statistics, it 
> would be useful to see the number of bytes given, where the fetch-pack 
> came from, and if we are using git-daemon virtual hosting which of our 
> domain served the request.

Certainly those are possible add-on patches, but would you require them to 
be in the same commit?

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH] Re: Teach mailinfo to ignore everything before -- >8 -- mark
From: Jakub Narebski @ 2009-08-26  8:57 UTC (permalink / raw)
  To: git
In-Reply-To: <20090826050224.GK3526@vidovic>

Nicolas Sebrecht wrote:

> For people who _really_ want to obey to scissors by default I'll add an
> option to git-config. Whithout more comments, I'll add
> 
>   scissors.obey

mailsplit.scissors

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

^ permalink raw reply

* Re: [PATCH] Re: Teach mailinfo to ignore everything before -- >8 -- mark
From: Johannes Schindelin @ 2009-08-26  9:00 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: git
In-Reply-To: <h72td7$cu6$1@ger.gmane.org>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 479 bytes --]

Hi,

On Wed, 26 Aug 2009, Jakub Narebski wrote:

> Nicolas Sebrecht wrote:
> 
> > For people who _really_ want to obey to scissors by default I'll add 
> > an option to git-config. Whithout more comments, I'll add
> > 
> >   scissors.obey
> 
> mailsplit.scissors

Sorry, did not have time to read this thread properly, but has anybody put 
thought into the interaction between this patch and "git rebase" (which 
uses "git am", and therefore mailsplit, internally)?

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH] Re: Teach mailinfo to ignore everything before -- >8 -- mark
From: Junio C Hamano @ 2009-08-26  9:03 UTC (permalink / raw)
  To: Jakub Narebski
  Cc: Nicolas Sebrecht, Nanako Shiraishi, Thell Fowler, git,
	Johannes.Schindelin
In-Reply-To: <h72td7$cu6$1@ger.gmane.org>

Jakub Narebski <jnareb@gmail.com> writes:

> Nicolas Sebrecht wrote:
>
>> For people who _really_ want to obey to scissors by default I'll add an
>> option to git-config. Whithout more comments, I'll add
>> 
>>   scissors.obey
>
> mailsplit.scissors

That may be a better name.

It must take lower precedence than the command line --no-scissors option,
and that option must be given to am when rebase internally runs am, so that
we won't pay attention to scissors when rebasing existing commits.

^ permalink raw reply

* Re: [PATCH] upload-pack: add a trigger for post-upload-pack hook
From: Junio C Hamano @ 2009-08-26  9:03 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Jeff King, Tom Werner, Tom Preston-Werner, git
In-Reply-To: <alpine.DEB.1.00.0908261043140.4713@intel-tinevez-2-302>

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

> Hi,
>
> On Tue, 25 Aug 2009, Junio C Hamano wrote:
>
>> If we are allowed to talk about asking for the moon,
>
> How about
>
>  	run_hook(NULL, "post-upload-pack",
>          	 create_full_pack ? "clone" : "fetch,
> 		 "the moon",
>                  NULL);
>
> then?
>
>> and if one of the primary reason for this new hook is statistics, it 
>> would be useful to see the number of bytes given, where the fetch-pack 
>> came from, and if we are using git-daemon virtual hosting which of our 
>> domain served the request.
>
> Certainly those are possible add-on patches, but would you require them to 
> be in the same commit?

I was merely responding to the "what else would be useful" question posed
by Peff.

Did you get an impression that I was saying "you must add these otherwise
I'll reject the patch"?

I didn't mean to.  I think it is entirely reasonable to queue the patch in
'pu' (after fixing the NULL termination bug), and start cooking without
any of the additional information.

Having said that, this is an external interface, and until we feel
reasonably sure that we are giving enough information to the hook and
we wouldn't need to change the interface, the series must not come near
'master'.

It might make sense to define the external interface to be "information is
given through the standard input of the hook, formatted in YAML, and here
are the initial set of items that may be fed", so that we do not have to
worry about the details too much.

^ permalink raw reply

* Re: [PATCH] fix simple deepening of a repo
From: Junio C Hamano @ 2009-08-26  9:03 UTC (permalink / raw)
  To: Shawn O. Pearce
  Cc: Johannes Sixt, Junio C Hamano, Nicolas Pitre, Julian Phillips,
	Daniel Barkalow, Johannes Schindelin, git
In-Reply-To: <20090826082256.GO1033@spearce.org>

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

>> How will this mesh with 'git clone --mirror'?
>
> Not well.
>
>> Is the client expected to
>> ask with 'expand refs/*'?
>
> If the client is new enough to understand the "expand" extension,
> yes, it would ask for "expand refs/*" and get everthing, allowing
> it to complete a full mirror.
>
> If the client is older and doesn't know this extension, then it
> is hopeless.  The server isn't advertising refs/*, doesn't know
> that the client can't ask for refs/*, and the client doesn't know
> it is missing refs when it makes the mirror.
>
> This backwards incompatible breakage is something I have no real
> solution for.  :-|

But we at least can assume that the server operator is reasonable and
wouldn't go overboard, (ab)using this "abbreviated advertisement" feature
to hide heads and tags from the clients.  I would suspect that a server
operated by such a sick person who hides these normal refs will be shunned
by users so it won't either happen in practice, or even if it happens, it
won't be a problem---simply because nobody would want to interact with
such a server.  

Think about in what situation you would want to do a mirror clone.  The
most obvious is to have a back-up or secondary distribution point, and I
do not think of any other sane reason (other than "because I can", which
does not count).  If the original repository has so many refs to benefit
from the "abbreviated advertisement" feature (otherwise there is no point
using it in the first place), then its mirror repository would also want
to use the feature when talking to its clients, acting as a back-up
distribution point.  That means the version of git used to prime, update
and serve the mirror will know the expand extention.

I am hoping that we can finish 1.6.5 by mid September (let's tentatively
say we will shoot for 16th).  I expect the expand extention to be in
'next' by that time, cooking for 1.7.0.  How does that timetable sound?

^ permalink raw reply

* [PATCH v3] Add script for importing bits-and-pieces to Git.
From: Peter Krefting @ 2009-08-24 17:09 UTC (permalink / raw)
  To: git

Allows the user to import version history that is stored in bits and
pieces in the file system, for instance snapshots of old development
trees, or day-by-day backups. A configuration file is used to
describe the relationship between the different files and allow
describing branches and merges, as well as authorship and commit
messages.

Output is created in a format compatible with git-fast-import.

Full documentation is provided inline in perldoc format.

Signed-off-by: Peter Krefting <peter@softwolves.pp.se>
---
This version contains updated documentation, trying to address the
points raised by Junio. It also fixes a compile error that snuck in
the v2 patch.

 contrib/fast-import/import-directories.perl |  332 +++++++++++++++++++++++++++
 1 files changed, 332 insertions(+), 0 deletions(-)
 create mode 100755 contrib/fast-import/import-directories.perl

diff --git a/contrib/fast-import/import-directories.perl b/contrib/fast-import/import-directories.perl
new file mode 100755
index 0000000..98079ad
--- /dev/null
+++ b/contrib/fast-import/import-directories.perl
@@ -0,0 +1,332 @@
+#!/usr/bin/perl -w
+#
+# Copyright 2008-2009 Peter Krefting <peter@softwolves.pp.se>
+#
+# ------------------------------------------------------------------------
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# ------------------------------------------------------------------------
+
+=pod
+
+=head1 NAME
+
+import-directories - Import bits and pieces to Git.
+
+=head1 SYNOPSIS
+
+B<import-directories.perl> F<configfile>
+
+=head1 DESCRIPTION
+
+Script to import arbitrary projects version controlled by the "copy the
+source directory to a new location and edit it there"-version controlled
+projects into version control. Handles projects with arbitrary branching
+and version trees, taking a file describing the inputs and generating a
+file compatible with the L<git-fast-import(1)> format.
+
+=head1 CONFIGURATION FILE
+
+=head2 Format
+
+The configuration file is using a standard I<.ini> format.
+
+ ; Comments start with semi-colons
+ [section]
+ key=value
+
+=head2 Global configuration
+
+Global configuration is done in the B<[config]> section, which should be
+the first section in the file. Configuration can be changed by
+repeating configuration sections later on.
+
+ [config]
+ ; configure conversion of CRLFs. "convert" means that all CRLFs
+ ; should be converted into LFs (suitable for the core.autocrlf
+ ; setting set to true in Git). "none" means that all data is
+ ; treated as binary.
+ crlf=convert
+
+=head2 Revision configuration
+
+Each revision that is to be imported is described in three
+sections. Sections should be defined chronologically, so that a
+revision's parent has always been defined when a new revision
+is introduced. All sections for one revision should be defined
+before defining the next revision.
+
+Revisions are specified numerically, but they numbers need not be
+consecutive, only unique.
+
+=pod
+
+=head3 Revision description section
+
+A section whose section name is just an integer gives meta-data
+about the revision.
+
+ [3]
+ ; author sets the author of the revisions
+ author=Peter Krefting <peter@softwolves.pp.se>
+ ; branch sets the branch that the revision should be committed to
+ branch=master
+ ; parent describes the revision that is the parent of this commit
+ ; (optional)
+ parent=1
+ ; merges describes a revision that is merged into this commit
+ ; (optional; can be repeated)
+ merges=2
+ ; selects one file to take the timestamp from
+ ; (optional; if unspecified, the most recent file from the .files
+ ;  section is used)
+ timestamp=3/source.c
+
+=head3 Revision contents section
+
+A section whose section name is an integer followed by B<.files>
+describes the files included in this revision.
+
+ [3.files]
+ ; the key is the path inside the repository, the value is the path
+ ; as seen from the importer script.
+ source.c=3/source.c
+ source.h=3/source.h
+
+=head3 Revision commit message section
+
+A section whose section name is an integer followed by B<.message>
+gives the commit message. This section is read verbatim.
+
+ [3.message]
+ Implement foobar.
+ ; trailing blank lines are ignored.
+
+=cut
+
+# Globals
+use strict;
+use integer;
+my $crlfmode = 0;
+my @revs;
+my (%revmap, %message, %files, %author, %branch, %parent, %merges, %time, %timesource);
+my $sectiontype = 0;
+my $rev = 0;
+my $mark = 1;
+
+# Check command line
+if ($#ARGV == -1 || $ARGV[0] =~ /^--?h/)
+{
+    exec('perldoc', $0);
+    exit 1;
+}
+
+# Open configuration
+my $config = $ARGV[0];
+open CFG, '<', $config or die "Cannot open configuration file \"$config\": ";
+
+# Open output
+my $output = $ARGV[1];
+open OUT, '>', $output or die "Cannot create output file \"$output\": ";
+binmode OUT;
+
+LINE: while (my $line = <CFG>)
+{
+	$line =~ s/\r?\n$//;
+	next LINE if $sectiontype != 4 && $line eq '';
+	next LINE if $line =~ /^;/;
+	my $oldsectiontype = $sectiontype;
+	my $oldrev = $rev;
+
+	# Sections
+	if ($line =~ m"^\[(config|(\d+)(|\.files|\.message))\]$")
+	{
+		if ($1 eq 'config')
+		{
+			$sectiontype = 1;
+		}
+		elsif ($3 eq '')
+		{
+			$sectiontype = 2;
+			$rev = $2;
+			# Create a new revision
+			die "Duplicate rev: $line\n " if defined $revmap{$rev};
+			print "Reading revision $rev\n";
+			push @revs, $rev;
+			$revmap{$rev} = $mark ++;
+			$time{$revmap{$rev}} = 0;
+		}
+		elsif ($3 eq '.files')
+		{
+			$sectiontype = 3;
+			$rev = $2;
+			die "Revision mismatch: $line\n " unless $rev == $oldrev;
+		}
+		elsif ($3 eq '.message')
+		{
+			$sectiontype = 4;
+			$rev = $2;
+			die "Revision mismatch: $line\n " unless $rev == $oldrev;
+		}
+		else
+		{
+			die "Internal parse error: $line\n ";
+		}
+		next LINE;
+	}
+
+	# Parse data
+	if ($sectiontype != 4)
+	{
+		# Key and value
+		if ($line =~ m"^(.*)=(.*)$")
+		{
+			my ($key, $value) = ($1, $2);
+			# Global configuration
+			if (1 == $sectiontype)
+			{
+				if ($key eq 'crlf')
+				{
+					$crlfmode = 1, next LINE if $value eq 'convert';
+					$crlfmode = 0, next LINE if $value eq 'none';
+				}
+				die "Unknown configuration option: $line\n ";
+			}
+			# Revision specification
+			if (2 == $sectiontype)
+			{
+				my $current = $revmap{$rev};
+				$author{$current} = $value, next LINE if $key eq 'author';
+				$branch{$current} = $value, next LINE if $key eq 'branch';
+				$parent{$current} = $value, next LINE if $key eq 'parent';
+				$timesource{$current} = $value, next LINE if $key eq 'timestamp';
+				push(@{$merges{$current}}, $value), next LINE if $key eq 'merges';
+				die "Unknown revision option: $line\n ";
+			}
+			# Filespecs
+			if (3 == $sectiontype)
+			{
+				# Add the file and create a marker
+				die "File not found: $line\n " unless -f $value;
+				my $current = $revmap{$rev};
+				${$files{$current}}{$key} = $mark;
+				my $time = &fileblob($value, $crlfmode, $mark ++);
+
+				# Update revision timestamp if more recent than other
+				# files seen, or if this is the file we have selected
+				# to take the time stamp from using the "timestamp"
+				# directive.
+				if ((defined $timesource{$current} && $timesource{$current} eq $value)
+				    || $time > $time{$current})
+				{
+					$time{$current} = $time;
+				}
+			}
+		}
+		else
+		{
+			die "Parse error: $line\n ";
+		}
+	}
+	else
+	{
+		# Commit message
+		my $current = $revmap{$rev};
+		if (defined $message{$current})
+		{
+			$message{$current} .= "\n";
+		}
+		$message{$current} .= $line;
+	}
+}
+close CFG;
+
+# Start spewing out data for git-fast-import
+foreach my $commit (@revs)
+{
+	# Progress
+	print OUT "progress Creating revision $commit\n";
+
+	# Create commit header
+	my $mark = $revmap{$commit};
+
+	# Branch and commit id
+	print OUT "commit refs/heads/", $branch{$mark}, "\nmark :", $mark, "\n";
+
+	# Author and timestamp
+	die "No timestamp defined for $commit (no files?)\n" unless defined $time{$mark};
+	print OUT "committer ", $author{$mark}, " ", $time{$mark}, " +0100\n";
+
+	# Commit message
+	die "No message defined for $commit\n" unless defined $message{$mark};
+	my $message = $message{$mark};
+	$message =~ s/\n$//; # Kill trailing empty line
+	print OUT "data ", length($message), "\n", $message, "\n";
+
+	# Parent and any merges
+	print OUT "from :", $revmap{$parent{$mark}}, "\n" if defined $parent{$mark};
+	if (defined $merges{$mark})
+	{
+		foreach my $merge (@{$merges{$mark}})
+		{
+			print OUT "merge :", $revmap{$merge}, "\n";
+		}
+	}
+
+	# Output file marks
+	print OUT "deleteall\n"; # start from scratch
+	foreach my $file (sort keys %{$files{$mark}})
+	{
+		print OUT "M 644 :", ${$files{$mark}}{$file}, " $file\n";
+	}
+	print OUT "\n";
+}
+
+# Create one file blob
+sub fileblob
+{
+	my ($filename, $crlfmode, $mark) = @_;
+
+	# Import the file
+	print OUT "progress Importing $filename\nblob\nmark :$mark\n";
+	open FILE, '<', $filename or die "Cannot read $filename\n ";
+	binmode FILE;
+	my ($size, $mtime) = (stat(FILE))[7,9];
+	my $file;
+	read FILE, $file, $size;
+	close FILE;
+	$file =~ s/\r\n/\n/g if $crlfmode;
+	print OUT "data ", length($file), "\n", $file, "\n";
+
+	return $time;
+}
+
+__END__
+
+=pod
+
+=head1 EXAMPLES
+
+B<import-directories.perl> F<project.import>
+
+=head1 AUTHOR
+
+Copyright 2008-2009 Peter Krefting E<lt>peter@softwolves.pp.se>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation.
+
+=cut
-- 
1.6.3.3

^ permalink raw reply related

* Re: [PATCH] git-bisect: call the found commit "*the* first bad commit"
From: Junio C Hamano @ 2009-08-26  9:05 UTC (permalink / raw)
  To: Nanako Shiraishi; +Cc: git
In-Reply-To: <20090826173850.6117@nanako3.lavabit.com>

Nanako Shiraishi <nanako3@lavabit.com> writes:

> .. as we learned in the school ;-)

Thanks.

Is it "learned in school", or do you also need "*the*" there?

;-)

^ permalink raw reply

* Re: [PATCH v3] Add script for importing bits-and-pieces to Git.
From: Peter Krefting @ 2009-08-26  9:08 UTC (permalink / raw)
  To: git
In-Reply-To: <20090826090426.D6C73189B12@perkele>

Peter Krefting:

> This version contains updated documentation, trying to address the
> points raised by Junio. It also fixes a compile error that snuck in
> the v2 patch.

No it doesn't. I seem to have sent out v2 again under a new name. Sorry for 
the noise :-)

-- 
\\// Peter - http://www.softwolves.pp.se/

^ permalink raw reply

* [PATCH v3.1] Add script for importing bits-and-pieces to Git.
From: Peter Krefting @ 2009-08-24 17:09 UTC (permalink / raw)
  To: git

Allows the user to import version history that is stored in bits and
pieces in the file system, for instance snapshots of old development
trees, or day-by-day backups. A configuration file is used to
describe the relationship between the different files and allow
describing branches and merges, as well as authorship and commit
messages.

Output is created in a format compatible with git-fast-import.

Full documentation is provided inline in perldoc format.

Signed-off-by: Peter Krefting <peter@softwolves.pp.se>
---
This version contains updated documentation, trying to address the
points raised by Junio. It also fixes a compile error that snuck in
the v2 patch.

 contrib/fast-import/import-directories.perl |  359 +++++++++++++++++++++++++++
 1 files changed, 359 insertions(+), 0 deletions(-)
 create mode 100755 contrib/fast-import/import-directories.perl

diff --git a/contrib/fast-import/import-directories.perl b/contrib/fast-import/import-directories.perl
new file mode 100755
index 0000000..a5429d3
--- /dev/null
+++ b/contrib/fast-import/import-directories.perl
@@ -0,0 +1,359 @@
+#!/usr/bin/perl -w
+#
+# Copyright 2008-2009 Peter Krefting <peter@softwolves.pp.se>
+#
+# ------------------------------------------------------------------------
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# ------------------------------------------------------------------------
+
+=pod
+
+=head1 NAME
+
+import-directories - Import bits and pieces to Git.
+
+=head1 SYNOPSIS
+
+B<import-directories.perl> F<configfile>
+
+=head1 DESCRIPTION
+
+Script to import arbitrary projects version controlled by the "copy the
+source directory to a new location and edit it there"-version controlled
+projects into version control. Handles projects with arbitrary branching
+and version trees, taking a file describing the inputs and generating a
+file compatible with the L<git-fast-import(1)> format.
+
+=head1 CONFIGURATION FILE
+
+=head2 Format
+
+The configuration file is based on the standard I<.ini> format.
+
+ ; Comments start with semi-colons
+ [section]
+ key=value
+
+Unlike the git-config format, no quoting characters are allowed, all
+section and key names are case-sensitive and whitespace is preserved
+as-is. For example:
+
+ key1 =value1
+ key2= value2
+
+Here the first key is "key1 " (note the trailing white-space) and the
+second value is " value2" (note the leading white-space). Keys cannot
+contain equal signs ("=").
+
+=head2 Global configuration
+
+Global configuration is done in the B<[config]> section, which should be
+the first section in the file. Configuration can be changed by
+repeating configuration sections later on.
+
+ [config]
+ ; configure conversion of CRLFs. "convert" means that all CRLFs
+ ; should be converted into LFs (suitable for the core.autocrlf
+ ; setting set to true in Git). "none" means that all data is
+ ; treated as binary.
+ crlf=convert
+
+=head2 Revision configuration
+
+Each revision that is to be imported is described in three
+sections. Revisions should be defined in topological order, so
+that a revision's parent has always been defined when a new revision
+is introduced. All the sections for one revision must be defined
+before defining the next revision.
+
+Each revision is assigned a unique numerical identifier. The
+numbers do not need to be consecutive, nor monotonically
+increasing.
+
+For instance, if your configuration file contains only the two
+revisions 4711 and 42, where 4711 is the initial commit, the
+only requirement is that 4711 is completely defined before 42.
+
+=pod
+
+=head3 Revision description section
+
+A section whose section name is just an integer gives meta-data
+about the revision.
+
+ [3]
+ ; author sets the author of the revisions
+ author=Peter Krefting <peter@softwolves.pp.se>
+ ; branch sets the branch that the revision should be committed to
+ branch=master
+ ; parent describes the revision that is the parent of this commit
+ ; (optional)
+ parent=1
+ ; merges describes a revision that is merged into this commit
+ ; (optional; can be repeated)
+ merges=2
+ ; selects one file to take the timestamp from
+ ; (optional; if unspecified, the most recent file from the .files
+ ;  section is used)
+ timestamp=3/source.c
+
+=head3 Revision contents section
+
+A section whose section name is an integer followed by B<.files>
+describe all the files included in this revision. If a file that
+was available previously is not included in this revision, it will
+be removed.
+
+If an on-disk revision is incomplete, you can point to files from
+a previous revision. There are no restriction as to where the source
+files are located, nor to the names of them.
+
+ [3.files]
+ ; the key is the path inside the repository, the value is the path
+ ; as seen from the importer script.
+ source.c=ver-3.00/source.c
+ source.h=ver-2.99/source.h
+ readme.txt=ver-3.00/introduction to the project.txt
+
+=head3 Revision commit message section
+
+A section whose section name is an integer followed by B<.message>
+gives the commit message. This section is read verbatim, up until
+the beginning of the next section. As such, a commit message may not
+contain a line that begins with an opening square bracket ("[") and
+ends with a closing square bracket ("]"), unless they are surrounded
+by whitespace or other characters.
+
+ [3.message]
+ Implement foobar.
+ ; trailing blank lines are ignored.
+
+=cut
+
+# Globals
+use strict;
+use integer;
+my $crlfmode = 0;
+my @revs;
+my (%revmap, %message, %files, %author, %branch, %parent, %merges, %time, %timesource);
+my $sectiontype = 0;
+my $rev = 0;
+my $mark = 1;
+
+# Check command line
+if ($#ARGV == -1 || $ARGV[0] =~ /^--?h/)
+{
+    exec('perldoc', $0);
+    exit 1;
+}
+
+# Open configuration
+my $config = $ARGV[0];
+open CFG, '<', $config or die "Cannot open configuration file \"$config\": ";
+
+# Open output
+my $output = $ARGV[1];
+open OUT, '>', $output or die "Cannot create output file \"$output\": ";
+binmode OUT;
+
+LINE: while (my $line = <CFG>)
+{
+	$line =~ s/\r?\n$//;
+	next LINE if $sectiontype != 4 && $line eq '';
+	next LINE if $line =~ /^;/;
+	my $oldsectiontype = $sectiontype;
+	my $oldrev = $rev;
+
+	# Sections
+	if ($line =~ m"^\[(config|(\d+)(|\.files|\.message))\]$")
+	{
+		if ($1 eq 'config')
+		{
+			$sectiontype = 1;
+		}
+		elsif ($3 eq '')
+		{
+			$sectiontype = 2;
+			$rev = $2;
+			# Create a new revision
+			die "Duplicate rev: $line\n " if defined $revmap{$rev};
+			print "Reading revision $rev\n";
+			push @revs, $rev;
+			$revmap{$rev} = $mark ++;
+			$time{$revmap{$rev}} = 0;
+		}
+		elsif ($3 eq '.files')
+		{
+			$sectiontype = 3;
+			$rev = $2;
+			die "Revision mismatch: $line\n " unless $rev == $oldrev;
+		}
+		elsif ($3 eq '.message')
+		{
+			$sectiontype = 4;
+			$rev = $2;
+			die "Revision mismatch: $line\n " unless $rev == $oldrev;
+		}
+		else
+		{
+			die "Internal parse error: $line\n ";
+		}
+		next LINE;
+	}
+
+	# Parse data
+	if ($sectiontype != 4)
+	{
+		# Key and value
+		if ($line =~ m"^(.*)=(.*)$")
+		{
+			my ($key, $value) = ($1, $2);
+			# Global configuration
+			if (1 == $sectiontype)
+			{
+				if ($key eq 'crlf')
+				{
+					$crlfmode = 1, next LINE if $value eq 'convert';
+					$crlfmode = 0, next LINE if $value eq 'none';
+				}
+				die "Unknown configuration option: $line\n ";
+			}
+			# Revision specification
+			if (2 == $sectiontype)
+			{
+				my $current = $revmap{$rev};
+				$author{$current} = $value, next LINE if $key eq 'author';
+				$branch{$current} = $value, next LINE if $key eq 'branch';
+				$parent{$current} = $value, next LINE if $key eq 'parent';
+				$timesource{$current} = $value, next LINE if $key eq 'timestamp';
+				push(@{$merges{$current}}, $value), next LINE if $key eq 'merges';
+				die "Unknown revision option: $line\n ";
+			}
+			# Filespecs
+			if (3 == $sectiontype)
+			{
+				# Add the file and create a marker
+				die "File not found: $line\n " unless -f $value;
+				my $current = $revmap{$rev};
+				${$files{$current}}{$key} = $mark;
+				my $time = &fileblob($value, $crlfmode, $mark ++);
+
+				# Update revision timestamp if more recent than other
+				# files seen, or if this is the file we have selected
+				# to take the time stamp from using the "timestamp"
+				# directive.
+				if ((defined $timesource{$current} && $timesource{$current} eq $value)
+				    || $time > $time{$current})
+				{
+					$time{$current} = $time;
+				}
+			}
+		}
+		else
+		{
+			die "Parse error: $line\n ";
+		}
+	}
+	else
+	{
+		# Commit message
+		my $current = $revmap{$rev};
+		if (defined $message{$current})
+		{
+			$message{$current} .= "\n";
+		}
+		$message{$current} .= $line;
+	}
+}
+close CFG;
+
+# Start spewing out data for git-fast-import
+foreach my $commit (@revs)
+{
+	# Progress
+	print OUT "progress Creating revision $commit\n";
+
+	# Create commit header
+	my $mark = $revmap{$commit};
+
+	# Branch and commit id
+	print OUT "commit refs/heads/", $branch{$mark}, "\nmark :", $mark, "\n";
+
+	# Author and timestamp
+	die "No timestamp defined for $commit (no files?)\n" unless defined $time{$mark};
+	print OUT "committer ", $author{$mark}, " ", $time{$mark}, " +0100\n";
+
+	# Commit message
+	die "No message defined for $commit\n" unless defined $message{$mark};
+	my $message = $message{$mark};
+	$message =~ s/\n$//; # Kill trailing empty line
+	print OUT "data ", length($message), "\n", $message, "\n";
+
+	# Parent and any merges
+	print OUT "from :", $revmap{$parent{$mark}}, "\n" if defined $parent{$mark};
+	if (defined $merges{$mark})
+	{
+		foreach my $merge (@{$merges{$mark}})
+		{
+			print OUT "merge :", $revmap{$merge}, "\n";
+		}
+	}
+
+	# Output file marks
+	print OUT "deleteall\n"; # start from scratch
+	foreach my $file (sort keys %{$files{$mark}})
+	{
+		print OUT "M 644 :", ${$files{$mark}}{$file}, " $file\n";
+	}
+	print OUT "\n";
+}
+
+# Create one file blob
+sub fileblob
+{
+	my ($filename, $crlfmode, $mark) = @_;
+
+	# Import the file
+	print OUT "progress Importing $filename\nblob\nmark :$mark\n";
+	open FILE, '<', $filename or die "Cannot read $filename\n ";
+	binmode FILE;
+	my ($size, $mtime) = (stat(FILE))[7,9];
+	my $file;
+	read FILE, $file, $size;
+	close FILE;
+	$file =~ s/\r\n/\n/g if $crlfmode;
+	print OUT "data ", length($file), "\n", $file, "\n";
+
+	return $mtime;
+}
+
+__END__
+
+=pod
+
+=head1 EXAMPLES
+
+B<import-directories.perl> F<project.import>
+
+=head1 AUTHOR
+
+Copyright 2008-2009 Peter Krefting E<lt>peter@softwolves.pp.se>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation.
+
+=cut
-- 
1.6.3.3

^ permalink raw reply related

* Re: [PATCH] import-tars: Allow per-tar author and commit message.
From: Peter Krefting @ 2009-08-26  9:17 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Nanako Shiraishi, Sam Vilain, Git Mailing List
In-Reply-To: <7v8wh7pumr.fsf@alter.siamese.dyndns.org>

Junio C Hamano:

> And the switch could be "--metainfo=<ext>", so that people can choose to 
> use other extensions, e.g. with "--metainfo=info" file.tar.info would be 
> read for descriptions.

That's a good idea. I just made a simple "-m" switch to enable the new code. 
I'll change it into a "--metainfo" and post an updated patch later.

-- 
\\// Peter - http://www.softwolves.pp.se/

^ permalink raw reply

* Newbie / git / gitosis question
From: Howard Miller @ 2009-08-26  9:27 UTC (permalink / raw)
  To: git

I've been working away at Gitosis and it's mostly fair enough but
there's one bit that's unclear to me...

git push origin master:refs/heads/master

Would somebody kindly explain (or point to docs) what
refs/heads/master means? How is this different from just 'git push
origin master' or even 'git push origin master:master'?

Any insights much appreciated.

^ permalink raw reply

* Re: Newbie / git / gitosis question
From: Michael Wookey @ 2009-08-26  9:38 UTC (permalink / raw)
  To: Howard Miller; +Cc: git
In-Reply-To: <26ae428a0908260227k7ac6aeden9a4eae7ee95d4d45@mail.gmail.com>

2009/8/26 Howard Miller <howard@e-learndesign.co.uk>:
> I've been working away at Gitosis and it's mostly fair enough but
> there's one bit that's unclear to me...
>
> git push origin master:refs/heads/master
>
> Would somebody kindly explain (or point to docs) what
> refs/heads/master means? How is this different from just 'git push
> origin master' or even 'git push origin master:master'?
>
> Any insights much appreciated.

You might find some insight here - http://progit.org/book/ch9-5.html

^ permalink raw reply

* Re: Newbie / git / gitosis question
From: Howard Miller @ 2009-08-26  9:46 UTC (permalink / raw)
  To: Michael Wookey; +Cc: git
In-Reply-To: <d2e97e800908260238p28bd6d27o6377f395df32b03c@mail.gmail.com>

Mmm...

I think I see what's happening  - vaguely - but I'm not sure I understand why!

Why does gitosis require you to be this specific? Why can't I just do
a 'straight' push?

Howard

2009/8/26 Michael Wookey <michaelwookey@gmail.com>:
> 2009/8/26 Howard Miller <howard@e-learndesign.co.uk>:
>> I've been working away at Gitosis and it's mostly fair enough but
>> there's one bit that's unclear to me...
>>
>> git push origin master:refs/heads/master
>>
>> Would somebody kindly explain (or point to docs) what
>> refs/heads/master means? How is this different from just 'git push
>> origin master' or even 'git push origin master:master'?
>>
>> Any insights much appreciated.
>
> You might find some insight here - http://progit.org/book/ch9-5.html
>

^ permalink raw reply

* Re: [PATCH] upload-pack: add a trigger for post-upload-pack hook
From: Johannes Schindelin @ 2009-08-26 10:06 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jeff King, Tom Werner, Tom Preston-Werner, git
In-Reply-To: <7vr5uzeyl7.fsf@alter.siamese.dyndns.org>

Hi,

On Wed, 26 Aug 2009, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> > On Tue, 25 Aug 2009, Junio C Hamano wrote:
> >
> >> and if one of the primary reason for this new hook is statistics, it 
> >> would be useful to see the number of bytes given, where the 
> >> fetch-pack came from, and if we are using git-daemon virtual hosting 
> >> which of our domain served the request.
> >
> > Certainly those are possible add-on patches, but would you require 
> > them to be in the same commit?
> 
> I was merely responding to the "what else would be useful" question posed
> by Peff.

Sure.

> Did you get an impression that I was saying "you must add these 
> otherwise I'll reject the patch"?

Well, I got the impression that you'd not accept the patch without 
additional information given by the hook, and I got the impression that 
Tom would decide as a consequence to rather live with his eternal fork 
instead of working on getting this patch included.

> It might make sense to define the external interface to be "information 
> is given through the standard input of the hook, formatted in YAML, and 
> here are the initial set of items that may be fed", so that we do not 
> have to worry about the details too much.

Hmm.  You bring up YAML a few times recently, it seems, but I think this 
is not what you are meaning.  In this case, you'd need to have a simple 
enquiry system that asks for some information and receives it as a 
response.

But I would find it utterly overengineered if upload-pack would support 
something as complicated as that.  IMHO either upload-pack knows already 
about the information, or the script has to try to discover it using Git 
commands itself.

My conclusion: I _think_ it would make sense to pass the name of the pack 
file(s) created by upload-pack to the hook, or something similar, but 
nothing more.  Well, _maybe_ the byte count of the protocol exchange and 
the IP.  But nothing that requires calculations.

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH] git-bisect: call the found commit "*the* first bad commit"
From: Johannes Schindelin @ 2009-08-26 10:08 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Nanako Shiraishi, git
In-Reply-To: <7vfxbfeyh5.fsf@alter.siamese.dyndns.org>

Hi,

On Wed, 26 Aug 2009, Junio C Hamano wrote:

> Nanako Shiraishi <nanako3@lavabit.com> writes:
> 
> > .. as we learned in the school ;-)
> 
> Thanks.
> 
> Is it "learned in school", or do you also need "*the*" there?
> 
> ;-)

Well, I learnt at school that it is "learnt" and "at school"...

double ;-)

Ciao,
Dscho

^ permalink raw reply

* [RFC] Use a 16-tree instead of a 256-tree for storing notes
From: Johan Herland @ 2009-08-26 10:31 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: git, gitster, trast, tavestbo, git, chriscool, spearce
In-Reply-To: <200908010436.57480.johan@herland.net>

The 256-tree structure is considerably faster than storing all entries in a
hash_map. Also, the memory consumption of the 256-tree structure is lower
than the hash_map, provided that you're only loading a few notes from a
"properly fanned-out" notes tree (i.e. 100000 notes in a 2/2/36 structure).
However, in the worst case (loading all 100000 notes), the memory usage of
the 256-tree structure (62.64 MB) is significantly worse than the hash_map
approach (10.25 MB).

This patch modifies the 256-tree structure into a 16-tree structure. This
significantly improves the memory situation. The result uses less memory
than both the 256-tree structure, and the hash_map approach, with a worst
case usage of 8.54 MB. Additionally, it seems to slightly improve the
runtime performance as well (probably because of the improved memory usage).

In conclusion, this is faster and smaller than all the previous drafts.

$ ./test_performance.sh
Timing 100 reps of 'git log -n 10 refs/heads/master >/dev/null' at fanout level 0...
15.05user 1.44system 0:16.59elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+782490minor)pagefaults 0swaps

Timing 100 reps of 'git log -n 10 refs/heads/master >/dev/null' at fanout level 1...
0.68user 0.17system 0:00.87elapsed 98%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+99585minor)pagefaults 0swaps

Timing 100 reps of 'git log -n 10 refs/heads/master >/dev/null' at fanout level 2...
0.41user 0.17system 0:00.61elapsed 97%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+94084minor)pagefaults 0swaps

Signed-off-by: Johan Herland <johan@herland.net>
---

Hi,

This patch goes on top of the 256-tree RFC I sent earlier.

If nobody suggests further improvements, this patch will be
included in the next iteration of the jh/notes topic.


Have fun! :)

...Johan


 notes.c |   26 ++++++++++++++------------
 1 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/notes.c b/notes.c
index 9282b16..32b1e01 100644
--- a/notes.c
+++ b/notes.c
@@ -7,9 +7,9 @@
 #include "tree-walk.h"
 
 /*
- * Use a non-balancing simple 256-tree structure with struct int_node as
+ * Use a non-balancing simple 16-tree structure with struct int_node as
  * internal nodes, and struct leaf_node as leaf nodes. Each int_node has a
- * 256-array of pointers to its children
+ * 16-array of pointers to its children
  * The bottom 2 bits of each pointer is used to identify the pointer type
  * - ptr & 3 == 0 - NULL pointer, assert(ptr == NULL)
  * - ptr & 3 == 1 - pointer to next internal node - cast to struct int_node *
@@ -21,18 +21,18 @@
  *
  * To add a leaf_node:
  * 1. Start at the root node, with n = 0
- * 2. Use the nth byte of the key as an index into a:
- *    - If NULL, store the tweaked pointer directly into a[n]
- *    - If an int_node, recurse into that node and increment n
- *    - If a leaf_node:
+ * 2. Use the nth nibble of the key as an index into a:
+ *    - If a[n] is NULL, store the tweaked pointer directly into a[n]
+ *    - If a[n] is an int_node, recurse into that node and increment n
+ *    - If a[n] is a leaf_node:
  *      1. Check if they're equal, and handle that (abort? overwrite?)
  *      2. Create a new int_node, and store both leaf_nodes there
  *      3. Store the new int_node into a[n].
  *
  * To find a leaf_node:
  * 1. Start at the root node, with n = 0
- * 2. Use the nth byte of the key as an index into a:
- *    - If an int_node, recurse into that node and increment n
+ * 2. Use the nth nibble of the key as an index into a:
+ *    - If a[n] is an int_node, recurse into that node and increment n
  *    - If a leaf_node with matching key, return leaf_node (assert note entry)
  *    - If a matching subtree entry, unpack that subtree entry (and remove it);
  *      restart search at the current level.
@@ -42,7 +42,7 @@
  *        subtree entry (and remove it); restart search at the current level.
  */
 struct int_node {
-	void *a[256];
+	void *a[16];
 };
 
 /*
@@ -79,11 +79,13 @@ static int initialized;
 static void load_subtree(struct leaf_node *subtree, struct int_node *node,
 		unsigned int n);
 
+#define GET_NIBBLE(n, sha1) (((sha1[n >> 1]) >> ((n & 0x01) << 2)) & 0x0f)
+
 static struct leaf_node *note_tree_find(struct int_node *tree, unsigned char n,
 		const unsigned char *key_sha1)
 {
 	struct leaf_node *l;
-	unsigned char i = key_sha1[n];
+	unsigned char i = GET_NIBBLE(n, key_sha1);
 	void *p = tree->a[i];
 
 	switch(GET_PTR_TYPE(p)) {
@@ -138,7 +140,7 @@ static int note_tree_insert(struct int_node *tree, unsigned char n,
 	struct int_node *new_node;
 	const struct leaf_node *l;
 	int ret;
-	unsigned char i = entry->key_sha1[n];
+	unsigned char i = GET_NIBBLE(n, entry->key_sha1);
 	void *p = tree->a[i];
 	assert(GET_PTR_TYPE(entry) == PTR_TYPE_NULL);
 	switch(GET_PTR_TYPE(p)) {
@@ -211,7 +213,7 @@ static void load_subtree(struct leaf_node *subtree, struct int_node *node,
 		     sha1_to_hex(subtree->val_sha1));
 
 	prefix_len = subtree->key_sha1[19];
-	assert(prefix_len >= n);
+	assert(prefix_len * 2 >= n);
 	memcpy(commit_sha1, subtree->key_sha1, prefix_len);
 	while (tree_entry(&desc, &entry)) {
 		int len = get_sha1_hex_segment(entry.path, strlen(entry.path),
-- 
1.6.4.304.g1365c.dirty

^ permalink raw reply related

* Re: Linus' sha1 is much faster!
From: Pádraig Brady @ 2009-08-26 11:39 UTC (permalink / raw)
  To: Nicolas Pitre
  Cc: Linus Torvalds, John Tapsell, Bryan Donlan, Bug-coreutils,
	Git Mailing List, Brandon Casey, Junio C Hamano, Paul Kocher
In-Reply-To: <alpine.LFD.2.00.0908162151180.6044@xanadu.home>

Nicolas Pitre wrote:
> On Sat, 15 Aug 2009, Linus Torvalds wrote:
> 
>> (Heh. Looking at that, I probably should move the 'size' field first, 
>> since that would have different alignment rules, and the struct would be 
>> more tightly packed that way, and initialize better).
> 
> I was about to suggest (i.e. post) a patch for that.  This is indeed a 
> good idea.
> 
>> Afaik, none of the actual code remains (the mozilla SHA1 thing did the 
>> wrong thing for performance even for just the final bytes, and did those a 
>> byte at a time etc, so I rewrote even the trivial SHA1_Final parts).
> 
> Maybe a patch adding a proper header with the actual license would be a 
> good idea too.

So have you decided on a final licence,
and if so update the headers accordingly?

cheers!
Pádraig.

^ permalink raw reply

* Re: Newbie / git / gitosis question
From: Graham Perks @ 2009-08-26 11:54 UTC (permalink / raw)
  To: Howard Miller; +Cc: git
In-Reply-To: <26ae428a0908260227k7ac6aeden9a4eae7ee95d4d45@mail.gmail.com>

On Aug 26, 2009, at 4:27 AM, Howard Miller wrote:
> there's one bit that's unclear to me...
>
> git push origin master:refs/heads/master
>
> Would somebody kindly explain (or point to docs) what
> refs/heads/master means?

I wish somehow these refs would be hidden so newbies like me and  
everyone I introduce to git didn't have to know about them. They feel  
like an "advanced concept", some internal syntax that 99% of users  
shouldn't need to know about. When I see a refspec in the help pages  
my eyes glaze over!

Graham.

^ 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