Git development
 help / color / mirror / Atom feed
* [PATCH] Implement git-quiltimport
From: Eric W. Biederman @ 2006-05-16 16:51 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git


Importing a quilt patch series into git is not very difficult
but parsing the patch descriptions and all of the other
minutia take a bit of effort to get right, so this automates it.

Since git and quilt complement each other it makes sense
to make it easy to go back and forth between the two.

---

Eric

 Documentation/git-quiltimport.txt |   50 +++++++++++++++++++++
 Makefile                          |    2 -
 git-quiltimport.sh                |   88 +++++++++++++++++++++++++++++++++++++
 3 files changed, 139 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/git-quiltimport.txt
 create mode 100644 git-quiltimport.sh

2256c7e9b3913732a5c3a2e54cdea20fc951b76d
diff --git a/Documentation/git-quiltimport.txt b/Documentation/git-quiltimport.txt
new file mode 100644
index 0000000..8ea20eb
--- /dev/null
+++ b/Documentation/git-quiltimport.txt
@@ -0,0 +1,50 @@
+git-quiltimport(1)
+================
+
+NAME
+----
+git-quiltimport - Applies a quilt patchset onto the current branch
+
+
+SYNOPSIS
+--------
+[verse]
+'git-quiltimport' [--author <author>] [--patches <dir>]
+
+
+DESCRIPTION
+-----------
+Applies a quilt patchset onto the current git branch, preserving
+the patch boundaries, patch order, and patch descriptions present
+in the quilt patchset.
+
+For each patch the code attempts to extract the author from the 
+patch description.  If that fails it falls back to the author
+specified with --author.  If the --author flag was not given
+the the author is recorded as unknown.
+
+The patch name is preserved as the 1 line subject in the git
+description.
+
+OPTIONS
+-------
+--author Author Name <Author Email>::
+	The author name and email address to use when no author
+	information can be found in the patch description.
+
+--patches <dir>::
+	The directory to find the quilt patches and the
+	quilt series file.
+
+Author
+------
+Written by Eric Biederman <ebiederm@lnxi.com>
+
+Documentation
+--------------
+Documentation by Eric Biederman <ebiederm@lnxi.com>
+
+GIT
+---
+Part of the gitlink:git[7] suite
+
diff --git a/Makefile b/Makefile
index 37fbe78..1f4abe6 100644
--- a/Makefile
+++ b/Makefile
@@ -125,7 +125,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-grep.sh \
-	git-lost-found.sh
+	git-lost-found.sh git-quiltimport.sh
 
 SCRIPT_PERL = \
 	git-archimport.perl git-cvsimport.perl git-relink.perl \
diff --git a/git-quiltimport.sh b/git-quiltimport.sh
new file mode 100644
index 0000000..534be82
--- /dev/null
+++ b/git-quiltimport.sh
@@ -0,0 +1,88 @@
+#!/bin/sh
+USAGE='--author <author> --patches </path/to/quilt/patch/directory>'
+SUBDIRECTORY_ON=Yes
+. git-sh-setup
+
+quilt_author="Unknown <unknown>"
+while case "$#" in 0) break;; esac
+do
+	case "$1" in
+	--au=*|--aut=*|--auth=*|--autho=*|--author=*)
+		quilt_author=$(expr "$1" : '-[^=]*\(.*\)')
+		shift
+		;;
+	
+	--au|--aut|--auth|--autho|--author)
+		case "$#" in 1) usage ;; esac
+		shift
+		quilt_author="$1"
+		shift
+		;;
+
+	--pa=*|--pat=*|--patc=*|--patch=*|--patche=*|--patches=*)
+		QUILT_PATCHES=$(expr "$1" : '-[^=]*\(.*\)')
+		shift
+		;;
+	
+	--pa|--pat|--patc|--patch|--patche|--patches)
+		case "$#" in 1) usage ;; esac
+		shift
+		QUILT_PATCHES="$1"
+		shift
+		;;
+	
+	*)
+		break
+		;;
+	esac
+done
+
+# Quilt Author
+quilt_author_name=$(expr "z$quilt_author" : 'z\(.*[^ ]\) *<.*') &&
+quilt_author_email=$(expr "z$quilt_author" : '.*\(<.*\)') &&
+test '' != "$quilt_author_name" &&
+test '' != "$quilt_author_email" ||
+die "malformatted --author parameter"
+
+# Quilt patch directory
+: ${QUILT_PATCHES:=patches}
+if ! [ -d "$QUILT_PATCHES" ] ; then
+	echo "The \"$QUILT_PATCHES\" directory does not exist."
+	exit 1
+fi
+
+# Temporay directories
+tmp_dir=.dotest
+tmp_msg="$tmp_dir/msg"
+tmp_patch="$tmp_dir/patch"
+tmp_info="$tmp_dir/info"
+
+
+# Find the intial commit
+commit=$(git-rev-parse HEAD)
+
+mkdir $tmp_dir || exit 2
+cat "$QUILT_PATCHES/series" | grep -v '^#' | 
+while read line ; do 
+	echo $line
+	(cat $QUILT_PATCHES/$line | git-mailinfo "$tmp_msg" "$tmp_patch" > "$tmp_info") || exit 3
+	
+	# Parse the author information
+	export GIT_AUTHOR_NAME=$(sed -ne 's/Author: //p' "$tmp_info")
+	export GIT_AUTHOR_EMAIL=$(sed -ne 's/Email: //p' "$tmp_info")
+	if [ -z "$GIT_AUTHOR_EMAIL" ] ; then
+		GIT_AUTHOR_NAME=$quilt_author_name
+		GIT_AUTHOR_EMAIL=$quilt_author_email
+	fi
+	export GIT_AUTHOR_DATE=$(sed -ne 's/Date: //p' "$tmp_info")
+	export SUBJECT=$(sed -ne 's/Subject: //p' "$tmp_info")
+	if [ -z "$SUBJECT" ] ; then
+		SUBJECT=$(echo $line | sed -e 's/.patch$//')
+	fi
+
+	git-apply --index -C1 "$tmp_patch" &&
+	tree=$(git-write-tree) &&
+	commit=$((echo "$SUBJECT"; echo; cat "$tmp_msg") | git-commit-tree $tree -p $commit) &&
+	git-update-ref HEAD $commit || exit 4
+done
+rm -rf $tmp_dir || exit 5
-- 
1.3.2.g2256

^ permalink raw reply related

* Re: [PATCH] Update the documentation for git-merge-base
From: Linus Torvalds @ 2006-05-16 16:32 UTC (permalink / raw)
  To: Fredrik Kuivinen; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.64.0605160821570.3866@g5.osdl.org>



On Tue, 16 May 2006, Linus Torvalds wrote:
> 
> I don't think you can be more specific, or do a better job. The definition 
> of "most recent" is arbitrary, of course - and going by commit date is 
> just _one_ way to order them, but it happens to be an easy one, and one 
> that is as good as any other choice.

Side note: since LCA's are (by definition) never going to have a direct 
graph relationship, there is obviously no ordering enforced by the graph 
itself. So they're all unordered in the graph sense, but you could use 
other measures of "distance" in the graph.

Example other orderings that we _could_ do, and I considered (some purely 
graph based, others based on content):

 - order by number of commits between the LCA and the two commits that we 
   are trying to find the LCA for (the "tips").
 - order by diff size between the LCA and the tips
 - order by lack of conflicts between the LCA and the tips.

however, none of the alternate orderings really seem to make a lot of 
sense.

The date-based one trumps them all by being straightforward and simple to 
both implement and explain. And iirc, I actually verified that it happened 
to pick the "better" one for at least one of my tests when using the old 
stupid straigth three-way merge, so I think it was actually objectively a 
good measure at least once.

Anybody who cares can obviously always just do "git-merge-base --all" and 
do their own sorting for the (relatively unlikely) case that you get more 
than one parent.

Anyway, just out of interest I just did some statistics using some shell 
scripts:

 - For the current kernel tree, of 1857 merges, only 17 had more than one 
   merge base (and none had more than two):

   1840 o
     17 oo

 - In contrast, for git (current master branch), the numbers are 35 out of 
   540, and there are lots of merges with many LCA's:

    505 o
     15 oo
     13 ooo
      2 oooo
      3 ooooo
      2 ooooooo

I think the difference is that Junio does a lot of these branches where he 
keeps on pulling from them, and never syncs back (which is a great 
workflow). In contrast, the kernel tends to try to avoid that because the 
history gets messy enough as it is ;)

Anyway, the two commits that apparently have seven (!) LCA's in the git 
tree should probably be checked out. They are probably a good thing to see 
if git-merge-base really _really_ does the right thing, and whether they 
really are true LCA's.

They are commits ad0b46bf.. and e6a933bd.. respectively.

		Linus

^ permalink raw reply

* Re: [PATCH] Update the documentation for git-merge-base
From: Linus Torvalds @ 2006-05-16 15:32 UTC (permalink / raw)
  To: Fredrik Kuivinen; +Cc: Junio C Hamano, git
In-Reply-To: <20060516065452.GA5540@c165.ib.student.liu.se>



On Tue, 16 May 2006, Fredrik Kuivinen wrote:
> 
> By "least" I mean the following:
> 
> C is a least common ancestor of A and B if:
> 
> * C is a common ancestor of A and B, and
> * for every other common ancestor D (different from C) of A and B, C
>   is not reacheable from D.

Yes, git-merge-base should always return a least common ancestor, never 
anything less. The only question is what happens when there are multiple 
LCA commits.

In fact, even in that case git-merge-base will have a pretty strong 
specification:

  "git-merge-base with the '--all' flag will return the complete set of
   least common ancestors, sorted by most recent (as defined purely by
   the commit date order, not any graph ordering) first.

   Without the '--all' flag, it will return just one LCA commit (the most 
   recent one, by the same date-based definition).

   In the case two or more LCA commits have exactly the same committer 
   date, the ordering between them is arbitrary"

I don't think you can be more specific, or do a better job. The definition 
of "most recent" is arbitrary, of course - and going by commit date is 
just _one_ way to order them, but it happens to be an easy one, and one 
that is as good as any other choice.

Of course, the defined ordering probably really matters only for the case 
where we return just one LCA out of many, but it's nice to be able to tell 
what the order will be even for the multi-commit case.

> There are two examples at the top of the source. In the first one a
> least common ancestor is returned. As I interpret the second one, it
> is an example of how the old algorithm without the postprocessing step
> produced a common ancestor which is not least.

Correct. We used to occasionally get it wrong, and return a common 
ancestor that wasn't least.

> Am I wrong? Do we have any cases where the current merge-base
> algorithm gives us common ancestors which are not least?

Modulo bugs, no. And I don't think there are any bugs in that respect.

		Linus

^ permalink raw reply

* Re: gateway status?
From: Jakub Narebski @ 2006-05-16 13:54 UTC (permalink / raw)
  To: git
In-Reply-To: <Pine.LNX.4.62.0605151122500.29452@qynat.qvtvafvgr.pbz>

David Lang wrote:

> I seem to remember seeing discussion of gateways to cvs/svn that would let 
> a project use a git repository and allow clients to use cvs/svn clients to 
> retreive data.
> 
> am I remembering correctly, and are these tools ready for production use? 


Eric Wong <normalperson@yhbt.net> wrote:
in "[0/2 PATCH] git-svn 1.0.0 release" thread
http://permalink.gmane.org/gmane.comp.version-control.git/19644

> It's been very solid for a long time now.  I haven't run into
> any problems with it myself in a while, and no critical bugs
> that I know of exist.  Labeling it 1.0.0 may make it look
> less scary to new users :)

So I guess yes, they are.


P.S. IIRC git-cvsserver is used as temporary "Git plugin" for Eclipse, and
there are some problems with that due to the cvs client/server
implementation in Eclipse.

-- 
Jakub Narebski
Warsaw, Poland

^ permalink raw reply

* Re: [PATCH] commit: allow --pretty= args to be abbreviated
From: Eric Wong @ 2006-05-16 13:25 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vac9jhv66.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano <junkio@cox.net> wrote:
> Eric Wong <normalperson@yhbt.net> writes:
> 
> > Unlike the original one, this one only does prefix matches, so
> > you can't do --pretty=er anymore :)
> 
> Sounds good.  But then you know how long the unique prefix
> are for each candidate, so wouldn't this rather be redundant, I
> wonder?

I just copied the idea for the 2nd for loop from gitopt, since it makes
maintenance easier when there are lots of possibilities.  We only have 6
(soon 7) to worry about for --pretty= here, so hard coding lengths
probably makes more sense.

> > +
> > +	/* look for abbreviations */
> > +	len = strlen(arg);
> > +	found = -1;
> > +	for (i = 0; i < ARRAY_SIZE(cmt_fmts); i++) {
> > +		if (!strncmp(cmt_fmts[i].n, arg, len)) {
> > +			if (found >= 0)
> > +				die("invalid --pretty format: %s", arg);
> > +			found = i;
> > +		}
> > +	}
> > +	if (found >= 0)
> > +		return cmt_fmts[found].v;
> > +	die("invalid --pretty format: %s", arg);
> >  }
> 
> It would probably be better to say "ambiguous" not "invalid" in
> the die() message.

Yes, but only one die() message left now :)

-- 
Eric Wong

>From nobody Mon Sep 17 00:00:00 2001
From: Eric Wong <normalperson@yhbt.net>
Date: Sun, 14 May 2006 17:20:46 -0700
Subject: [PATCH] commit: allow --pretty= args to be abbreviated

Unlike the original one, this one only does prefix matches, so
you can't do --pretty=er anymore :)

This one really works with and without the gitopt changes.

Signed-off-by: Eric Wong <normalperson@yhbt.net>

---

 commit.c |   38 ++++++++++++++++++++++++--------------
 1 files changed, 24 insertions(+), 14 deletions(-)

044dff6523c25e173eb7fb1c5d5c8a8e6ada8fdc
diff --git a/commit.c b/commit.c
index 2717dd8..4a26070 100644
--- a/commit.c
+++ b/commit.c
@@ -22,23 +22,33 @@ struct sort_node
 
 const char *commit_type = "commit";
 
+struct cmt_fmt_map {
+	const char *n;
+	size_t cmp_len;
+	enum cmit_fmt v;
+} cmt_fmts[] = {
+	{ "raw",	1,	CMIT_FMT_RAW },
+	{ "medium",	1,	CMIT_FMT_MEDIUM },
+	{ "short",	1,	CMIT_FMT_SHORT },
+	{ "full",	5,	CMIT_FMT_FULL },
+	{ "fuller",	5,	CMIT_FMT_FULLER },
+	{ "oneline",	1,	CMIT_FMT_ONELINE },
+};
+
 enum cmit_fmt get_commit_format(const char *arg)
 {
-	if (!*arg)
+	int i;
+
+	if (!arg || !*arg)
 		return CMIT_FMT_DEFAULT;
-	if (!strcmp(arg, "=raw"))
-		return CMIT_FMT_RAW;
-	if (!strcmp(arg, "=medium"))
-		return CMIT_FMT_MEDIUM;
-	if (!strcmp(arg, "=short"))
-		return CMIT_FMT_SHORT;
-	if (!strcmp(arg, "=full"))
-		return CMIT_FMT_FULL;
-	if (!strcmp(arg, "=fuller"))
-		return CMIT_FMT_FULLER;
-	if (!strcmp(arg, "=oneline"))
-		return CMIT_FMT_ONELINE;
-	die("invalid --pretty format");
+	if (*arg == '=')
+		arg++;
+	for (i = 0; i < ARRAY_SIZE(cmt_fmts); i++) {
+		if (!strncmp(arg, cmt_fmts[i].n, cmt_fmts[i].cmp_len))
+			return cmt_fmts[i].v;
+	}
+
+	die("invalid --pretty format: %s", arg);
 }
 
 static struct commit *check_commit(struct object *obj,
-- 
1.3.2.g7d11

^ permalink raw reply related

* Re: Fwd: [OT] Re: Git via a proxy server?
From: Petr Vandrovec @ 2006-05-16 13:11 UTC (permalink / raw)
  To: Sam Song; +Cc: git
In-Reply-To: <20060516121356.11646.qmail@web32002.mail.mud.yahoo.com>

Sam Song wrote:
> Hello,
> 
> Petr Vandrovec <petr@vmware.com> wrote:
> 
>>Date:	Mon, 27 Feb 2006 00:35:00 +0100
>>From:	Petr Vandrovec <petr@vmware.com>
>>To:	Sergey Vlasov <vsu@altlinux.ru>
>>CC:	"Salyzyn, Mark" <mark_salyzyn@adaptec.com>,
>>	Kernel Mailing List 
>><linux-kernel@vger.kernel.org>
>>
>>>[snip]
>>>I have successfully used transconnect
>>>(http://sourceforge.net/projects/transconnect) for
>>>tunnelling git
>>>protocol through a HTTP proxy (squid in my case)
>>>supporting the CONNECT method.
>>>
>>>[snip] 
>>>Note: most HTTP proxy servers allow CONNECT method
>>>to a very limited range of ports, and 
>>>administrators will need to enable the git port
>>>(9418) explicitly.
>>>
>>
>>I know I'm coming kinda late, but I'm using:
>>
>>export GIT_PROXY_COMMAND=/usr/local/bin/proxy-cmd.sh
>>
>>and proxy-cmd.sh is just single-line command glued
>>from what I found available in /bin:
>>
>>#! /bin/bash
>>
>>(echo "CONNECT $1:$2 HTTP/1.0"; echo; cat ) | socket
>>
>>proxy.ourcompany.com 3128 | (read a; read a; cat )
>>
>>Replace socket's arguments 'proxy.ourcompany.com
>>3128' with your http proxy.  Fortunately our proxy
>>does not see anything wrong with git's port.
>>		Best regards,
>>			Petr Vandrovec
> 
> 
> With above usage on GIT_PROXY_COMMAND, I still have
> problem on connection with remote git repository.
> 
> I also tried setting http_proxy directly but the same
> result. It's first usage of git in our network. Well, 
> need I enable the git port 9418 at proxy server? Or 
> did I miss sth or what?

Yes.  Try running 'socket 192.168.40.99 80', and type
CONNECT 204.152.191.37:9418 HTTP/1.0
Proxy-Authorization: Basic <yoursecret,f.e.wget -d should reveal this to you>
<empty line>

You should get back user readable diagnostics what went wrong.  Yes, your admin 
must allow CONNECT method for target port 9418.

> I use git-2006-05-14.tar.gz package on FC3. 
> 
> Method I : Use GIT_PROXY_COMMAND
> 
> [root@sam u-boot]# git clone \
> git://www.denx.de/git/u-boot.git u-boot-denx.git
> 
> fatal: exec failed
> fetch-pack from 'git://www.denx.de/git/u-boot.git' 
> failed.

Is $GIT_PROXY_COMMAND executable? (just in case...)  Try 'strace -f git clone 
...', it should tell you what's going on.

> #! /bin/bash
> 
> (echo "CONNECT $1:$2 HTTP/1.0";echo;cat) | socket
> <um> <pwd> 192.168.40.99 80 | (read a;read a;cat)

What is '<um>' and '<pwd>' ?  socket just connects somewhere, so if you are 
supposed to use <username>:<pwd> to connect to your proxy, you must add 
Proxy-Authorization header yourself:

(echo "CONNECT $1:$2 HTTP/1.0";
  echo "Proxy-Authorization: Basic <base64encoded um:pwd>";
  echo;
  cat ) | socket 192.168.40.99 80 | (read a; read a; cat)

Best to test this is to start 'socket 192.168.40.99 80' from command line and 
then type these two lines above, plus one empty line.  You should get back '200 
OK', empty line, and then you can start communicating using git protocol - if 
you can do that...

> Method II : Use http_proxy directly
> 
> [root@sam u-boot]# export \
> http_proxy="http://<username>:<pwd>@192.168.40.99:80"
> [root@sam u-boot]# git clone \ 
> http://parisc-linux.org/git/linux-2.6.git/ parisc-2.6

As far as I can tell, http_proxy is ignored (Debian's git 1.3.2-1/cogito 0.17.2-1).
								Petr

^ permalink raw reply

* Re: gateway status?
From: Martin Langhoff @ 2006-05-16 13:09 UTC (permalink / raw)
  To: David Lang; +Cc: git
In-Reply-To: <Pine.LNX.4.62.0605151122500.29452@qynat.qvtvafvgr.pbz>

On 5/16/06, David Lang <dlang@digitalinsight.com> wrote:
> I seem to remember seeing discussion of gateways to cvs/svn that would let
> a project use a git repository and allow clients to use cvs/svn clients to
> retreive data.

David,

I suspect you might be thinking of git-cvsserver. The code has no
known bugs, but is has only seen limited use by in-house dev teams.

A good measure is to run an import of the current cvs project (I would
try both git-cvsimport and parsecvs) and then get a checkout via
git-cvsserver.

Works great with traditional cvs cli and well behaved clients (TortoiseCVS).

> am I remembering correctly, and are these tools ready for production use?
> the popfile project is getting ready to abandon sourceforge and move to
> self-hosting, but before I suggest that they use git I need to know the
> current status of these projects (I think the ability to export directly
> into the other interfaces is a significant advantage)

Moodle (a project I hack on) is in a similar situation, specially
after the SF.net debacle with CVS. It is very likely that it will move
to git with git-cvsserver providing "anon cvs" and cvs over ssh to a
very limited set of people with commit rights but no development
knowledge (translators, etc). So there is a path forward.

cheers,



martin

^ permalink raw reply

* Fwd: [OT] Re: Git via a proxy server?
From: Sam Song @ 2006-05-16 12:13 UTC (permalink / raw)
  To: Petr Vandrovec; +Cc: git

Hello,

Petr Vandrovec <petr@vmware.com> wrote:
> Date:	Mon, 27 Feb 2006 00:35:00 +0100
> From:	Petr Vandrovec <petr@vmware.com>
> To:	Sergey Vlasov <vsu@altlinux.ru>
> CC:	"Salyzyn, Mark" <mark_salyzyn@adaptec.com>,
> 	Kernel Mailing List 
> <linux-kernel@vger.kernel.org>
> > [snip]
> > I have successfully used transconnect
> > (http://sourceforge.net/projects/transconnect) for
> > tunnelling git
> > protocol through a HTTP proxy (squid in my case)
> > supporting the CONNECT method.
> >
> > [snip] 
> > Note: most HTTP proxy servers allow CONNECT method
> > to a very limited range of ports, and 
> > administrators will need to enable the git port
> > (9418) explicitly.
> > 
> I know I'm coming kinda late, but I'm using:
> 
> export GIT_PROXY_COMMAND=/usr/local/bin/proxy-cmd.sh
> 
> and proxy-cmd.sh is just single-line command glued
> from what I found available in /bin:
> 
> #! /bin/bash
> 
> (echo "CONNECT $1:$2 HTTP/1.0"; echo; cat ) | socket
> 
> proxy.ourcompany.com 3128 | (read a; read a; cat )
> 
> Replace socket's arguments 'proxy.ourcompany.com
> 3128' with your http proxy.  Fortunately our proxy
> does not see anything wrong with git's port.
> 		Best regards,
> 			Petr Vandrovec

With above usage on GIT_PROXY_COMMAND, I still have
problem on connection with remote git repository.

I also tried setting http_proxy directly but the same
result. It's first usage of git in our network. Well, 
need I enable the git port 9418 at proxy server? Or 
did I miss sth or what?

I use git-2006-05-14.tar.gz package on FC3. 

Method I : Use GIT_PROXY_COMMAND

[root@sam u-boot]# git clone \
git://www.denx.de/git/u-boot.git u-boot-denx.git

fatal: exec failed
fetch-pack from 'git://www.denx.de/git/u-boot.git' 
failed.

[root@sam u-boot]# git clone \
http://parisc-linux.org/git/linux-2.6.git/ parisc-2.6

Cannot get remote repository information.
Perhaps git-update-server-info needs to be run there?
[root@sam u-boot]#

/usr/local/bin/proxy-cmd.sh 

#! /bin/bash

(echo "CONNECT $1:$2 HTTP/1.0";echo;cat) | socket
<um> <pwd> 192.168.40.99 80 | (read a;read a;cat)

Method II : Use http_proxy directly

[root@sam u-boot]# export \
http_proxy="http://<username>:<pwd>@192.168.40.99:80"
[root@sam u-boot]# git clone \ 
http://parisc-linux.org/git/linux-2.6.git/ parisc-2.6

Cannot get remote repository information.
Perhaps git-update-server-info needs to be run there?

[root@sam u-boot]# git clone \
git://www.denx.de/git/u-boot.git u-boot-denx.git
fatal: unable to connect a socket (Connection timed 
out)
fetch-pack from 'git://www.denx.de/git/u-boot.git' 
failed.
[root@sam u-boot]#

Thanks in advance,

Sam

P.S. I forward this thread from LKML for better 
discussion. Hope Petr wouldn't mind.

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam
protection around 
http://mail.yahoo.com 

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

^ permalink raw reply

* Re: [PATCH] Simplify packing public repositories
From: Sean @ 2006-05-16 11:47 UTC (permalink / raw)
  To: Timo Hirvonen; +Cc: junkio, git
In-Reply-To: <20060516144635.010bb65f.tihirvon@gmail.com>

On Tue, 16 May 2006 14:46:35 +0300
Timo Hirvonen <tihirvon@gmail.com> wrote:

> Support "git repack project.git" syntax which is more intuitive than
> using the GIT_DIR environment variable.
> 

There are a few commands that would benefit from being easier to run
in a bare repository.  If this option was added to the "git" wrapper
rather than git-repack, it would work for all of them.  But maybe
git could just automatically recognize when it's in a bare repository.

Sean

^ permalink raw reply

* [PATCH] Simplify packing public repositories
From: Timo Hirvonen @ 2006-05-16 11:46 UTC (permalink / raw)
  To: junkio; +Cc: git

Support "git repack project.git" syntax which is more intuitive than
using the GIT_DIR environment variable.

Signed-off-by: Timo Hirvonen <tihirvon@gmail.com>

---

 git-repack.sh |   27 ++++++++++++++++++++++++---
 1 files changed, 24 insertions(+), 3 deletions(-)

c09c41750023e5b502312ddaa21bf5a2371e66ac
diff --git a/git-repack.sh b/git-repack.sh
index 4fb3f26..b24cd1a 100755
--- a/git-repack.sh
+++ b/git-repack.sh
@@ -3,8 +3,8 @@ #
 # Copyright (c) 2005 Linus Torvalds
 #
 
-USAGE='[-a] [-d] [-f] [-l] [-n] [-q]'
-. git-sh-setup
+unset CDPATH
+USAGE='[-a] [-d] [-f] [-l] [-n] [-q] [GIT_DIR]'
 
 no_update_info= all_into_one= remove_redundant=
 local= quiet= no_reuse_delta= extra=
@@ -19,11 +19,32 @@ do
 	-l)	local=--local ;;
 	--window=*) extra="$extra $1" ;;
 	--depth=*) extra="$extra $1" ;;
-	*)	usage ;;
+	-h|--h|--he|--hel|--help)
+		echo "Usage: $0 $USAGE"
+		exit
+		;;
+	*)
+		if test "$#" -gt 1
+		then
+			echo >&2 "Usage: $0 $USAGE"
+			exit 1
+		fi
+		export GIT_DIR="$1"
+		;;
 	esac
 	shift
 done
 
+: ${GIT_DIR=.git}
+: ${GIT_OBJECT_DIRECTORY="$GIT_DIR/objects"}
+
+# Make sure we are in a valid repository of a vintage we understand.
+GIT_DIR="$GIT_DIR" git repo-config --get core.nosuch >/dev/null
+if test $? = 128
+then
+    exit
+fi
+
 rm -f .tmp-pack-*
 PACKDIR="$GIT_OBJECT_DIRECTORY/pack"
 
-- 
1.3.3.g8701-dirty

^ permalink raw reply related

* The smartest way to save money, buy Viagra online.
From: Sandy Benton @ 2006-05-16 11:29 UTC (permalink / raw)
  To: git

We guarantee the quality and safety of all medications ordered.
http://dtc.pxvxuguuv4uf7p7icppiu7p7.myrciaid.com/?nizjfaylh

^ permalink raw reply

* Re: [PATCH] CMIT_FMT_EMAIL: Q-encode Subject: and display-name part of From: fields.
From: Rocco Rutte @ 2006-05-16 10:49 UTC (permalink / raw)
  To: git
In-Reply-To: <7vmzdi9ssv.fsf@assigned-by-dhcp.cox.net>

Hi,

* Junio C Hamano [06-05-16 03:18:24 -0700] wrote:

[...]

> Thoughts?

> If we decide to do the header formatting here, there are two
> further enhancements that need to be done:

> (1) The charset must be configurable for projects that use
>     encoding different from UTF-8, perhaps with the .git/config
>     [i18n] commitEncoding.  It is only a convention, not a hard
>     rule, to use UTF-8 for the metainformation.

To write an encoder really fully conforming to RfC2047 is a mess. Not so
much because the algorithms are difficult but because there're many
things to take care of if you want to do it right.

For example, encoded words are required to be at most something below 80
characters long. For names this maybe is not an issue, but for subjects.
I didn't really check whether your patch produces only the minimum
encoding (i.e. only those words that need it and not just all words with
'_' or '=20' in between them) but if not, 80 isn't that much after all.
And you may need to think about header folding (and unfolding for
reading it back in).

Also, supporting any character set (via iconv()) blows up the
implementation. There're character sets for which other RfCs define the
encoding method so only using quoted-printable is not fully correct in
all possible cases.

And, with the first point, several character sets really can become a
mess as you need to produce several encoded words because the input
would exceed RfC limits otherwise. Because for multi-byte character sets
you musn't break within a multi-byte character sequence but only at
their boundaries. So you need a generic way to detect the byte-size of
such a character in any supported character set.

With just the UTF-8 encoding all of this is pretty simple though.

I would rather try to find a way to implement this in a scripting
language that already has standard modules for this or makes it easy to
write one. In C this gets quite lengthy...

   bye, Rocco
-- 
:wq!

^ permalink raw reply

* Re: [PATCH] CMIT_FMT_EMAIL: Q-encode Subject: and display-name part of From: fields.
From: Jakub Narebski @ 2006-05-16 10:38 UTC (permalink / raw)
  To: git
In-Reply-To: <7vmzdi9ssv.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano wrote:

> By convention, the commit message and the author/committer names
> in the commit objects are UTF-8 encoded.  When formatting for
> e-mails, Q-encode them according to RFC 2047.
> 
> While we are at it, generate the content-type and
> content-transfer-encoding headers as well.
> 
> Signed-off-by: Junio C Hamano <junkio@cox.net>
> 
> ---
> 
>  With this patch, the output formatted with
> 
> git show --pretty=email --patch-with-stat 9d7f73d4
> 
>  would start like this:
> 
>    From 9d7f73d43fa49d0d2f5a8cfcce9d659e8ad2d265  Thu Apr 7 15:13:13 2005
>    From: =?utf-8?q?Lukas_Sandstr=C3=B6m?= <lukass@etek.chalmers.se>
>    Date: Sat, 25 Feb 2006 12:20:13 +0100
>    Subject: [PATCH] git-fetch: print the new and old ref when fast-forwarding 
>    Content-Type: text/plain; charset=UTF-8 
>    Content-Transfer-Encoding: 8bit

I guess that we also need
     
     MIME-Version: 1.0

(from what I remember of troubles with Eoutlook Express not sending all 
the required headers, and tin not working properly).

If I remember correctly encoding headers using quoted-printable is needed
only because headers are before charset is set. IIRC there was proposal
to use UTF-8 for headers regardless of the charset used for body of message.

P.S. Should we set User-Agent header as well?
-- 
Jakub Narebski
Warsaw, Poland

^ permalink raw reply

* Buy popular drugs online.
From: Simeon Kuhn @ 2006-05-16 10:21 UTC (permalink / raw)
  To: git

The objective of this guide is to save you time and money. 
http://jrtz.s0g0fjffg7f0aaa3fsslxaaa.sluggingmc.com/?efvck

^ permalink raw reply

* [PATCH] CMIT_FMT_EMAIL: Q-encode Subject: and display-name part of From: fields.
From: Junio C Hamano @ 2006-05-16 10:18 UTC (permalink / raw)
  To: git

By convention, the commit message and the author/committer names
in the commit objects are UTF-8 encoded.  When formatting for
e-mails, Q-encode them according to RFC 2047.

While we are at it, generate the content-type and
content-transfer-encoding headers as well.

Signed-off-by: Junio C Hamano <junkio@cox.net>

---

 With this patch, the output formatted with

	git show --pretty=email --patch-with-stat 9d7f73d4

 would start like this:

   From 9d7f73d43fa49d0d2f5a8cfcce9d659e8ad2d265  Thu Apr 7 15:13:13 2005
   From: =?utf-8?q?Lukas_Sandstr=C3=B6m?= <lukass@etek.chalmers.se>
   Date: Sat, 25 Feb 2006 12:20:13 +0100
   Subject: [PATCH] git-fetch: print the new and old ref when fast-forwarding
   Content-Type: text/plain; charset=UTF-8
   Content-Transfer-Encoding: 8bit

 This is marked RFC because I am not convinced if this kind of
 header formatting should be done by format-patch; we might be
 better off leaving the proper massaging to whatever downstream
 program that reads its output (e.g. send-email or imap-send).
 We produce the mbox format (and that is a requirement -- its
 output should be consumable by git-am), so the downstream needs
 to strip off the initial UNIX-From line at least anyway.

 Thoughts?

 If we decide to do the header formatting here, there are two
 further enhancements that need to be done:

 (1) The charset must be configurable for projects that use
     encoding different from UTF-8, perhaps with the .git/config
     [i18n] commitEncoding.  It is only a convention, not a hard
     rule, to use UTF-8 for the metainformation.

 (2) Some projects, notably Wine, seem to prefer patches to be
     sent as attachments, and we have support for that in the
     script version of format-patch.  We would want to have the
     same here.  This needs to be an option; define a new
     format, CMIT_FMT_MIME, and invoke it with --pretty=mime.

     Ideally we would want to say, in the body part header for
     the attachment, that the type of the payload is a raw 8bit
     text/patch without any specific charset (if the upstream
     project has a UTF-8 encoded file, you should not send in a
     patch in iso-8859-1 and expect somebody to automagically
     transcode your patch -- the patch is applied as is and MTA
     should not molest it).

 The RFC2047 q-encoding code definitely needs to be audited by
 an RFC lawyer.  I used to be one myself but I lost my edge and
 patience these days.

diff --git a/commit.c b/commit.c
index 93b3903..dee5756 100644
--- a/commit.c
+++ b/commit.c
@@ -413,6 +413,46 @@ static int get_one_line(const char *msg,
 	return ret;
 }
 
+static int is_rfc2047_special(char ch)
+{
+	return ((ch & 0x80) || (ch == '=') || (ch == '?') || (ch == '_'));
+}
+
+static int add_rfc2047(char *buf, const char *line, int len)
+{
+	char *bp = buf;
+	int i, needquote;
+	static const char q_utf8[] = "=?utf-8?q?";
+
+	for (i = needquote = 0; !needquote && i < len; i++) {
+		unsigned ch = line[i];
+		if (ch & 0x80)
+			needquote++;
+		if ((i + 1 < len) &&
+		    (ch == '=' && line[i+1] == '?'))
+			needquote++;
+	}
+	if (!needquote)
+		return sprintf(buf, "%.*s", len, line);
+
+	memcpy(bp, q_utf8, sizeof(q_utf8)-1);
+	bp += sizeof(q_utf8)-1;
+	for (i = 0; i < len; i++) {
+		unsigned ch = line[i];
+		if (is_rfc2047_special(ch)) {
+			sprintf(bp, "=%02X", ch);
+			bp += 3;
+		}
+		else if (ch == ' ')
+			*bp++ = '_';
+		else
+			*bp++ = ch;
+	}
+	memcpy(bp, "?=", 2);
+	bp += 2;
+	return bp - buf;
+}
+
 static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf, const char *line)
 {
 	char *date;
@@ -431,12 +471,26 @@ static int add_user_info(const char *wha
 	tz = strtol(date, NULL, 10);
 
 	if (fmt == CMIT_FMT_EMAIL) {
-		what = "From";
+		char *name_tail = strchr(line, '<');
+		int display_name_length;
+		if (!name_tail)
+			return 0;
+		while (line < name_tail && isspace(name_tail[-1]))
+			name_tail--;
+		display_name_length = name_tail - line;
 		filler = "";
+		strcpy(buf, "From: ");
+		ret = strlen(buf);
+		ret += add_rfc2047(buf + ret, line, display_name_length);
+		memcpy(buf + ret, name_tail, namelen - display_name_length);
+		ret += namelen - display_name_length;
+		buf[ret++] = '\n';
+	}
+	else {
+		ret = sprintf(buf, "%s: %.*s%.*s\n", what,
+			      (fmt == CMIT_FMT_FULLER) ? 4 : 0,
+			      filler, namelen, line);
 	}
-	ret = sprintf(buf, "%s: %.*s%.*s\n", what,
-		      (fmt == CMIT_FMT_FULLER) ? 4 : 0,
-		      filler, namelen, line);
 	switch (fmt) {
 	case CMIT_FMT_MEDIUM:
 		ret += sprintf(buf + ret, "Date:   %s\n", show_date(time, tz));
@@ -575,14 +629,24 @@ unsigned long pretty_print_commit(enum c
 			int slen = strlen(subject);
 			memcpy(buf + offset, subject, slen);
 			offset += slen;
+			offset += add_rfc2047(buf + offset, line, linelen);
+		}
+		else {
+			memset(buf + offset, ' ', indent);
+			memcpy(buf + offset + indent, line, linelen);
+			offset += linelen + indent;
 		}
-		memset(buf + offset, ' ', indent);
-		memcpy(buf + offset + indent, line, linelen);
-		offset += linelen + indent;
 		buf[offset++] = '\n';
 		if (fmt == CMIT_FMT_ONELINE)
 			break;
-		subject = NULL;
+		if (subject) {
+			static const char header[] =
+				"Content-Type: text/plain; charset=UTF-8\n"
+				"Content-Transfer-Encoding: 8bit\n";
+			memcpy(buf + offset, header, sizeof(header)-1);
+			offset += sizeof(header)-1;
+			subject = NULL;
+		}
 	}
 	while (offset && isspace(buf[offset-1]))
 		offset--;

^ permalink raw reply related

* Re: [PATCH] Update the documentation for git-merge-base
From: Junio C Hamano @ 2006-05-16  7:51 UTC (permalink / raw)
  To: Fredrik Kuivinen; +Cc: git
In-Reply-To: <20060516065452.GA5540@c165.ib.student.liu.se>

Fredrik Kuivinen <freku045@student.liu.se> writes:

>> See the big illustration at the top of the source for how you
>> can construct pathological case to defeat an attempt to
>> guarantee such.  --all guarantees that the output contains all
>> interesting ones, but does not guarantee the output has no
>> suboptimal merge bases.
>
> There are two examples at the top of the source. In the first one a
> least common ancestor is returned. As I interpret the second one, it
> is an example of how the old algorithm without the postprocessing step
> produced a common ancestor which is not least.

Ah, yes, I remember now.

The drawing was done while we were working on the solution to
that pathological case; mark_reachable_commits() solves that
horizon effect.

    http://article.gmane.org/gmane.comp.version-control.git/11410
    http://article.gmane.org/gmane.comp.version-control.git/11429
    http://article.gmane.org/gmane.comp.version-control.git/11552
    http://article.gmane.org/gmane.comp.version-control.git/11613

However, our inability to come up with one is not a nonexistence
proof of cases the current algorithm can fail, so math minded
people _might_ want to prove the algorithm is optimal.

Not me, though.

^ permalink raw reply

* Re: [PATCH 1/2] Handle branch names with slashes
From: Karl Hasselström @ 2006-05-16  7:45 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Catalin Marinas
In-Reply-To: <7v64k6ea8r.fsf@assigned-by-dhcp.cox.net>

On 2006-05-15 23:48:04 -0700, Junio C Hamano wrote:

> Karl Hasselström <kha@treskal.com> writes:
>
> > I had to change the patch@branch/top command-line syntax to
> > patch@branch%top, in order to get sane parsing. The /top variant
> > is still available for repositories that have no slashy branches;
> > it is disabled as soon as there exists at least one subdirectory
> > of refs/heads. Preferably, this compatibility hack can be killed
> > some time in the future.
>
> I wonder if using double-slashes is an easier alternative to type
> than '%', like "patch@branch//top". That way, you do not have to
> forbid per-cent sign in branch names.

Good argument. And // does look slightly better than %, too. But I'll
wait a few days this time, or else someone will surely come along with
an even better idea. :-)

-- 
Karl Hasselström, kha@treskal.com
      www.treskal.com/kalle

^ permalink raw reply

* Re: newbie question
From: Matthias Kestenholz @ 2006-05-16  7:09 UTC (permalink / raw)
  To: Li Yang-r58472; +Cc: git
In-Reply-To: <9FCDBA58F226D911B202000BDBAD467308146E@zch01exm40.ap.freescale.net>

Hello,

* Li Yang-r58472 (LeoLi@freescale.com) wrote:
> I just starting to use git recently.  I have setup a public repository,
> and pushed cloned open source repository to it.  As most documents 
> suggested, I need to run a repack on the public repository.  Normally 
> git-repack is run in the source directory(the parent directory of .git).  
> Considering the public repository, there is no source directory and the
> *.git is the uppest level directory.  Where am I supposed to run the
> git-repack command?

Do it like that:

$ ls
project.git
$ GIT_DIR=project.git git-repack -a -d

^ permalink raw reply

* newbie question
From: Li Yang-r58472 @ 2006-05-16  7:03 UTC (permalink / raw)
  To: git

I just starting to use git recently.  I have setup a public repository, and pushed cloned open source repository to it.  As most documents suggested, I need to run a repack on the public repository.  Normally git-repack is run in the source directory(the parent directory of .git).  Considering the public repository, there is no source directory and the *.git is the uppest level directory.  Where am I supposed to run the git-repack command?

^ permalink raw reply

* Re: [PATCH] Update the documentation for git-merge-base
From: Fredrik Kuivinen @ 2006-05-16  6:54 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Fredrik Kuivinen, git
In-Reply-To: <7vhd3qebuv.fsf@assigned-by-dhcp.cox.net>

On Mon, May 15, 2006 at 11:13:12PM -0700, Junio C Hamano wrote:
> Fredrik Kuivinen <freku045@student.liu.se> writes:
> 
> > Is the code guaranteed to return a least common ancestor? If that is
> > the case we should probably mention it in the documentation.
> 
> Unfortunately, no, if you mean by "least common" closest to the
> tips.
>

By "least" I mean the following:

C is a least common ancestor of A and B if:

* C is a common ancestor of A and B, and
* for every other common ancestor D (different from C) of A and B, C
  is not reacheable from D.

> See the big illustration at the top of the source for how you
> can construct pathological case to defeat an attempt to
> guarantee such.  --all guarantees that the output contains all
> interesting ones, but does not guarantee the output has no
> suboptimal merge bases.

There are two examples at the top of the source. In the first one a
least common ancestor is returned. As I interpret the second one, it
is an example of how the old algorithm without the postprocessing step
produced a common ancestor which is not least.

Am I wrong? Do we have any cases where the current merge-base
algorithm gives us common ancestors which are not least?

- Fredrik

^ permalink raw reply

* Re: [PATCH 1/2] Handle branch names with slashes
From: Junio C Hamano @ 2006-05-16  6:48 UTC (permalink / raw)
  To: Karl Hasselström; +Cc: git
In-Reply-To: <20060516063541.GA11218@backpacker.hemma.treskal.com>

Karl Hasselström <kha@treskal.com> writes:

> Teach stgit to handle branch names with slashes in them; that is,
> branches living in a subdirectory of .git/refs/heads.
>
> I had to change the patch@branch/top command-line syntax to
> patch@branch%top, in order to get sane parsing. The /top variant is
> still available for repositories that have no slashy branches; it is
> disabled as soon as there exists at least one subdirectory of
> refs/heads. Preferably, this compatibility hack can be killed some
> time in the future.

I wonder if using double-slashes is an easier alternative to
type than '%', like "patch@branch//top".  That way, you do not
have to forbid per-cent sign in branch names.

^ permalink raw reply

* [PATCH 2/2] Tests for branch names with slashes
From: Karl Hasselström @ 2006-05-16  6:37 UTC (permalink / raw)
  To: Catalin Marinas; +Cc: Wartan Hachaturow, git
In-Reply-To: <20060515105810.GA27077@diana.vm.bytemark.co.uk>

Test a number of operations on a repository that has branch names
containing slashes (that is, branches living in a subdirectory of
.git/refs/heads).

Signed-off-by: Karl Hasselström <kha@treskal.com>


---

The test also had to be changed to use % instead of #.

 t/t0001-subdir-branches.sh |   59 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 59 insertions(+), 0 deletions(-)
 create mode 100644 t/t0001-subdir-branches.sh

2278d3988ae3fee7624aac6db6bd92677173749f
diff --git a/t/t0001-subdir-branches.sh b/t/t0001-subdir-branches.sh
new file mode 100644
index 0000000..64f583c
--- /dev/null
+++ b/t/t0001-subdir-branches.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Karl Hasselström
+#
+
+test_description='Branch names containing slashes
+
+Test a number of operations on a repository that has branch names
+containing slashes (that is, branches living in a subdirectory of
+.git/refs/heads).'
+
+. ./test-lib.sh
+
+test_expect_success 'Create a patch' \
+  'stg init &&
+   echo "foo" > foo.txt &&
+   stg add foo.txt &&
+   stg new foo -m "Add foo.txt" &&
+   stg refresh'
+
+test_expect_success 'Old and new id with non-slashy branch' \
+  'stg id foo &&
+   stg id foo% &&
+   stg id foo/ &&
+   stg id foo%top &&
+   stg id foo/top &&
+   stg id foo@master &&
+   stg id foo@master%top &&
+   stg id foo@master/top'
+
+test_expect_success 'Clone branch to slashier name' \
+  'stg branch --clone x/y/z'
+
+test_expect_success 'Try new form of id with slashy branch' \
+  'stg id foo &&
+   stg id foo% &&
+   stg id foo%top &&
+   stg id foo@x/y/z &&
+   stg id foo@x/y/z%top'
+
+test_expect_failure 'Try old id with slashy branch' \
+  'stg id foo/ ||
+   stg id foo/top ||
+   stg id foo@x/y/z/top'
+
+test_expect_success 'Create patch in slashy branch' \
+  'echo "bar" >> foo.txt &&
+   stg new bar -m "Add another line" &&
+   stg refresh'
+
+test_expect_success 'Rename branches' \
+  'stg branch --rename master goo/gaa &&
+   test ! -e .git/refs/heads/master &&
+   stg branch --rename goo/gaa x1/x2/x3/x4 &&
+   test ! -e .git/refs/heads/goo &&
+   stg branch --rename x1/x2/x3/x4 servant &&
+   test ! -e .git/refs/heads/x1'
+
+test_done
-- 
1.3.2.g639c


-- 
Karl Hasselström, kha@treskal.com
      www.treskal.com/kalle

^ permalink raw reply related

* [PATCH 1/2] Handle branch names with slashes
From: Karl Hasselström @ 2006-05-16  6:35 UTC (permalink / raw)
  To: Catalin Marinas; +Cc: Wartan Hachaturow, git
In-Reply-To: <20060515105810.GA27077@diana.vm.bytemark.co.uk>

Teach stgit to handle branch names with slashes in them; that is,
branches living in a subdirectory of .git/refs/heads.

I had to change the patch@branch/top command-line syntax to
patch@branch%top, in order to get sane parsing. The /top variant is
still available for repositories that have no slashy branches; it is
disabled as soon as there exists at least one subdirectory of
refs/heads. Preferably, this compatibility hack can be killed some
time in the future.

Signed-off-by: Karl Hasselström <kha@treskal.com>


---

This is the same patch as before, but with # replaced with %.

 stgit/commands/branch.py |    5 ++
 stgit/commands/common.py |  103 ++++++++++++++++++++++++++--------------------
 stgit/commands/diff.py   |   12 +++--
 stgit/commands/files.py  |    4 +-
 stgit/commands/id.py     |    2 -
 stgit/commands/mail.py   |    8 ++--
 stgit/git.py             |   42 +++++++++----------
 stgit/stack.py           |   21 ++++++---
 stgit/utils.py           |   88 +++++++++++++++++++++++++++++++++++++--
 9 files changed, 193 insertions(+), 92 deletions(-)

76545c189be3a091ab62b112f1a841473600d35c
diff --git a/stgit/commands/branch.py b/stgit/commands/branch.py
index 2218bbb..d348409 100644
--- a/stgit/commands/branch.py
+++ b/stgit/commands/branch.py
@@ -172,7 +172,10 @@ def func(parser, options, args):
         if len(args) != 0:
             parser.error('incorrect number of arguments')
 
-        branches = os.listdir(os.path.join(basedir.get(), 'refs', 'heads'))
+        branches = []
+        basepath = os.path.join(basedir.get(), 'refs', 'heads')
+        for path, files, dirs in walk_tree(basepath):
+            branches += [os.path.join(path, f) for f in files]
         branches.sort()
 
         if branches:
diff --git a/stgit/commands/common.py b/stgit/commands/common.py
index c6ca514..a428dd9 100644
--- a/stgit/commands/common.py
+++ b/stgit/commands/common.py
@@ -18,7 +18,7 @@ along with this program; if not, write t
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 """
 
-import sys, os, re
+import sys, os, os.path, re
 from optparse import OptionParser, make_option
 
 from stgit.utils import *
@@ -34,54 +34,69 @@ class CmdException(Exception):
 
 
 # Utility functions
+class RevParseException(Exception):
+    """Revision spec parse error."""
+    pass
+
+def parse_rev(rev):
+    """Parse a revision specification into its
+    patchname@branchname%patch_id parts. If no branch name has a slash
+    in it, also accept / instead of %."""
+    files, dirs = list_files_and_dirs(os.path.join(basedir.get(),
+                                                   'refs', 'heads'))
+    if len(dirs) != 0:
+        # We have branch names with / in them.
+        branch_chars = '[^@%]'
+        patch_id_mark = '%'
+    else:
+        # No / in branch names.
+        branch_chars = '[^@%/]'
+        patch_id_mark = '[/%]'
+    patch_re = r'(?P<patch>[^@/%]+)'
+    branch_re = r'@(?P<branch>%s+)' % branch_chars
+    patch_id_re = r'%s(?P<patch_id>[a-z.]*)' % patch_id_mark
+
+    # Try %patch_id.
+    m = re.match(r'^%s$' % patch_id_re, rev)
+    if m:
+        return None, None, m.group('patch_id')
+
+    # Try patch[@branch][%patch_id].
+    m = re.match(r'^%s(%s)?(%s)?$' % (patch_re, branch_re, patch_id_re), rev)
+    if m:
+        return m.group('patch'), m.group('branch'), m.group('patch_id')
+
+    # No, we can't parse that.
+    raise RevParseException
+
 def git_id(rev):
     """Return the GIT id
     """
     if not rev:
         return None
-    
-    rev_list = rev.split('/')
-    if len(rev_list) == 2:
-        patch_id = rev_list[1]
-        if not patch_id:
-            patch_id = 'top'
-    elif len(rev_list) == 1:
-        patch_id = 'top'
-    else:
-        patch_id = None
-
-    patch_branch = rev_list[0].split('@')
-    if len(patch_branch) == 1:
-        series = crt_series
-    elif len(patch_branch) == 2:
-        series = stack.Series(patch_branch[1])
-    else:
-        raise CmdException, 'Unknown id: %s' % rev
-
-    patch_name = patch_branch[0]
-    if not patch_name:
-        patch_name = series.get_current()
-        if not patch_name:
-            raise CmdException, 'No patches applied'
-
-    # patch
-    if patch_name in series.get_applied() \
-           or patch_name in series.get_unapplied():
-        if patch_id == 'top':
-            return series.get_patch(patch_name).get_top()
-        elif patch_id == 'bottom':
-            return series.get_patch(patch_name).get_bottom()
-        # Note we can return None here.
-        elif patch_id == 'top.old':
-            return series.get_patch(patch_name).get_old_top()
-        elif patch_id == 'bottom.old':
-            return series.get_patch(patch_name).get_old_bottom()
-
-    # base
-    if patch_name == 'base' and len(rev_list) == 1:
-        return read_string(series.get_base_file())
-
-    # anything else failed
+    try:
+        patch, branch, patch_id = parse_rev(rev)
+        if branch == None:
+            series = crt_series
+        else:
+            series = stack.Series(branch)
+        if patch == None:
+            patch = series.get_current()
+            if not patch:
+                raise CmdException, 'No patches applied'
+        if patch in series.get_applied() or patch in series.get_unapplied():
+            if patch_id in ['top', '', None]:
+                return series.get_patch(patch).get_top()
+            elif patch_id == 'bottom':
+                return series.get_patch(patch).get_bottom()
+            elif patch_id == 'top.old':
+                return series.get_patch(patch).get_old_top()
+            elif patch_id == 'bottom.old':
+                return series.get_patch(patch).get_old_bottom()
+        if patch == 'base' and patch_id == None:
+            return read_string(series.get_base_file())
+    except RevParseException:
+        pass
     return git.rev_parse(rev + '^{commit}')
 
 def check_local_changes():
diff --git a/stgit/commands/diff.py b/stgit/commands/diff.py
index 7dc6c5d..e465e7a 100644
--- a/stgit/commands/diff.py
+++ b/stgit/commands/diff.py
@@ -33,12 +33,12 @@ or a tree-ish object and another tree-is
 be given to restrict the diff output. The tree-ish object can be a
 standard git commit, tag or tree. In addition to these, the command
 also supports 'base', representing the bottom of the current stack,
-and '[patch]/[bottom | top]' for the patch boundaries (defaulting to
+and '[patch][%[bottom | top]]' for the patch boundaries (defaulting to
 the current one):
 
-rev = '([patch]/[bottom | top]) | <tree-ish> | base'
+rev = '([patch][%[bottom | top]]) | <tree-ish> | base'
 
-If neither bottom or top are given but a '/' is present, the command
+If neither bottom or top are given but a '%' is present, the command
 shows the specified patch (defaulting to the current one)."""
 
 options = [make_option('-r', metavar = 'rev1[:[rev2]]', dest = 'revs',
@@ -55,10 +55,10 @@ def func(parser, options, args):
         rev_list = options.revs.split(':')
         rev_list_len = len(rev_list)
         if rev_list_len == 1:
-            if rev_list[0][-1] == '/':
+            if rev_list[0][-1] in ['/', '%']:
                 # the whole patch
-                rev1 = rev_list[0] + 'bottom'
-                rev2 = rev_list[0] + 'top'
+                rev1 = rev_list[0][:-1] + '%bottom'
+                rev2 = rev_list[0][:-1] + '%top'
             else:
                 rev1 = rev_list[0]
                 rev2 = None
diff --git a/stgit/commands/files.py b/stgit/commands/files.py
index 0694d83..a20ce96 100644
--- a/stgit/commands/files.py
+++ b/stgit/commands/files.py
@@ -53,8 +53,8 @@ def func(parser, options, args):
     else:
         parser.error('incorrect number of arguments')
 
-    rev1 = git_id('%s/bottom' % patch)
-    rev2 = git_id('%s/top' % patch)
+    rev1 = git_id('%s%%bottom' % patch)
+    rev2 = git_id('%s%%top' % patch)
 
     if options.stat:
         print git.diffstat(rev1 = rev1, rev2 = rev2)
diff --git a/stgit/commands/id.py b/stgit/commands/id.py
index 1cf6ea6..1a5938b 100644
--- a/stgit/commands/id.py
+++ b/stgit/commands/id.py
@@ -28,7 +28,7 @@ usage = """%prog [options] [id]
 
 Print the hash value of a GIT id (defaulting to HEAD). In addition to
 the standard GIT id's like heads and tags, this command also accepts
-'base[@<branch>]' and '[<patch>[@<branch>]][/(bottom | top)]'. If no
+'base[@<branch>]' and '[<patch>[@<branch>]][%[bottom | top]]'. If no
 'top' or 'bottom' are passed and <patch> is a valid patch name, 'top'
 will be used by default."""
 
diff --git a/stgit/commands/mail.py b/stgit/commands/mail.py
index 5e01ea1..0d2c260 100644
--- a/stgit/commands/mail.py
+++ b/stgit/commands/mail.py
@@ -324,10 +324,10 @@ def __build_message(tmpl, patch, patch_n
                  'shortdescr':   short_descr,
                  'longdescr':    long_descr,
                  'endofheaders': headers_end,
-                 'diff':         git.diff(rev1 = git_id('%s/bottom' % patch),
-                                          rev2 = git_id('%s/top' % patch)),
-                 'diffstat':     git.diffstat(rev1 = git_id('%s/bottom'%patch),
-                                              rev2 = git_id('%s/top' % patch)),
+                 'diff':         git.diff(rev1 = git_id('%s%%bottom' % patch),
+                                          rev2 = git_id('%s%%top' % patch)),
+                 'diffstat':     git.diffstat(rev1 = git_id('%s%%bottom'%patch),
+                                              rev2 = git_id('%s%%top' % patch)),
                  'date':         email.Utils.formatdate(localtime = True),
                  'version':      version_str,
                  'patchnr':      patch_nr_str,
diff --git a/stgit/git.py b/stgit/git.py
index 2884f36..716609c 100644
--- a/stgit/git.py
+++ b/stgit/git.py
@@ -225,7 +225,8 @@ def get_head():
 def get_head_file():
     """Returns the name of the file pointed to by the HEAD link
     """
-    return os.path.basename(_output_one_line('git-symbolic-ref HEAD'))
+    return strip_prefix('refs/heads/',
+                        _output_one_line('git-symbolic-ref HEAD'))
 
 def set_head_file(ref):
     """Resets HEAD to point to a new ref
@@ -233,7 +234,8 @@ def set_head_file(ref):
     # head cache flushing is needed since we might have a different value
     # in the new head
     __clear_head_cache()
-    if __run('git-symbolic-ref HEAD', [ref]) != 0:
+    if __run('git-symbolic-ref HEAD',
+             [os.path.join('refs', 'heads', ref)]) != 0:
         raise GitException, 'Could not set head to "%s"' % ref
 
 def __set_head(val):
@@ -272,6 +274,7 @@ def rev_parse(git_id):
 def branch_exists(branch):
     """Existence check for the named branch
     """
+    branch = os.path.join('refs', 'heads', branch)
     for line in _output_lines('git-rev-parse --symbolic --all 2>&1'):
         if line.strip() == branch:
             return True
@@ -282,12 +285,11 @@ def branch_exists(branch):
 def create_branch(new_branch, tree_id = None):
     """Create a new branch in the git repository
     """
-    new_head = os.path.join('refs', 'heads', new_branch)
-    if branch_exists(new_head):
+    if branch_exists(new_branch):
         raise GitException, 'Branch "%s" already exists' % new_branch
 
     current_head = get_head()
-    set_head_file(new_head)
+    set_head_file(new_branch)
     __set_head(current_head)
 
     # a checkout isn't needed if new branch points to the current head
@@ -297,22 +299,22 @@ def create_branch(new_branch, tree_id = 
     if os.path.isfile(os.path.join(basedir.get(), 'MERGE_HEAD')):
         os.remove(os.path.join(basedir.get(), 'MERGE_HEAD'))
 
-def switch_branch(name):
+def switch_branch(new_branch):
     """Switch to a git branch
     """
     global __head
 
-    new_head = os.path.join('refs', 'heads', name)
-    if not branch_exists(new_head):
-        raise GitException, 'Branch "%s" does not exist' % name
+    if not branch_exists(new_branch):
+        raise GitException, 'Branch "%s" does not exist' % new_branch
 
-    tree_id = rev_parse(new_head + '^{commit}')
+    tree_id = rev_parse(os.path.join('refs', 'heads', new_branch)
+                        + '^{commit}')
     if tree_id != get_head():
         refresh_index()
         if __run('git-read-tree -u -m', [get_head(), tree_id]) != 0:
             raise GitException, 'git-read-tree failed (local changes maybe?)'
         __head = tree_id
-    set_head_file(new_head)
+    set_head_file(new_branch)
 
     if os.path.isfile(os.path.join(basedir.get(), 'MERGE_HEAD')):
         os.remove(os.path.join(basedir.get(), 'MERGE_HEAD'))
@@ -320,25 +322,23 @@ def switch_branch(name):
 def delete_branch(name):
     """Delete a git branch
     """
-    branch_head = os.path.join('refs', 'heads', name)
-    if not branch_exists(branch_head):
+    if not branch_exists(name):
         raise GitException, 'Branch "%s" does not exist' % name
-    os.remove(os.path.join(basedir.get(), branch_head))
+    remove_file_and_dirs(os.path.join(basedir.get(), 'refs', 'heads'),
+                         name)
 
 def rename_branch(from_name, to_name):
     """Rename a git branch
     """
-    from_head = os.path.join('refs', 'heads', from_name)
-    if not branch_exists(from_head):
+    if not branch_exists(from_name):
         raise GitException, 'Branch "%s" does not exist' % from_name
-    to_head = os.path.join('refs', 'heads', to_name)
-    if branch_exists(to_head):
+    if branch_exists(to_name):
         raise GitException, 'Branch "%s" already exists' % to_name
 
     if get_head_file() == from_name:
-        set_head_file(to_head)
-    os.rename(os.path.join(basedir.get(), from_head), \
-              os.path.join(basedir.get(), to_head))
+        set_head_file(to_name)
+    rename(os.path.join(basedir.get(), 'refs', 'heads'),
+           from_name, to_name)
 
 def add(names):
     """Add the files or recursively add the directory contents
diff --git a/stgit/stack.py b/stgit/stack.py
index f83161b..49b50e7 100644
--- a/stgit/stack.py
+++ b/stgit/stack.py
@@ -443,8 +443,7 @@ class Series:
 
         os.makedirs(self.__patch_dir)
 
-        if not os.path.isdir(bases_dir):
-            os.makedirs(bases_dir)
+        create_dirs(bases_dir)
 
         create_empty_file(self.__applied_file)
         create_empty_file(self.__unapplied_file)
@@ -502,11 +501,14 @@ class Series:
         git.rename_branch(self.__name, to_name)
 
         if os.path.isdir(self.__series_dir):
-            os.rename(self.__series_dir, to_stack.__series_dir)
+            rename(os.path.join(self.__base_dir, 'patches'),
+                   self.__name, to_stack.__name)
         if os.path.exists(self.__base_file):
-            os.rename(self.__base_file, to_stack.__base_file)
+            rename(os.path.join(self.__base_dir, 'refs', 'bases'),
+                   self.__name, to_stack.__name)
         if os.path.exists(self.__refs_dir):
-            os.rename(self.__refs_dir, to_stack.__refs_dir)
+            rename(os.path.join(self.__base_dir, 'refs', 'patches'),
+                   self.__name, to_stack.__name)
 
         self.__init__(to_name)
 
@@ -560,16 +562,19 @@ class Series:
             else:
                 print 'Patch directory %s is not empty.' % self.__name
             if not os.listdir(self.__series_dir):
-                os.rmdir(self.__series_dir)
+                remove_dirs(os.path.join(self.__base_dir, 'patches'),
+                            self.__name)
             else:
                 print 'Series directory %s is not empty.' % self.__name
             if not os.listdir(self.__refs_dir):
-                os.rmdir(self.__refs_dir)
+                remove_dirs(os.path.join(self.__base_dir, 'refs', 'patches'),
+                            self.__name)
             else:
                 print 'Refs directory %s is not empty.' % self.__refs_dir
 
         if os.path.exists(self.__base_file):
-            os.remove(self.__base_file)
+            remove_file_and_dirs(
+                os.path.join(self.__base_dir, 'refs', 'bases'), self.__name)
 
     def refresh_patch(self, files = None, message = None, edit = False,
                       show_patch = False,
diff --git a/stgit/utils.py b/stgit/utils.py
index 5749b3b..68b8f58 100644
--- a/stgit/utils.py
+++ b/stgit/utils.py
@@ -1,6 +1,8 @@
 """Common utility functions
 """
 
+import errno, os, os.path
+
 __copyright__ = """
 Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com>
 
@@ -18,6 +20,12 @@ along with this program; if not, write t
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 """
 
+def mkdir_file(filename, mode):
+    """Opens filename with the given mode, creating the directory it's
+    in if it doesn't already exist."""
+    create_dirs(os.path.dirname(filename))
+    return file(filename, mode)
+
 def read_string(filename, multiline = False):
     """Reads the first line from a file
     """
@@ -32,7 +40,7 @@ def read_string(filename, multiline = Fa
 def write_string(filename, line, multiline = False):
     """Writes 'line' to file and truncates it
     """
-    f = file(filename, 'w+')
+    f = mkdir_file(filename, 'w+')
     if multiline:
         f.write(line)
     else:
@@ -42,7 +50,7 @@ def write_string(filename, line, multili
 def append_strings(filename, lines):
     """Appends 'lines' sequence to file
     """
-    f = file(filename, 'a+')
+    f = mkdir_file(filename, 'a+')
     for line in lines:
         print >> f, line
     f.close()
@@ -50,14 +58,14 @@ def append_strings(filename, lines):
 def append_string(filename, line):
     """Appends 'line' to file
     """
-    f = file(filename, 'a+')
+    f = mkdir_file(filename, 'a+')
     print >> f, line
     f.close()
 
 def insert_string(filename, line):
     """Inserts 'line' at the beginning of the file
     """
-    f = file(filename, 'r+')
+    f = mkdir_file(filename, 'r+')
     lines = f.readlines()
     f.seek(0); f.truncate()
     print >> f, line
@@ -67,4 +75,74 @@ def insert_string(filename, line):
 def create_empty_file(name):
     """Creates an empty file
     """
-    file(name, 'w+').close()
+    mkdir_file(name, 'w+').close()
+
+def list_files_and_dirs(path):
+    """Return the sets of filenames and directory names in a
+    directory."""
+    files, dirs = [], []
+    for fd in os.listdir(path):
+        full_fd = os.path.join(path, fd)
+        if os.path.isfile(full_fd):
+            files.append(fd)
+        elif os.path.isdir(full_fd):
+            dirs.append(fd)
+    return files, dirs
+
+def walk_tree(basedir):
+    """Starting in the given directory, iterate through all its
+    subdirectories. For each subdirectory, yield the name of the
+    subdirectory (relative to the base directory), the list of
+    filenames in the subdirectory, and the list of directory names in
+    the subdirectory."""
+    subdirs = ['']
+    while subdirs:
+        subdir = subdirs.pop()
+        files, dirs = list_files_and_dirs(os.path.join(basedir, subdir))
+        for d in dirs:
+            subdirs.append(os.path.join(subdir, d))
+        yield subdir, files, dirs
+
+def strip_prefix(prefix, string):
+    """Return string, without the prefix. Blow up if string doesn't
+    start with prefix."""
+    assert string.startswith(prefix)
+    return string[len(prefix):]
+
+def remove_dirs(basedir, dirs):
+    """Starting at join(basedir, dirs), remove the directory if empty,
+    and try the same with its parent, until we find a nonempty
+    directory or reach basedir."""
+    path = dirs
+    while path:
+        try:
+            os.rmdir(os.path.join(basedir, path))
+        except OSError:
+            return # can't remove nonempty directory
+        path = os.path.dirname(path)
+
+def remove_file_and_dirs(basedir, file):
+    """Remove join(basedir, file), and then remove the directory it
+    was in if empty, and try the same with its parent, until we find a
+    nonempty directory or reach basedir."""
+    os.remove(os.path.join(basedir, file))
+    remove_dirs(basedir, os.path.dirname(file))
+
+def create_dirs(directory):
+    """Create the given directory, if the path doesn't already exist."""
+    if directory:
+        create_dirs(os.path.dirname(directory))
+        try:
+            os.mkdir(directory)
+        except OSError, e:
+            if e.errno != errno.EEXIST:
+                raise e
+
+def rename(basedir, file1, file2):
+    """Rename join(basedir, file1) to join(basedir, file2), not
+    leaving any empty directories behind and creating any directories
+    necessary."""
+    full_file2 = os.path.join(basedir, file2)
+    create_dirs(os.path.dirname(full_file2))
+    os.rename(os.path.join(basedir, file1), full_file2)
+    remove_dirs(basedir, os.path.dirname(file1))
-- 
1.3.2.g639c


-- 
Karl Hasselström, kha@treskal.com
      www.treskal.com/kalle

^ permalink raw reply related

* Re: [PATCH] Update the documentation for git-merge-base
From: Junio C Hamano @ 2006-05-16  6:13 UTC (permalink / raw)
  To: Fredrik Kuivinen; +Cc: git
In-Reply-To: <20060516055815.GA4572@c165.ib.student.liu.se>

Fredrik Kuivinen <freku045@student.liu.se> writes:

> Is the code guaranteed to return a least common ancestor? If that is
> the case we should probably mention it in the documentation.

Unfortunately, no, if you mean by "least common" closest to the
tips.

See the big illustration at the top of the source for how you
can construct pathological case to defeat an attempt to
guarantee such.  --all guarantees that the output contains all
interesting ones, but does not guarantee the output has no
suboptimal merge bases.

^ permalink raw reply

* [PATCH] Update the documentation for git-merge-base
From: Fredrik Kuivinen @ 2006-05-16  5:58 UTC (permalink / raw)
  To: junkio; +Cc: git


Signed-off-by: Fredrik Kuivinen <freku045@student.liu.se>

---

Is the code guaranteed to return a least common ancestor? If that is
the case we should probably mention it in the documentation.


 Documentation/git-merge-base.txt |   18 ++++++++++++++----
 1 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-merge-base.txt b/Documentation/git-merge-base.txt
index d1d56f1..6099be2 100644
--- a/Documentation/git-merge-base.txt
+++ b/Documentation/git-merge-base.txt
@@ -8,16 +8,26 @@ git-merge-base - Finds as good a common 
 
 SYNOPSIS
 --------
-'git-merge-base' <commit> <commit>
+'git-merge-base' [--all] <commit> <commit>
 
 DESCRIPTION
 -----------
-"git-merge-base" finds as good a common ancestor as possible. Given a
-selection of equally good common ancestors it should not be relied on
-to decide in any particular way.
+
+"git-merge-base" finds as good a common ancestor as possible between
+the two commits. That is, given two commits A and B 'git-merge-base A
+B' will output a commit which is reachable from both A and B through
+the parent relationship.
+
+Given a selection of equally good common ancestors it should not be
+relied on to decide in any particular way.
 
 The "git-merge-base" algorithm is still in flux - use the source...
 
+OPTIONS
+-------
+--all::
+	Output all common ancestors for the two commits instead of
+	just one.
 
 Author
 ------

^ permalink raw reply related


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