Git development
 help / color / mirror / Atom feed
* Re: [PATCH/Test] Build in merge is broken
From: Junio C Hamano @ 2008-07-13 19:11 UTC (permalink / raw)
  To: Miklos Vajna; +Cc: Sverre Hvammen Johansen, git
In-Reply-To: <20080713184300.GF10347@genesis.frugalware.org>

Miklos Vajna <vmiklos@frugalware.org> writes:

> On Sun, Jul 13, 2008 at 07:46:59PM +0200, Miklos Vajna <vmiklos@frugalware.org> wrote:
>> So far what I see is that the input for the reduce_heads() function is
>> (c1, c0, c2, c0, c1). The expected output would be (c1, c2), but the
>> actual output is c2. So I suspect the bug is not in builtin-merge.c
>> itself but in reduce_heads().
>
> This fixes the problem for me. Junio, does the fix looks correct to you
> as well?

You are correct, the "item"s are the highlander (i.e. "there can be only
one") objects but commit-list elements that hold pointers to them are not,
so we need to dereference and compare.

Thanks.

^ permalink raw reply

* Re: [PATCH 0/4] Proposed patches
From: Lukas Sandström @ 2008-07-13 18:57 UTC (permalink / raw)
  To: Catalin Marinas; +Cc: git
In-Reply-To: <b0943d9e0807130442k36a10747q7bcbd996cdc774dd@mail.gmail.com>

Catalin Marinas wrote:
> 2008/7/13 Catalin Marinas <catalin.marinas@gmail.com>:
>> A new post of the proposed patches after implementing Karl's comments.
> 
> BTW, these are StGIT patches, I forgot to add the prefix in the subject line.
> 
If you run "git config format.subjectprefix 'StGIT PATCH'" in your repo,
git format-patch will add the prefix automatically for you.

StGIT might have a similar option.

/Lukas

^ permalink raw reply

* Re: [PATCH/Test] Build in merge is broken
From: Miklos Vajna @ 2008-07-13 18:43 UTC (permalink / raw)
  To: Sverre Hvammen Johansen; +Cc: git, Junio C Hamano
In-Reply-To: <20080713174659.GE10347@genesis.frugalware.org>

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

On Sun, Jul 13, 2008 at 07:46:59PM +0200, Miklos Vajna <vmiklos@frugalware.org> wrote:
> So far what I see is that the input for the reduce_heads() function is
> (c1, c0, c2, c0, c1). The expected output would be (c1, c2), but the
> actual output is c2. So I suspect the bug is not in builtin-merge.c
> itself but in reduce_heads().

This fixes the problem for me. Junio, does the fix looks correct to you
as well?

Thanks.

diff --git a/commit.c b/commit.c
index d20b14e..03e73f3 100644
--- a/commit.c
+++ b/commit.c
@@ -747,7 +747,7 @@ struct commit_list *reduce_heads(struct commit_list *heads)
 
 		num_other = 0;
 		for (q = heads; q; q = q->next) {
-			if (p == q)
+			if (p->item == q->item)
 				continue;
 			other[num_other++] = q->item;
 		}

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

^ permalink raw reply related

* Re: tests for git-p4
From: Matt McClure @ 2008-07-13 18:40 UTC (permalink / raw)
  To: Simon Hausmann; +Cc: git
In-Reply-To: <200807131426.09688.simon@lst.de>

On Sun, Jul 13, 2008 at 8:26 AM, Simon Hausmann <simon@lst.de> wrote:
> On Saturday 12 July 2008 14:24:10 Matt McClure wrote:
> There are currently no automated tests for git-p4. I would certainly be
> interested, but I forsee difficulties testing the interaction with p4 in a
> general way independent from a specific server setup.

I can solve that by bootstrapping a p4d server for the tests that need
to exercise p4 directly.  At higher levels of abstraction, if they
evolve, I could replace p4 with a test double that doesn't need a
Perforce server.

Matt

^ permalink raw reply

* Re: [RFH] Finding all commits that touch the same files as a specific commit
From: Johannes Schindelin @ 2008-07-13 18:30 UTC (permalink / raw)
  To: Sverre Rabbelier; +Cc: Junio C Hamano, Git Mailinglist
In-Reply-To: <bd6139dc0807130743y178a865amebcf130a68283854@mail.gmail.com>

Hi,

On Sun, 13 Jul 2008, Sverre Rabbelier wrote:

> On Sun, Jul 13, 2008 at 3:24 AM, Junio C Hamano <gitster@pobox.com> wrote:
> 
> <explanation of the git log traversal machinery snipped>
> 
> > In order to follow renames reliably in a merge heavy history, you need to
> > keep track of the pathname the file you are interested in appears as _in
> > each commit_.  As you traverse down the history, you pass down the
> > pathname to the parent you visit, so while you are traversing from 'x' to
> > earlier 'x', you will keep following "git-gui/git-gui.sh", while you
> > traverse down to 'o', you will inspect "git-gui.sh".
> >
> > The data structure the revision traversal machinery uses does not support
> > this "path-per-commit" natively.
> 
> Would it be possible to go for a slightly less complicated approach
> and instead of passing replacing the tracked file, append it?

Maybe I miss something, but do you not have to keep track of the file 
names, in order to keep track of the proper statistics?

If that is the case, appending does not cut it.

Ciao,
Dscho

^ permalink raw reply

* [PATCH] git-mailinfo: use strbuf's instead of fixed buffers
From: Lukas Sandström @ 2008-07-13 18:30 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Lukas Sandström, Git Mailing List
In-Reply-To: <487A497E.6030308@etek.chalmers.se>

Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
---
 builtin-mailinfo.c |  750 ++++++++++++++++++++++++----------------------------
 1 files changed, 348 insertions(+), 402 deletions(-)

diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
index 2d1520f..329ac43 100644
--- a/builtin-mailinfo.c
+++ b/builtin-mailinfo.c
@@ -5,14 +5,15 @@
 #include "cache.h"
 #include "builtin.h"
 #include "utf8.h"
+#include "strbuf.h"
 
 static FILE *cmitmsg, *patchfile, *fin, *fout;
 
 static int keep_subject;
 static const char *metainfo_charset;
-static char line[1000];
-static char name[1000];
-static char email[1000];
+static struct strbuf line = STRBUF_INIT;
+static struct strbuf name = STRBUF_INIT;
+static struct strbuf email = STRBUF_INIT;
 
 static enum  {
 	TE_DONTCARE, TE_QP, TE_BASE64,
@@ -21,74 +22,77 @@ static enum  {
 	TYPE_TEXT, TYPE_OTHER,
 } message_type;
 
-static char charset[256];
+static struct strbuf charset = STRBUF_INIT;
 static int patch_lines;
-static char **p_hdr_data, **s_hdr_data;
+static struct strbuf **p_hdr_data, **s_hdr_data;
 
 #define MAX_HDR_PARSED 10
 #define MAX_BOUNDARIES 5
 
-static char *sanity_check(char *name, char *email)
+static void get_sane_name(struct strbuf *out, struct strbuf *name, struct strbuf *email)
 {
-	int len = strlen(name);
-	if (len < 3 || len > 60)
-		return email;
-	if (strchr(name, '@') || strchr(name, '<') || strchr(name, '>'))
-		return email;
-	return name;
+	struct strbuf *src = name;
+	if (name->len < 3 || 60 < name->len || strchr(name->buf, '@') ||
+		strchr(name->buf, '<') || strchr(name->buf, '>'))
+		src = email;
+	else if (name == out)
+		return;
+	strbuf_reset(out);
+	strbuf_addbuf(out, src);
 }
 
-static int bogus_from(char *line)
+static void parse_bogus_from(const struct strbuf *line)
 {
 	/* John Doe <johndoe> */
-	char *bra, *ket, *dst, *cp;
 
+	char *bra, *ket;
 	/* This is fallback, so do not bother if we already have an
 	 * e-mail address.
 	 */
-	if (*email)
-		return 0;
+	if (email.len)
+		return;
 
-	bra = strchr(line, '<');
+	bra = strchr(line->buf, '<');
 	if (!bra)
-		return 0;
+		return;
 	ket = strchr(bra, '>');
 	if (!ket)
-		return 0;
+		return;
 
-	for (dst = email, cp = bra+1; cp < ket; )
-		*dst++ = *cp++;
-	*dst = 0;
-	for (cp = line; isspace(*cp); cp++)
-		;
-	for (bra--; isspace(*bra); bra--)
-		*bra = 0;
-	cp = sanity_check(cp, email);
-	strcpy(name, cp);
-	return 1;
+	strbuf_reset(&email);
+	strbuf_add(&email, bra + 1, ket - bra - 1);
+
+	strbuf_reset(&name);
+	strbuf_add(&name, line->buf, bra - line->buf);
+	strbuf_trim(&name);
+	get_sane_name(&name, &name, &email);
 }
 
-static int handle_from(char *in_line)
+static void handle_from(const struct strbuf *from)
 {
-	char line[1000];
 	char *at;
-	char *dst;
+	size_t el;
+	struct strbuf f;
 
-	strcpy(line, in_line);
-	at = strchr(line, '@');
+	strbuf_init(&f, from->len);
+	strbuf_addbuf(&f, from);
+
+	at = strchr(f.buf, '@');
 	if (!at)
-		return bogus_from(line);
+		return parse_bogus_from(from);
 
 	/*
 	 * If we already have one email, don't take any confusing lines
 	 */
-	if (*email && strchr(at+1, '@'))
-		return 0;
+	if (email.len && strchr(at + 1, '@')) {
+		strbuf_release(&f);
+		return;
+	}
 
 	/* Pick up the string around '@', possibly delimited with <>
-	 * pair; that is the email part.  White them out while copying.
+	 * pair; that is the email part.
 	 */
-	while (at > line) {
+	while (at > f.buf) {
 		char c = at[-1];
 		if (isspace(c))
 			break;
@@ -98,56 +102,35 @@ static int handle_from(char *in_line)
 		}
 		at--;
 	}
-	dst = email;
-	for (;;) {
-		unsigned char c = *at;
-		if (!c || c == '>' || isspace(c)) {
-			if (c == '>')
-				*at = ' ';
-			break;
-		}
-		*at++ = ' ';
-		*dst++ = c;
-	}
-	*dst++ = 0;
+	el = strcspn(at, " \n\t\r\v\f>");
+	strbuf_reset(&email);
+	strbuf_add(&email, at, el);
+	strbuf_remove(&f, at - f.buf, el + 1);
 
 	/* The remainder is name.  It could be "John Doe <john.doe@xz>"
-	 * or "john.doe@xz (John Doe)", but we have whited out the
+	 * or "john.doe@xz (John Doe)", but we have removed the
 	 * email part, so trim from both ends, possibly removing
 	 * the () pair at the end.
 	 */
-	at = line + strlen(line);
-	while (at > line) {
-		unsigned char c = *--at;
-		if (!isspace(c)) {
-			at[(c == ')') ? 0 : 1] = 0;
-			break;
-		}
-	}
+	strbuf_trim(&f);
+	if (f.buf[0] == '(')
+		strbuf_remove(&name, 0, 1);
+	if (f.len && f.buf[f.len - 1] == ')')
+		strbuf_setlen(&f, f.len - 1);
 
-	at = line;
-	for (;;) {
-		unsigned char c = *at;
-		if (!c || !isspace(c)) {
-			if (c == '(')
-				at++;
-			break;
-		}
-		at++;
-	}
-	at = sanity_check(at, email);
-	strcpy(name, at);
-	return 1;
+	get_sane_name(&name, &f, &email);
+	strbuf_release(&f);
 }
 
-static int handle_header(char *line, char *data, int ofs)
+static void handle_header(struct strbuf **out, const struct strbuf *line)
 {
-	if (!line || !data)
-		return 1;
-
-	strcpy(data, line+ofs);
+	if (!*out) {
+		*out = xmalloc(sizeof(struct strbuf));
+		strbuf_init(*out, line->len);
+	} else
+		strbuf_reset(*out);
 
-	return 0;
+	strbuf_addbuf(*out, line);
 }
 
 /* NOTE NOTE NOTE.  We do not claim we do full MIME.  We just attempt
@@ -156,13 +139,13 @@ static int handle_header(char *line, char *data, int ofs)
  * case insensitively.
  */
 
-static int slurp_attr(const char *line, const char *name, char *attr)
+static int slurp_attr(const char *line, const char *name, struct strbuf *attr)
 {
 	const char *ends, *ap = strcasestr(line, name);
 	size_t sz;
 
 	if (!ap) {
-		*attr = 0;
+		strbuf_setlen(attr, 0);
 		return 0;
 	}
 	ap += strlen(name);
@@ -173,180 +156,171 @@ static int slurp_attr(const char *line, const char *name, char *attr)
 	else
 		ends = "; \t";
 	sz = strcspn(ap, ends);
-	memcpy(attr, ap, sz);
-	attr[sz] = 0;
+	strbuf_add(attr, ap, sz);
 	return 1;
 }
 
-struct content_type {
-	char *boundary;
-	int boundary_len;
-};
-
-static struct content_type content[MAX_BOUNDARIES];
+static struct strbuf *content[MAX_BOUNDARIES];
 
-static struct content_type *content_top = content;
+static struct strbuf **content_top = content;
 
-static int handle_content_type(char *line)
+static void handle_content_type(struct strbuf *line)
 {
-	char boundary[256];
+	struct strbuf *boundary = xmalloc(sizeof(struct strbuf));
+	strbuf_init(boundary, line->len);
 
-	if (strcasestr(line, "text/") == NULL)
+	if (!strcasestr(line->buf, "text/"))
 		 message_type = TYPE_OTHER;
-	if (slurp_attr(line, "boundary=", boundary + 2)) {
-		memcpy(boundary, "--", 2);
+	if (slurp_attr(line->buf, "boundary=", boundary)) {
+		strbuf_insert(boundary, 0, "--", 2);
 		if (content_top++ >= &content[MAX_BOUNDARIES]) {
 			fprintf(stderr, "Too many boundaries to handle\n");
 			exit(1);
 		}
-		content_top->boundary_len = strlen(boundary);
-		content_top->boundary = xmalloc(content_top->boundary_len+1);
-		strcpy(content_top->boundary, boundary);
+		*content_top = boundary;
+		boundary = NULL;
 	}
-	if (slurp_attr(line, "charset=", charset)) {
-		int i, c;
-		for (i = 0; (c = charset[i]) != 0; i++)
-			charset[i] = tolower(c);
+	if (slurp_attr(line->buf, "charset=", &charset))
+		strbuf_tolower(&charset);
+
+	if (boundary) {
+		strbuf_release(boundary);
+		free(boundary);
 	}
-	return 0;
 }
 
-static int handle_content_transfer_encoding(char *line)
+static void handle_content_transfer_encoding(const struct strbuf *line)
 {
-	if (strcasestr(line, "base64"))
+	if (strcasestr(line->buf, "base64"))
 		transfer_encoding = TE_BASE64;
-	else if (strcasestr(line, "quoted-printable"))
+	else if (strcasestr(line->buf, "quoted-printable"))
 		transfer_encoding = TE_QP;
 	else
 		transfer_encoding = TE_DONTCARE;
-	return 0;
-}
-
-static int is_multipart_boundary(const char *line)
-{
-	return (!memcmp(line, content_top->boundary, content_top->boundary_len));
 }
 
-static int eatspace(char *line)
+static int is_multipart_boundary(const struct strbuf *line)
 {
-	int len = strlen(line);
-	while (len > 0 && isspace(line[len-1]))
-		line[--len] = 0;
-	return len;
+	return !strbuf_cmp(line, *content_top);
 }
 
-static char *cleanup_subject(char *subject)
+static void cleanup_subject(struct strbuf *subject)
 {
-	for (;;) {
-		char *p;
-		int len, remove;
-		switch (*subject) {
+	char *pos;
+	size_t remove;
+	while (subject->len) {
+		switch (*subject->buf) {
 		case 'r': case 'R':
-			if (!memcmp("e:", subject+1, 2)) {
-				subject += 3;
+			if (subject->len <= 3)
+				break;
+			if (!memcmp(subject->buf + 1, "e:", 2)) {
+				strbuf_remove(subject, 0, 3);
 				continue;
 			}
 			break;
 		case ' ': case '\t': case ':':
-			subject++;
+			strbuf_remove(subject, 0, 1);
 			continue;
-
 		case '[':
-			p = strchr(subject, ']');
-			if (!p) {
-				subject++;
-				continue;
-			}
-			len = strlen(p);
-			remove = p - subject;
-			if (remove <= len *2) {
-				subject = p+1;
-				continue;
-			}
+			if ((pos = strchr(subject->buf, ']'))) {
+				remove = pos - subject->buf + 1;
+				/* Don't remove too much. */
+				if (remove <= (subject->len - remove + 1) * 2) {
+					strbuf_remove(subject, 0, remove);
+					continue;
+				}
+			} else
+				strbuf_remove(subject, 0, 1);
 			break;
 		}
-		eatspace(subject);
-		return subject;
+		strbuf_trim(subject);
+		return;
 	}
 }
 
-static void cleanup_space(char *buf)
+static void cleanup_space(struct strbuf *sb)
 {
-	unsigned char c;
-	while ((c = *buf) != 0) {
-		buf++;
-		if (isspace(c)) {
-			buf[-1] = ' ';
-			c = *buf;
-			while (isspace(c)) {
-				int len = strlen(buf);
-				memmove(buf, buf+1, len);
-				c = *buf;
-			}
+	size_t pos, cnt;
+	for (pos = 0; pos < sb->len; pos++) {
+		if (isspace(sb->buf[pos])) {
+			sb->buf[pos] = ' ';
+			for (cnt = 0; isspace(sb->buf[pos + cnt + 1]); cnt++);
+			strbuf_remove(sb, pos + 1, cnt);
 		}
 	}
 }
 
-static void decode_header(char *it, unsigned itsize);
+static void decode_header(struct strbuf *line);
 static const char *header[MAX_HDR_PARSED] = {
 	"From","Subject","Date",
 };
 
-static int check_header(char *line, unsigned linesize, char **hdr_data, int overwrite)
+static inline int cmp_header(const struct strbuf *line, const char *hdr)
 {
-	int i;
+	int len = strlen(hdr);
+	return !strncasecmp(line->buf, hdr, len) && line->len > len &&
+			line->buf[len] == ':' && isspace(line->buf[len + 1]);
+}
 
+static int check_header(const struct strbuf *line,
+				struct strbuf *hdr_data[], int overwrite)
+{
+	int i, ret = 0, len;
+	struct strbuf sb = STRBUF_INIT;
 	/* search for the interesting parts */
 	for (i = 0; header[i]; i++) {
 		int len = strlen(header[i]);
-		if ((!hdr_data[i] || overwrite) &&
-		    !strncasecmp(line, header[i], len) &&
-		    line[len] == ':' && isspace(line[len + 1])) {
+		if ((!hdr_data[i] || overwrite) && cmp_header(line, header[i])) {
 			/* Unwrap inline B and Q encoding, and optionally
 			 * normalize the meta information to utf8.
 			 */
-			decode_header(line + len + 2, linesize - len - 2);
-			hdr_data[i] = xmalloc(1000 * sizeof(char));
-			if (! handle_header(line, hdr_data[i], len + 2)) {
-				return 1;
-			}
+			strbuf_add(&sb, line->buf + len + 2, line->len - len -2);
+			decode_header(&sb);
+			handle_header(&hdr_data[i], &sb);
+			ret = 1;
+			goto check_header_out;
 		}
 	}
 
 	/* Content stuff */
-	if (!strncasecmp(line, "Content-Type", 12) &&
-		line[12] == ':' && isspace(line[12 + 1])) {
-		decode_header(line + 12 + 2, linesize - 12 - 2);
-		if (! handle_content_type(line)) {
-			return 1;
-		}
-	}
-	if (!strncasecmp(line, "Content-Transfer-Encoding", 25) &&
-		line[25] == ':' && isspace(line[25 + 1])) {
-		decode_header(line + 25 + 2, linesize - 25 - 2);
-		if (! handle_content_transfer_encoding(line)) {
-			return 1;
-		}
+	if (cmp_header(line, "Content-Type")) {
+		len = strlen("Content-Type: ");
+		strbuf_add(&sb, line->buf + len, line->len - len);
+		decode_header(&sb);
+		strbuf_insert(&sb, 0, "Content-Type: ", len);
+		handle_content_type(&sb);
+		ret = 1;
+		goto check_header_out;
+	}
+	if (cmp_header(line, "Content-Transfer-Encoding")) {
+		len = strlen("Content-Transfer-Encoding: ");
+		strbuf_add(&sb, line->buf + len, line->len - len);
+		decode_header(&sb);
+		handle_content_transfer_encoding(&sb);
+		ret = 1;
+		goto check_header_out;
 	}
 
 	/* for inbody stuff */
-	if (!memcmp(">From", line, 5) && isspace(line[5]))
-		return 1;
-	if (!memcmp("[PATCH]", line, 7) && isspace(line[7])) {
+	if (!prefixcmp(line->buf, ">From") && isspace(line->buf[5]))
+		ret = 1; /* Should this return 0? */
+		goto check_header_out;
+	if (!prefixcmp(line->buf, "[PATCH]") && isspace(line->buf[7])) {
 		for (i = 0; header[i]; i++) {
 			if (!memcmp("Subject", header[i], 7)) {
-				if (! handle_header(line, hdr_data[i], 0)) {
-					return 1;
-				}
+				handle_header(&hdr_data[i], line);
+				ret = 1;
+				goto check_header_out;
 			}
 		}
 	}
 
-	/* no match */
-	return 0;
+check_header_out:
+	strbuf_release(&sb);
+	return ret;
 }
 
-static int is_rfc2822_header(char *line)
+static int is_rfc2822_header(const struct strbuf *line)
 {
 	/*
 	 * The section that defines the loosest possible
@@ -357,15 +331,15 @@ static int is_rfc2822_header(char *line)
 	 * ftext = %d33-57 / %59-126
 	 */
 	int ch;
-	char *cp = line;
+	char *cp = line->buf;
 
 	/* Count mbox From headers as headers */
-	if (!memcmp(line, "From ", 5) || !memcmp(line, ">From ", 6))
+	if (!prefixcmp(cp, "From ") || !prefixcmp(cp, ">From "))
 		return 1;
 
 	while ((ch = *cp++)) {
 		if (ch == ':')
-			return cp != line;
+			return 1;
 		if ((33 <= ch && ch <= 57) ||
 		    (59 <= ch && ch <= 126))
 			continue;
@@ -374,34 +348,20 @@ static int is_rfc2822_header(char *line)
 	return 0;
 }
 
-/*
- * sz is size of 'line' buffer in bytes.  Must be reasonably
- * long enough to hold one physical real-world e-mail line.
- */
-static int read_one_header_line(char *line, int sz, FILE *in)
+static int read_one_header_line(struct strbuf *line, FILE *in)
 {
-	int len;
-
-	/*
-	 * We will read at most (sz-1) bytes and then potentially
-	 * re-add NUL after it.  Accessing line[sz] after this is safe
-	 * and we can allow len to grow up to and including sz.
-	 */
-	sz--;
-
 	/* Get the first part of the line. */
-	if (!fgets(line, sz, in))
+	if (strbuf_getline(line, in, '\n'))
 		return 0;
 
 	/*
 	 * Is it an empty line or not a valid rfc2822 header?
 	 * If so, stop here, and return false ("not a header")
 	 */
-	len = eatspace(line);
-	if (!len || !is_rfc2822_header(line)) {
+	strbuf_rtrim(line);
+	if (!line->len || !is_rfc2822_header(line)) {
 		/* Re-add the newline */
-		line[len] = '\n';
-		line[len + 1] = '\0';
+		strbuf_addch(line, '\n');
 		return 0;
 	}
 
@@ -410,65 +370,53 @@ static int read_one_header_line(char *line, int sz, FILE *in)
 	 * Yuck, 2822 header "folding"
 	 */
 	for (;;) {
-		int peek, addlen;
-		static char continuation[1000];
+		int peek;
+		struct strbuf continuation = STRBUF_INIT;
 
 		peek = fgetc(in); ungetc(peek, in);
 		if (peek != ' ' && peek != '\t')
 			break;
-		if (!fgets(continuation, sizeof(continuation), in))
+		if (strbuf_getline(&continuation, in, '\n'))
 			break;
-		addlen = eatspace(continuation);
-		if (len < sz - 1) {
-			if (addlen >= sz - len)
-				addlen = sz - len - 1;
-			memcpy(line + len, continuation, addlen);
-			line[len] = '\n';
-			len += addlen;
-		}
+		continuation.buf[0] = '\n';
+		strbuf_rtrim(&continuation);
+		strbuf_addbuf(line, &continuation);
 	}
-	line[len] = 0;
 
 	return 1;
 }
 
-static int decode_q_segment(char *in, char *ot, unsigned otsize, char *ep, int rfc2047)
+static struct strbuf *decode_q_segment(const struct strbuf *q_seg, int rfc2047)
 {
-	char *otbegin = ot;
-	char *otend = ot + otsize;
+	const char *in = q_seg->buf;
 	int c;
-	while ((c = *in++) != 0 && (in <= ep)) {
-		if (ot == otend) {
-			*--ot = '\0';
-			return -1;
-		}
+	struct strbuf *out = xmalloc(sizeof(struct strbuf));
+	strbuf_init(out, q_seg->len);
+
+	while ((c = *in++) != 0) {
 		if (c == '=') {
 			int d = *in++;
 			if (d == '\n' || !d)
 				break; /* drop trailing newline */
-			*ot++ = ((hexval(d) << 4) | hexval(*in++));
+			strbuf_addch(out, (hexval(d) << 4) | hexval(*in++));
 			continue;
 		}
 		if (rfc2047 && c == '_') /* rfc2047 4.2 (2) */
 			c = 0x20;
-		*ot++ = c;
+		strbuf_addch(out, c);
 	}
-	*ot = 0;
-	return (ot - otbegin);
+	return out;
 }
 
-static int decode_b_segment(char *in, char *ot, unsigned otsize, char *ep)
+static struct strbuf *decode_b_segment(const struct strbuf *b_seg)
 {
 	/* Decode in..ep, possibly in-place to ot */
 	int c, pos = 0, acc = 0;
-	char *otbegin = ot;
-	char *otend = ot + otsize;
+	const char *in = b_seg->buf;
+	struct strbuf *out = xmalloc(sizeof(struct strbuf));
+	strbuf_init(out, b_seg->len);
 
-	while ((c = *in++) != 0 && (in <= ep)) {
-		if (ot == otend) {
-			*--ot = '\0';
-			return -1;
-		}
+	while ((c = *in++) != 0) {
 		if (c == '+')
 			c = 62;
 		else if (c == '/')
@@ -493,21 +441,20 @@ static int decode_b_segment(char *in, char *ot, unsigned otsize, char *ep)
 			acc = (c << 2);
 			break;
 		case 1:
-			*ot++ = (acc | (c >> 4));
+			strbuf_addch(out, (acc | (c >> 4)));
 			acc = (c & 15) << 4;
 			break;
 		case 2:
-			*ot++ = (acc | (c >> 2));
+			strbuf_addch(out, (acc | (c >> 2)));
 			acc = (c & 3) << 6;
 			break;
 		case 3:
-			*ot++ = (acc | c);
+			strbuf_addch(out, (acc | c));
 			acc = pos = 0;
 			break;
 		}
 	}
-	*ot = 0;
-	return (ot - otbegin);
+	return out;
 }
 
 /*
@@ -521,16 +468,16 @@ static int decode_b_segment(char *in, char *ot, unsigned otsize, char *ep)
  * Otherwise, we default to assuming it is Latin1 for historical
  * reasons.
  */
-static const char *guess_charset(const char *line, const char *target_charset)
+static const char *guess_charset(const struct strbuf *line, const char *target_charset)
 {
 	if (is_encoding_utf8(target_charset)) {
-		if (is_utf8(line))
+		if (is_utf8(line->buf))
 			return NULL;
 	}
 	return "latin1";
 }
 
-static void convert_to_utf8(char *line, unsigned linesize, const char *charset)
+static void convert_to_utf8(struct strbuf *line, const char *charset)
 {
 	char *out;
 
@@ -542,112 +489,119 @@ static void convert_to_utf8(char *line, unsigned linesize, const char *charset)
 
 	if (!strcmp(metainfo_charset, charset))
 		return;
-	out = reencode_string(line, metainfo_charset, charset);
+	out = reencode_string(line->buf, metainfo_charset, charset);
 	if (!out)
 		die("cannot convert from %s to %s\n",
 		    charset, metainfo_charset);
-	strlcpy(line, out, linesize);
-	free(out);
+	strbuf_attach(line, out, strlen(out), strlen(out));
 }
 
-static int decode_header_bq(char *it, unsigned itsize)
+static int decode_header_bq(struct strbuf *it)
 {
 	char *in, *out, *ep, *cp, *sp;
-	char outbuf[1000];
+	struct strbuf outbuf = STRBUF_INIT, *dec;
+	struct strbuf charset_q = STRBUF_INIT, piecebuf = STRBUF_INIT;
 	int rfc2047 = 0;
 
-	in = it;
-	out = outbuf;
-	while ((ep = strstr(in, "=?")) != NULL) {
-		int sz, encoding;
-		char charset_q[256], piecebuf[256];
+	in = it->buf;
+	while (in - it->buf <= it->len && (ep = strstr(in, "=?")) != NULL) {
+		int encoding;
+		strbuf_reset(&charset_q);
+		strbuf_reset(&piecebuf);
 		rfc2047 = 1;
 
 		if (in != ep) {
-			sz = ep - in;
-			memcpy(out, in, sz);
-			out += sz;
-			in += sz;
+			strbuf_add(&outbuf, in, ep - in);
+			in = ep;
 		}
 		/* E.g.
 		 * ep : "=?iso-2022-jp?B?GyR...?= foo"
 		 * ep : "=?ISO-8859-1?Q?Foo=FCbar?= baz"
 		 */
 		ep += 2;
-		cp = strchr(ep, '?');
-		if (!cp)
-			return rfc2047; /* no munging */
-		for (sp = ep; sp < cp; sp++)
-			charset_q[sp - ep] = tolower(*sp);
-		charset_q[cp - ep] = 0;
+
+		if (ep - it->buf >= it->len || !(cp = strchr(ep, '?')))
+			goto decode_header_bq_out;
+
+		if (cp + 3 - it->buf > it->len)
+			goto decode_header_bq_out;
+		strbuf_add(&charset_q, ep, cp - ep);
+		strbuf_tolower(&charset_q);
+
 		encoding = cp[1];
 		if (!encoding || cp[2] != '?')
-			return rfc2047; /* no munging */
+			goto decode_header_bq_out;
 		ep = strstr(cp + 3, "?=");
 		if (!ep)
-			return rfc2047; /* no munging */
+			goto decode_header_bq_out;
+		strbuf_add(&piecebuf, cp + 3, ep - cp - 3);
 		switch (tolower(encoding)) {
 		default:
-			return rfc2047; /* no munging */
+			goto decode_header_bq_out;
 		case 'b':
-			sz = decode_b_segment(cp + 3, piecebuf, sizeof(piecebuf), ep);
+			dec = decode_b_segment(&piecebuf);
 			break;
 		case 'q':
-			sz = decode_q_segment(cp + 3, piecebuf, sizeof(piecebuf), ep, 1);
+			dec = decode_q_segment(&piecebuf, 1);
 			break;
 		}
-		if (sz < 0)
-			return rfc2047;
 		if (metainfo_charset)
-			convert_to_utf8(piecebuf, sizeof(piecebuf), charset_q);
+			convert_to_utf8(dec, charset_q.buf);
 
-		sz = strlen(piecebuf);
-		if (outbuf + sizeof(outbuf) <= out + sz)
-			return rfc2047; /* no munging */
-		strcpy(out, piecebuf);
-		out += sz;
+		strbuf_addbuf(&outbuf, dec);
+		strbuf_release(dec);
+		free(dec);
 		in = ep + 2;
 	}
-	strcpy(out, in);
-	strlcpy(it, outbuf, itsize);
+	strbuf_addstr(&outbuf, in);
+	strbuf_reset(it);
+	strbuf_addbuf(it, &outbuf);
+decode_header_bq_out:
+	strbuf_release(&outbuf);
+	strbuf_release(&charset_q);
+	strbuf_release(&piecebuf);
 	return rfc2047;
 }
 
-static void decode_header(char *it, unsigned itsize)
+static void decode_header(struct strbuf *it)
 {
-
-	if (decode_header_bq(it, itsize))
+	if (decode_header_bq(it))
 		return;
 	/* otherwise "it" is a straight copy of the input.
 	 * This can be binary guck but there is no charset specified.
 	 */
 	if (metainfo_charset)
-		convert_to_utf8(it, itsize, "");
+		convert_to_utf8(it, "");
 }
 
-static int decode_transfer_encoding(char *line, unsigned linesize, int inputlen)
+static void decode_transfer_encoding(struct strbuf *line)
 {
-	char *ep;
+	struct strbuf *ret;
+	int len;
 
 	switch (transfer_encoding) {
 	case TE_QP:
-		ep = line + inputlen;
-		return decode_q_segment(line, line, linesize, ep, 0);
+		ret = decode_q_segment(line, 0);
+		break;
 	case TE_BASE64:
-		ep = line + inputlen;
-		return decode_b_segment(line, line, linesize, ep);
+		ret = decode_b_segment(line);
+		break;
 	case TE_DONTCARE:
 	default:
-		return inputlen;
+		return;
 	}
+	strbuf_reset(line);
+	strbuf_addbuf(line, ret);
+	strbuf_release(ret);
+	free(ret);
 }
 
-static int handle_filter(char *line, unsigned linesize, int linelen);
+static void handle_filter(struct strbuf *line);
 
 static int find_boundary(void)
 {
-	while(fgets(line, sizeof(line), fin) != NULL) {
-		if (is_multipart_boundary(line))
+	while(!strbuf_getline(&line, fin, '\n')) {
+		if (is_multipart_boundary(&line))
 			return 1;
 	}
 	return 0;
@@ -655,12 +609,17 @@ static int find_boundary(void)
 
 static int handle_boundary(void)
 {
-	char newline[]="\n";
+	struct strbuf newline = STRBUF_INIT;
+
+	strbuf_addch(&newline, '\n');
 again:
-	if (!memcmp(line+content_top->boundary_len, "--", 2)) {
+	if (line.len >= (*content_top)->len + 2 &&
+	    !memcmp(line.buf + (*content_top)->len, "--", 2)) {
 		/* we hit an end boundary */
 		/* pop the current boundary off the stack */
-		free(content_top->boundary);
+		strbuf_release(*content_top);
+		free(*content_top);
+		*content_top = NULL;
 
 		/* technically won't happen as is_multipart_boundary()
 		   will fail first.  But just in case..
@@ -670,7 +629,8 @@ again:
 					"can't recover\n");
 			exit(1);
 		}
-		handle_filter(newline, sizeof(newline), strlen(newline));
+		handle_filter(&newline);
+		strbuf_release(&newline);
 
 		/* skip to the next boundary */
 		if (!find_boundary())
@@ -680,39 +640,44 @@ again:
 
 	/* set some defaults */
 	transfer_encoding = TE_DONTCARE;
-	charset[0] = 0;
+	strbuf_reset(&charset);
 	message_type = TYPE_TEXT;
 
 	/* slurp in this section's info */
-	while (read_one_header_line(line, sizeof(line), fin))
-		check_header(line, sizeof(line), p_hdr_data, 0);
+	while (read_one_header_line(&line, fin))
+		check_header(&line, p_hdr_data, 0);
 
+	strbuf_release(&newline);
 	/* eat the blank line after section info */
-	return (fgets(line, sizeof(line), fin) != NULL);
+	return (strbuf_getline(&line, fin, '\n') == 0);
 }
 
-static inline int patchbreak(const char *line)
+static inline int patchbreak(const struct strbuf *line)
 {
+	size_t i;
+
 	/* Beginning of a "diff -" header? */
-	if (!memcmp("diff -", line, 6))
+	if (!prefixcmp(line->buf, "diff -"))
 		return 1;
 
 	/* CVS "Index: " line? */
-	if (!memcmp("Index: ", line, 7))
+	if (!prefixcmp(line->buf, "Index: "))
 		return 1;
 
 	/*
 	 * "--- <filename>" starts patches without headers
 	 * "---<sp>*" is a manual separator
 	 */
-	if (!memcmp("---", line, 3)) {
-		line += 3;
+	if (line->len < 4)
+		return 0;
+
+	if (!prefixcmp(line->buf, "---")) {
 		/* space followed by a filename? */
-		if (line[0] == ' ' && !isspace(line[1]))
+		if (line->buf[3] == ' ' && !isspace(line->buf[4]))
 			return 1;
 		/* Just whitespace? */
-		for (;;) {
-			unsigned char c = *line++;
+		for (i = 3; i < line->len; i++) {
+			unsigned char c = line->buf[i];
 			if (c == '\n')
 				return 1;
 			if (!isspace(c))
@@ -723,32 +688,25 @@ static inline int patchbreak(const char *line)
 	return 0;
 }
 
-
-static int handle_commit_msg(char *line, unsigned linesize)
+static int handle_commit_msg(struct strbuf *line)
 {
 	static int still_looking = 1;
-	char *endline = line + linesize;
+	char *c;
 
 	if (!cmitmsg)
 		return 0;
 
 	if (still_looking) {
-		char *cp = line;
-		if (isspace(*line)) {
-			for (cp = line + 1; *cp; cp++) {
-				if (!isspace(*cp))
-					break;
-			}
-			if (!*cp)
-				return 0;
-		}
-		if ((still_looking = check_header(cp, endline - cp, s_hdr_data, 0)) != 0)
+		strbuf_ltrim(line);
+		if (!line->len)
+			return 0;
+		if ((still_looking = check_header(line, s_hdr_data, 0)) != 0)
 			return 0;
 	}
 
 	/* normalize the log message to UTF-8. */
 	if (metainfo_charset)
-		convert_to_utf8(line, endline - line, charset);
+		convert_to_utf8(line, charset.buf);
 
 	if (patchbreak(line)) {
 		fclose(cmitmsg);
@@ -756,142 +714,132 @@ static int handle_commit_msg(char *line, unsigned linesize)
 		return 1;
 	}
 
-	fputs(line, cmitmsg);
+	fputs(line->buf, cmitmsg);
 	return 0;
 }
 
-static int handle_patch(char *line, int len)
+static void handle_patch(const struct strbuf *line)
 {
-	fwrite(line, 1, len, patchfile);
+	fwrite(line->buf, 1, line->len, patchfile);
 	patch_lines++;
-	return 0;
 }
 
-static int handle_filter(char *line, unsigned linesize, int linelen)
+static void handle_filter(struct strbuf *line)
 {
 	static int filter = 0;
 
-	/* filter tells us which part we left off on
-	 * a non-zero return indicates we hit a filter point
-	 */
+	/* filter tells us which part we left off on */
 	switch (filter) {
 	case 0:
-		if (!handle_commit_msg(line, linesize))
+		if (!handle_commit_msg(line))
 			break;
 		filter++;
 	case 1:
-		if (!handle_patch(line, linelen))
-			break;
-		filter++;
-	default:
-		return 1;
+		handle_patch(line);
+		break;
 	}
-
-	return 0;
 }
 
 static void handle_body(void)
 {
-	int rc = 0;
-	static char newline[2000];
-	static char *np = newline;
-	int len = strlen(line);
+	int len = 0;
+	struct strbuf prev = STRBUF_INIT;
 
 	/* Skip up to the first boundary */
-	if (content_top->boundary) {
+	if (*content_top) {
 		if (!find_boundary())
-			return;
+			goto handle_body_out;
 	}
 
 	do {
+		strbuf_setlen(&line, line.len + len);
+
 		/* process any boundary lines */
-		if (content_top->boundary && is_multipart_boundary(line)) {
+		if (*content_top && is_multipart_boundary(&line)) {
 			/* flush any leftover */
-			if (np != newline)
-				handle_filter(newline, sizeof(newline),
-					      np - newline);
+			if (line.len)
+				handle_filter(&line);
+
 			if (!handle_boundary())
-				return;
-			len = strlen(line);
+				goto handle_body_out;
 		}
 
 		/* Unwrap transfer encoding */
-		len = decode_transfer_encoding(line, sizeof(line), len);
-		if (len < 0) {
-			error("Malformed input line");
-			return;
-		}
+		decode_transfer_encoding(&line);
 
 		switch (transfer_encoding) {
 		case TE_BASE64:
 		case TE_QP:
 		{
-			char *op = line;
+			struct strbuf **lines, **it, *sb;
+
+			/* Prepend any previous partial lines */
+			strbuf_insert(&line, 0, prev.buf, prev.len);
+			strbuf_reset(&prev);
 
 			/* binary data most likely doesn't have newlines */
 			if (message_type != TYPE_TEXT) {
-				rc = handle_filter(line, sizeof(line), len);
+				handle_filter(&line);
 				break;
 			}
-
 			/*
 			 * This is a decoded line that may contain
 			 * multiple new lines.  Pass only one chunk
 			 * at a time to handle_filter()
 			 */
-			do {
-				while (op < line + len && *op != '\n')
-					*np++ = *op++;
-				*np = *op;
-				if (*np != 0) {
-					/* should be sitting on a new line */
-					*(++np) = 0;
-					op++;
-					rc = handle_filter(newline, sizeof(newline), np - newline);
-					np = newline;
-				}
-			} while (op < line + len);
+			lines = strbuf_split(&line, '\n');
+			for (it = lines; (sb = *it); it++) {
+				if (*(it + 1) == NULL) /* The last line */
+					if (sb->buf[sb->len - 1] != '\n') {
+						/* Partial line, save it for later. */
+						strbuf_addbuf(&prev, sb);
+						break;
+					}
+				handle_filter(sb);
+			}
 			/*
-			 * The partial chunk is saved in newline and will be
+			 * The partial chunk is saved in "prev" and will be
 			 * appended by the next iteration of read_line_with_nul().
 			 */
+			strbuf_list_free(lines);
 			break;
 		}
 		default:
-			rc = handle_filter(line, sizeof(line), len);
+			handle_filter(&line);
 		}
-		if (rc)
-			/* nothing left to filter */
-			break;
-	} while ((len = read_line_with_nul(line, sizeof(line), fin)));
 
-	return;
+		strbuf_reset(&line);
+		if (strbuf_avail(&line) < 100)
+			strbuf_grow(&line, 100);
+	} while ((len = read_line_with_nul(line.buf, strbuf_avail(&line), fin)));
+
+handle_body_out:
+	strbuf_release(&prev);
 }
 
-static void output_header_lines(FILE *fout, const char *hdr, char *data)
+static void output_header_lines(FILE *fout, const char *hdr, const struct strbuf *data)
 {
+	const char *sp = data->buf;
 	while (1) {
-		char *ep = strchr(data, '\n');
+		char *ep = strchr(sp, '\n');
 		int len;
 		if (!ep)
-			len = strlen(data);
+			len = strlen(sp);
 		else
-			len = ep - data;
-		fprintf(fout, "%s: %.*s\n", hdr, len, data);
+			len = ep - sp;
+		fprintf(fout, "%s: %.*s\n", hdr, len, sp);
 		if (!ep)
 			break;
-		data = ep + 1;
+		sp = ep + 1;
 	}
 }
 
 static void handle_info(void)
 {
-	char *sub;
-	char *hdr;
+	struct strbuf *hdr;
 	int i;
 
 	for (i = 0; header[i]; i++) {
-
 		/* only print inbody headers if we output a patch file */
 		if (patch_lines && s_hdr_data[i])
 			hdr = s_hdr_data[i];
@@ -901,20 +849,18 @@ static void handle_info(void)
 			continue;
 
 		if (!memcmp(header[i], "Subject", 7)) {
-			if (keep_subject)
-				sub = hdr;
-			else {
-				sub = cleanup_subject(hdr);
-				cleanup_space(sub);
+			if (!keep_subject) {
+				cleanup_subject(hdr);
+				cleanup_space(hdr);
 			}
-			output_header_lines(fout, "Subject", sub);
+			output_header_lines(fout, "Subject", hdr);
 		} else if (!memcmp(header[i], "From", 4)) {
 			handle_from(hdr);
-			fprintf(fout, "Author: %s\n", name);
-			fprintf(fout, "Email: %s\n", email);
+			fprintf(fout, "Author: %s\n", name.buf);
+			fprintf(fout, "Email: %s\n", email.buf);
 		} else {
 			cleanup_space(hdr);
-			fprintf(fout, "%s: %s\n", header[i], hdr);
+			fprintf(fout, "%s: %s\n", header[i], hdr->buf);
 		}
 	}
 	fprintf(fout, "\n");
@@ -941,8 +887,8 @@ static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
 		return -1;
 	}
 
-	p_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(char *));
-	s_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(char *));
+	p_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(*p_hdr_data));
+	s_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(*s_hdr_data));
 
 	do {
 		peek = fgetc(in);
@@ -950,8 +896,8 @@ static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
 	ungetc(peek, in);
 
 	/* process the email header */
-	while (read_one_header_line(line, sizeof(line), fin))
-		check_header(line, sizeof(line), p_hdr_data, 1);
+	while (read_one_header_line(&line, fin))
+		check_header(&line, p_hdr_data, 1);
 
 	handle_body();
 	handle_info();
-- 
1.5.4.5

^ permalink raw reply related

* [PATCH] Add some useful functions for strbuf manipulation.
From: Lukas Sandström @ 2008-07-13 18:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Lukas Sandström, Git Mailing List
In-Reply-To: <487A4948.8080003@etek.chalmers.se>

Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
---
 strbuf.c |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 strbuf.h |    6 +++++
 2 files changed, 76 insertions(+), 0 deletions(-)

diff --git a/strbuf.c b/strbuf.c
index 7767170..6294940 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -60,6 +60,18 @@ void strbuf_grow(struct strbuf *sb, size_t extra)
 	ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
 }
 
+void strbuf_trim(struct strbuf *sb)
+{
+	char *b = sb->buf;
+	while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
+		sb->len--;
+	while(sb->len > 0 && isspace(*b)) {
+		b++;
+		sb->len--;
+	}
+	memmove(sb->buf, b, sb->len);
+	sb->buf[sb->len] = '\0';
+}
 void strbuf_rtrim(struct strbuf *sb)
 {
 	while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
@@ -67,6 +79,64 @@ void strbuf_rtrim(struct strbuf *sb)
 	sb->buf[sb->len] = '\0';
 }
 
+void strbuf_ltrim(struct strbuf *sb)
+{
+	char *b = sb->buf;
+	while(sb->len > 0 && isspace(*b)) {
+		b++;
+		sb->len--;
+	}
+	memmove(sb->buf, b, sb->len);
+	sb->buf[sb->len] = '\0';
+}
+
+void strbuf_tolower(struct strbuf *sb)
+{
+	int i;
+	for (i = 0; i < sb->len; i++)
+		sb->buf[i] = tolower(sb->buf[i]);
+}
+
+struct strbuf ** strbuf_split(const struct strbuf *sb, int delim)
+{
+	int alloc = 2, pos = 0;
+	char *n, *p;
+	struct strbuf **ret;
+	struct strbuf *t;
+
+	ret = xcalloc(alloc, sizeof(struct strbuf *));
+	p = n = sb->buf;
+	while (n < sb->buf + sb->len) {
+		int len;
+		n = memchr(n, delim, sb->len - (n - sb->buf));
+		if (pos + 1 >= alloc) {
+			alloc = alloc * 2;
+			ret = xrealloc(ret, sizeof(struct strbuf *) * alloc);
+		}
+		if (!n)
+			n = sb->buf + sb->len - 1;
+		len = n - p + 1;
+		t = xmalloc(sizeof(struct strbuf));
+		strbuf_init(t, len);
+		strbuf_add(t, p, len);
+		ret[pos] = t;
+		ret[++pos] = NULL;
+		p = ++n;
+	}
+	return ret;
+}
+
+void strbuf_list_free(struct strbuf ** sbs)
+{
+	struct strbuf **s = sbs;
+
+	while(*s) {
+		strbuf_release(*s);
+		free(*s++);
+	}
+	free(sbs);
+}
+
 int strbuf_cmp(const struct strbuf *a, const struct strbuf *b)
 {
 	int cmp;
diff --git a/strbuf.h b/strbuf.h
index a1b0143..5e65a3f 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -77,8 +77,14 @@ static inline void strbuf_setlen(struct strbuf *sb, size_t len) {
 #define strbuf_reset(sb)  strbuf_setlen(sb, 0)
 
 /*----- content related -----*/
+extern void strbuf_trim(struct strbuf *);
 extern void strbuf_rtrim(struct strbuf *);
+extern void strbuf_ltrim(struct strbuf *);
 extern int strbuf_cmp(const struct strbuf *, const struct strbuf *);
+extern void strbuf_tolower(struct strbuf *);
+
+extern struct strbuf ** strbuf_split(const struct strbuf*, int delim);
+extern void strbuf_list_free(struct strbuf **);
 
 /*----- add data in your buffer -----*/
 static inline void strbuf_addch(struct strbuf *sb, int c) {
-- 
1.5.4.5

^ permalink raw reply related

* [PATCH] Make some strbuf_*() struct strbuf arguments const.
From: Lukas Sandström @ 2008-07-13 18:28 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Lukas Sandström, Git Mailing List
In-Reply-To: <487A46C5.6000503@etek.chalmers.se>

Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se>
---

 strbuf.c |    2 +-
 strbuf.h |    6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/strbuf.c b/strbuf.c
index 4aed752..7767170 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -67,7 +67,7 @@ void strbuf_rtrim(struct strbuf *sb)
 	sb->buf[sb->len] = '\0';
 }
 
-int strbuf_cmp(struct strbuf *a, struct strbuf *b)
+int strbuf_cmp(const struct strbuf *a, const struct strbuf *b)
 {
 	int cmp;
 	if (a->len < b->len) {
diff --git a/strbuf.h b/strbuf.h
index faec229..a1b0143 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -61,7 +61,7 @@ static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) {
 }
 
 /*----- strbuf size related -----*/
-static inline size_t strbuf_avail(struct strbuf *sb) {
+static inline size_t strbuf_avail(const struct strbuf *sb) {
 	return sb->alloc ? sb->alloc - sb->len - 1 : 0;
 }
 
@@ -78,7 +78,7 @@ static inline void strbuf_setlen(struct strbuf *sb, size_t len) {
 
 /*----- content related -----*/
 extern void strbuf_rtrim(struct strbuf *);
-extern int strbuf_cmp(struct strbuf *, struct strbuf *);
+extern int strbuf_cmp(const struct strbuf *, const struct strbuf *);
 
 /*----- add data in your buffer -----*/
 static inline void strbuf_addch(struct strbuf *sb, int c) {
@@ -98,7 +98,7 @@ extern void strbuf_add(struct strbuf *, const void *, size_t);
 static inline void strbuf_addstr(struct strbuf *sb, const char *s) {
 	strbuf_add(sb, s, strlen(s));
 }
-static inline void strbuf_addbuf(struct strbuf *sb, struct strbuf *sb2) {
+static inline void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2) {
 	strbuf_add(sb, sb2->buf, sb2->len);
 }
 extern void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len);
-- 
1.5.4.5

^ permalink raw reply related

* Re: ! [PATCH/RFC] git-mailinfo: use strbuf's instead of fixed buffers
From: Lukas Sandström @ 2008-07-13 18:17 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <7vy747fx9x.fsf_-_@gitster.siamese.dyndns.org>

Junio C Hamano wrote:
> Lukas Sandström <lukass@etek.chalmers.se> writes:
> 
>> -static char *sanity_check(char *name, char *email)
>> +static void sanity_check(struct strbuf *out, struct strbuf *name, struct strbuf *email)
>>  {
>> -	int len = strlen(name);
>> -	if (len < 3 || len > 60)
>> -		return email;
>> -	if (strchr(name, '@') || strchr(name, '<') || strchr(name, '>'))
>> -		return email;
>> -	return name;
>> +	struct strbuf o = STRBUF_INIT;
>> +	if (name->len < 3 || name->len > 60)
>> +		strbuf_addbuf(&o, email);
>> +	if (strchr(name->buf, '@') || strchr(name->buf, '<') ||
>> +		strchr(name->buf, '>'))
>> +		strbuf_addbuf(&o, email);
>> +	strbuf_addbuf(&o, name);
>> +	strbuf_reset(out);
>> +	strbuf_addbuf(out, &o);
>> +	strbuf_release(&o);
> 
> This does not look like a correct conversion.  When name is too short or
> too long, we do not even look at name and return email straight.  Perhaps
> this would be more faithful conversion:
> 
> 	struct strbuf *src = name;
> 	if (name->len < 3 ||
>             60 < name->len ||
> 	    strchr(name->buf, '@') ||
> 	    strchr(name->buf, '<') ||
> 	    strchr(name->buf, '>'))
> 		src = email;
> 	else if (name == out)
>         	return;
> 	strbuf_reset(out);
> 	strbuf_addbuf(out, src);
> 
> It is not your fault, but sanity_check() is a grave misnomer for this
> function.  This does "get_sane_name" (i.e. we have name and email but if
> name does not look right, use email instead).

Right. I changed the name and used your implementation.

>> -static int bogus_from(char *line)
>> +static int bogus_from(const struct strbuf *line)
>>  {

[ ... ]

>>  	return 1;
>>  }
> 
> Conversion looks correct but its return value does not make much sense
> (again, not your fault).  bogus_from() is given a bogus looking from line
> (it is not about checking if it is bogus), and returns 0 if we already
> have e-mail address, if the from line does not have bra-ket for grabbing
> e-mail address for, but returns 1 if we managed to get name and email
> pairs.  The inconsistency does not matter only because its sole caller
> handle_from() returns its return value, and its caller discards it.  We
> may be better off declaring this function and handle_from() as void.
> 

Done.

>>  	/* The remainder is name.  It could be "John Doe <john.doe@xz>"
>>  	 * or "john.doe@xz (John Doe)", but we have whited out the
>>  	 * email part, so trim from both ends, possibly removing
>>  	 * the () pair at the end.
>>  	 */
> 
> Now, it should read "but we have removed the email part", I think.

Done.
>> +	strbuf_trim(from);
>> +	if (*from->buf == '(')
>> +		strbuf_remove(&name, 0, 1);
>> +	if (*(from->buf + from->len - 1) == ')')
> 
> Can from be empty at this point before this check?
> 

Yes. Added a test for that.

>> +		strbuf_setlen(from, from->len - 1);
>> +
>> +	sanity_check(&name, from, &email);
>>  	return 1;
>>  }
> 
> We used to copy the data from the argument (in_line) before munging it in
> this function, but now we are modifying it in place (from).  Does this
> upset our caller, or the original code was just doing an extra unnecessary
> copy?

No, it's ok with the current code, since when handle_from() is called, it's
the last time we look at the header[i] field. I changed it to copy its argument
anyway, for future-proofing.

> 
>> -static int handle_header(char *line, char *data, int ofs)
>> +static void handle_header(struct strbuf **out, const struct strbuf *line)
>>  {
>> -	if (!line || !data)
>> -		return 1;
>> -
>> -	strcpy(data, line+ofs);
>> +	if (!*out) {
>> +		*out = xmalloc(sizeof(struct strbuf));
>> +		strbuf_init(*out, line->len);
>> +	} else
>> +		strbuf_reset(*out);
>>  
>> -	return 0;
>> +	strbuf_addbuf(*out, (struct strbuf *)line); /* const warning */
>>  }
> 
> I think its second parameter can safely become "const struct strbuf *";
> perhaps we should fix the definition of strbuf_addbuf() in your first
> patch?
> 
Done.

>> @@ -173,180 +153,176 @@ static int slurp_attr(const char *line, const char *name, char *attr)
>>  	else
>>  		ends = "; \t";
>>  	sz = strcspn(ap, ends);
>> -	memcpy(attr, ap, sz);
>> -	attr[sz] = 0;
>> +	strbuf_add(attr, ap, sz);
>>  	return 1;
>>  }
>>  
>>  struct content_type {
>> -	char *boundary;
>> -	int boundary_len;
>> +	struct strbuf *boundary;
>>  };
>>  
>>  static struct content_type content[MAX_BOUNDARIES];
> 
> Wouldn't it make more sense to get rid of "struct content_type" altogether
> and use "struct strbuf *content[MAX_BOUNDARIES]" directly?

Sure.

I'll send a patch updated with your comments shortly.

/Lukas

^ permalink raw reply

* Re: [PATCH/Test] Build in merge is broken
From: Miklos Vajna @ 2008-07-13 17:46 UTC (permalink / raw)
  To: Sverre Hvammen Johansen; +Cc: git, Junio C Hamano
In-Reply-To: <20080713124100.GB10347@genesis.frugalware.org>

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

On Sun, Jul 13, 2008 at 02:41:00PM +0200, Miklos Vajna <vmiklos@frugalware.org> wrote:
> > The test case when run will record the parents that were asked for which is
> > fine.  However, only c2 is recorded as a parent in the commit object.  Both
> > c1 and c2 should have been recorded.  The merge is otherwise working
> > correctly.
> 
> Thanks for the testcase, I'm on it. ;-)

So far what I see is that the input for the reduce_heads() function is
(c1, c0, c2, c0, c1). The expected output would be (c1, c2), but the
actual output is c2. So I suspect the bug is not in builtin-merge.c
itself but in reduce_heads().

Hmm..

Adding Junio to Cc, who is the original author of reduce_heads().

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

^ permalink raw reply

* Re: [RFH] Finding all commits that touch the same files as a specific commit
From: Sverre Rabbelier @ 2008-07-13 14:43 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailinglist
In-Reply-To: <7viqvavao4.fsf@gitster.siamese.dyndns.org>

On Sun, Jul 13, 2008 at 3:24 AM, Junio C Hamano <gitster@pobox.com> wrote:

<explanation of the git log traversal machinery snipped>

> In order to follow renames reliably in a merge heavy history, you need to
> keep track of the pathname the file you are interested in appears as _in
> each commit_.  As you traverse down the history, you pass down the
> pathname to the parent you visit, so while you are traversing from 'x' to
> earlier 'x', you will keep following "git-gui/git-gui.sh", while you
> traverse down to 'o', you will inspect "git-gui.sh".
>
> The data structure the revision traversal machinery uses does not support
> this "path-per-commit" natively.

Would it be possible to go for a slightly less complicated approach
and instead of passing replacing the tracked file, append it? We
already have a list of files we are tracking, so I assume the data
structure does support that. Such would run with the risk of tracking
too much (e.g., you rename a.txt => b.txt, and then later on
create/rename a new a.txt which is then tracked as well).

> This is the reason "git-blame" uses its own traversal engine.  It keeps
> track of <commit, path> pairs so that it can mark which line came from
> what path in what commit.  When copy/move detection are used, we can even
> notice that the contents we are interested in came from more than one file
> in the same commits, and the data structure supports it (i.e. it is not
> just a pointer to a single string from "struct commit").

So what could be done is use a blame-like mechanism that invokes
rename detection on each interesting commit and then record that
information? Purely hypothetical though, since I know neither and have
no time to do so.

> For the purpose of "git log" traversal and the "file renames" people
> usually talk about, this is overkill; you should however be able to
> backport the basic idea to revision machinery, if you really cared.

Right, that'd teach git log how to follow across renames in an
intelligent manner that works also for non-linear histories at the
cost of using up more memory and cpu?

> In a real history, "file rename" is a very ill defined concept and is not
> always useful in practice.  I did a fairly detailed analysis on one
> real-world history more than two years ago, which is found here:
>
>    http://thread.gmane.org/gmane.comp.version-control.git/13746/focus=13769

Aye, I agree that a 'rename' is hard to define and that a lot of
effort could be put into supporting 'renames' that are not trivial
(e.g., more complex than 'git mv foo.txt bar.txt').

> In our own "git.git" history, the evolution of what finally landed in
> revision.c is interesting.  The interesting part of content movement never
> involved any file renames --- only bits and pieces migrated over across
> many files.  That is not something "file rename tracking", even with an
> extension to the revision traversal machinery to keep one path per commit
> to record the file you are interested in, can ever give meaningful
> explanation of the history.  You need a lot more fine grained "blame"
> traversal machinery for that.

This makes sense, but it (using blame traversal machinery) is overkill
for what I am interested in. What I think would be a good goal in
supporting is the subtree merge strategy. It would be nice if 'git log
--follow-subtree-merge refspec -- filefilter' or such would Just Work
(TM). Perhaps that the hunk-tracking I am working on with Dscho could
help make 'git log --numstat' more accurate. Those two combined (git
log being able to follow across subtree merges and being able to
recognise hunks being moved) would be all that I need.


-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* Re: git pull is slow
From: Johannes Schindelin @ 2008-07-13 13:59 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Stephan Hennig, Nicolas Pitre, Andreas Ericsson, git
In-Reply-To: <20080713011512.GB31050@spearce.org>

Hi,

On Sun, 13 Jul 2008, Shawn O. Pearce wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> > On Sat, 12 Jul 2008, Stephan Hennig wrote:
> > > 
> > > Thanks for having a look at this!  What does "problem with the pack" 
> > > mean?  Do you think it is a Git problem (client or server side?) or just 
> > > a misconfiguration?
> > 
> > I thought that the blobs in the pack are just too similar.  That makes for 
> > a good compression, since you get many relatively small deltas.  But it 
> > also makes for a lot of work to reconstruct the blobs.
> > 
> > I suspected that you run out of space for the cache holding some 
> > reconstructed blobs (to prevent reconstructing all of them from scratch).
> ...
> > Whoa. As you can see, your puny little 3.3 megabyte pack is blown to a 
> > full 555 megabyte in RAM.
> ...
> > I expect this to touch the resolve_delta() function of index-pack.c in a 
> > major way, though.
> 
> Yea, that's going to be ugly.  The "cache" you speak of above is held on 
> the call stack as resolv_delta() recurses through the delta chain to 
> reconstruct objects and generate their SHA-1s.  There isn't a way to 
> release these objects when memory gets low so your worst case scenario 
> is a 100M+ blob with a delta chain of 50 or more - that will take you 5G 
> of memory to pass through index-pack.

Actually, there is...

You would only need to tap into the "release_pack_memory()" mechanism, 
adding a sort of a "smart pointer" that knows how to reconstruct its 
contents.

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH] bash completion: Improve responsiveness of git-log completion
From: Johannes Schindelin @ 2008-07-13 13:55 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Junio C Hamano, git, Petr Baudis
In-Reply-To: <20080713023742.GA31760@spearce.org>

Hi,

On Sun, 13 Jul 2008, Shawn O. Pearce wrote:

>  Does this make things better?  Or worse?  I'm not seeing a huge
>  difference on my own system.  Maybe its too fast these days...

I see an incredible difference.  I do not have the means to measure at the 
moment, but it jumped from several seconds (which qualifies for a synonym 
to "eternity" in Git speak, as you know) to almost instantaneous.

Good job,
Dscho

^ permalink raw reply

* [PATCH] Make usage strings dash-less
From: Stephan Beyer @ 2008-07-13 13:36 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Pierre Habouzit, Stephan Beyer

When you misuse a git command, you are shown the usage string.
But this is currently shown in the dashed form.  So if you just
copy what you see, it will not work, when the dashed form
is no longer supported.

This patch makes git commands show the dash-less version.

For shell scripts that do not specify OPTIONS_SPEC, git-sh-setup.sh
generates a dash-less usage string now.

Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
---

Hi,

the stupid part of the patch is generated using:

	sed -i 's/^\([ \t]*\)"git-/\1"git /g' *.c
	sed -i 's/^git-/git /' git-*sh

There haven't been any false positives,
but I cannot guarantee that alle occurences in *.c and *.sh
have been replaced. ;)

Perl files were changed manually.
There, "$0" stuff was replaced by constant "git foo" strings.

Regards,
  Stephan

 builtin-add.c            |    2 +-
 builtin-apply.c          |    2 +-
 builtin-archive.c        |    2 +-
 builtin-blame.c          |    2 +-
 builtin-branch.c         |    8 ++++----
 builtin-cat-file.c       |    4 ++--
 builtin-check-attr.c     |    2 +-
 builtin-checkout-index.c |    2 +-
 builtin-clean.c          |    2 +-
 builtin-clone.c          |    2 +-
 builtin-commit.c         |    4 ++--
 builtin-config.c         |    2 +-
 builtin-count-objects.c  |    2 +-
 builtin-describe.c       |    2 +-
 builtin-diff-files.c     |    2 +-
 builtin-diff-index.c     |    2 +-
 builtin-diff-tree.c      |    2 +-
 builtin-diff.c           |    2 +-
 builtin-fast-export.c    |    2 +-
 builtin-fetch-pack.c     |    2 +-
 builtin-fetch.c          |    2 +-
 builtin-fmt-merge-msg.c  |    2 +-
 builtin-for-each-ref.c   |    2 +-
 builtin-fsck.c           |    2 +-
 builtin-gc.c             |    2 +-
 builtin-grep.c           |    2 +-
 builtin-init-db.c        |    2 +-
 builtin-log.c            |    2 +-
 builtin-ls-files.c       |    2 +-
 builtin-ls-remote.c      |    2 +-
 builtin-ls-tree.c        |    2 +-
 builtin-mailinfo.c       |    2 +-
 builtin-mailsplit.c      |    2 +-
 builtin-merge-base.c     |    2 +-
 builtin-mv.c             |    2 +-
 builtin-name-rev.c       |    2 +-
 builtin-pack-refs.c      |    2 +-
 builtin-prune-packed.c   |    2 +-
 builtin-prune.c          |    2 +-
 builtin-push.c           |    2 +-
 builtin-reflog.c         |    6 +++---
 builtin-rerere.c         |    2 +-
 builtin-reset.c          |    4 ++--
 builtin-rev-list.c       |    2 +-
 builtin-rev-parse.c      |    2 +-
 builtin-revert.c         |    4 ++--
 builtin-rm.c             |    2 +-
 builtin-send-pack.c      |    2 +-
 builtin-shortlog.c       |    2 +-
 builtin-show-branch.c    |    2 +-
 builtin-symbolic-ref.c   |    2 +-
 builtin-tag.c            |    8 ++++----
 builtin-tar-tree.c       |    2 +-
 builtin-update-index.c   |    2 +-
 builtin-update-ref.c     |    4 ++--
 builtin-upload-archive.c |    6 +++---
 builtin-verify-tag.c     |    2 +-
 builtin-write-tree.c     |    2 +-
 daemon.c                 |    2 +-
 fast-import.c            |    2 +-
 git-am.sh                |    6 +++---
 git-archimport.perl      |    4 ++--
 git-cvsexportcommit.perl |    2 +-
 git-cvsimport.perl       |    2 +-
 git-cvsserver.perl       |    2 +-
 git-instaweb.sh          |    2 +-
 git-merge.sh             |    4 ++--
 git-pull.sh              |    2 +-
 git-quiltimport.sh       |    2 +-
 git-relink.perl          |    2 +-
 git-repack.sh            |    2 +-
 git-send-email.perl      |    2 +-
 git-sh-setup.sh          |    7 ++++---
 git-svn.perl             |    2 +-
 hash-object.c            |    2 +-
 help.c                   |    2 +-
 http-push.c              |    2 +-
 index-pack.c             |    2 +-
 pack-redundant.c         |    2 +-
 update-server-info.c     |    2 +-
 80 files changed, 102 insertions(+), 101 deletions(-)

diff --git a/builtin-add.c b/builtin-add.c
index 9930cf5..bf13aa3 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -16,7 +16,7 @@
 #include "parse-options.h"
 
 static const char * const builtin_add_usage[] = {
-	"git-add [options] [--] <filepattern>...",
+	"git add [options] [--] <filepattern>...",
 	NULL
 };
 static int patch_interactive = 0, add_interactive = 0;
diff --git a/builtin-apply.c b/builtin-apply.c
index d13313f..e15471b 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -46,7 +46,7 @@ static const char *fake_ancestor;
 static int line_termination = '\n';
 static unsigned long p_context = ULONG_MAX;
 static const char apply_usage[] =
-"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--cached] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [--reverse] [--reject] [--verbose] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|fix|error|error-all>] <patch>...";
+"git apply [--stat] [--numstat] [--summary] [--check] [--index] [--cached] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [--reverse] [--reject] [--verbose] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|fix|error|error-all>] <patch>...";
 
 static enum ws_error_action {
 	nowarn_ws_error,
diff --git a/builtin-archive.c b/builtin-archive.c
index c2e0c1e..5cca460 100644
--- a/builtin-archive.c
+++ b/builtin-archive.c
@@ -13,7 +13,7 @@
 #include "attr.h"
 
 static const char archive_usage[] = \
-"git-archive --format=<fmt> [--prefix=<prefix>/] [--verbose] [<extra>] <tree-ish> [path...]";
+"git archive --format=<fmt> [--prefix=<prefix>/] [--verbose] [<extra>] <tree-ish> [path...]";
 
 static struct archiver_desc
 {
diff --git a/builtin-blame.c b/builtin-blame.c
index b451f6c..91850a5 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -20,7 +20,7 @@
 #include "mailmap.h"
 
 static char blame_usage[] =
-"git-blame [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-p] [-w] [-L n,m] [-S <revs-file>] [-M] [-C] [-C] [--contents <filename>] [--incremental] [commit] [--] file\n"
+"git blame [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-p] [-w] [-L n,m] [-S <revs-file>] [-M] [-C] [-C] [--contents <filename>] [--incremental] [commit] [--] file\n"
 "  -c                  Use the same output mode as git-annotate (Default: off)\n"
 "  -b                  Show blank SHA-1 for boundary commits (Default: off)\n"
 "  -l                  Show long commit SHA1 (Default: off)\n"
diff --git a/builtin-branch.c b/builtin-branch.c
index d279702..5cc3771 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -15,10 +15,10 @@
 #include "branch.h"
 
 static const char * const builtin_branch_usage[] = {
-	"git-branch [options] [-r | -a] [--merged | --no-merged]",
-	"git-branch [options] [-l] [-f] <branchname> [<start-point>]",
-	"git-branch [options] [-r] (-d | -D) <branchname>",
-	"git-branch [options] (-m | -M) [<oldbranch>] <newbranch>",
+	"git branch [options] [-r | -a] [--merged | --no-merged]",
+	"git branch [options] [-l] [-f] <branchname> [<start-point>]",
+	"git branch [options] [-r] (-d | -D) <branchname>",
+	"git branch [options] (-m | -M) [<oldbranch>] <newbranch>",
 	NULL
 };
 
diff --git a/builtin-cat-file.c b/builtin-cat-file.c
index 880e75a..7441a56 100644
--- a/builtin-cat-file.c
+++ b/builtin-cat-file.c
@@ -202,8 +202,8 @@ static int batch_objects(int print_contents)
 }
 
 static const char * const cat_file_usage[] = {
-	"git-cat-file [-t|-s|-e|-p|<type>] <sha1>",
-	"git-cat-file [--batch|--batch-check] < <list_of_sha1s>",
+	"git cat-file [-t|-s|-e|-p|<type>] <sha1>",
+	"git cat-file [--batch|--batch-check] < <list_of_sha1s>",
 	NULL
 };
 
diff --git a/builtin-check-attr.c b/builtin-check-attr.c
index 6afdfa1..cb783fc 100644
--- a/builtin-check-attr.c
+++ b/builtin-check-attr.c
@@ -4,7 +4,7 @@
 #include "quote.h"
 
 static const char check_attr_usage[] =
-"git-check-attr attr... [--] pathname...";
+"git check-attr attr... [--] pathname...";
 
 int cmd_check_attr(int argc, const char **argv, const char *prefix)
 {
diff --git a/builtin-checkout-index.c b/builtin-checkout-index.c
index eb1fc9a..71ebabf 100644
--- a/builtin-checkout-index.c
+++ b/builtin-checkout-index.c
@@ -154,7 +154,7 @@ static void checkout_all(const char *prefix, int prefix_length)
 }
 
 static const char checkout_cache_usage[] =
-"git-checkout-index [-u] [-q] [-a] [-f] [-n] [--stage=[123]|all] [--prefix=<string>] [--temp] [--] <file>...";
+"git checkout-index [-u] [-q] [-a] [-f] [-n] [--stage=[123]|all] [--prefix=<string>] [--temp] [--] <file>...";
 
 static struct lock_file lock_file;
 
diff --git a/builtin-clean.c b/builtin-clean.c
index 80a7ff9..48bf29f 100644
--- a/builtin-clean.c
+++ b/builtin-clean.c
@@ -15,7 +15,7 @@
 static int force = -1; /* unset */
 
 static const char *const builtin_clean_usage[] = {
-	"git-clean [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...",
+	"git clean [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...",
 	NULL
 };
 
diff --git a/builtin-clone.c b/builtin-clone.c
index ec36209..8112716 100644
--- a/builtin-clone.c
+++ b/builtin-clone.c
@@ -29,7 +29,7 @@
  *
  */
 static const char * const builtin_clone_usage[] = {
-	"git-clone [options] [--] <repo> [<dir>]",
+	"git clone [options] [--] <repo> [<dir>]",
 	NULL
 };
 
diff --git a/builtin-commit.c b/builtin-commit.c
index 745c11e..41cf5f2 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -25,12 +25,12 @@
 #include "unpack-trees.h"
 
 static const char * const builtin_commit_usage[] = {
-	"git-commit [options] [--] <filepattern>...",
+	"git commit [options] [--] <filepattern>...",
 	NULL
 };
 
 static const char * const builtin_status_usage[] = {
-	"git-status [options] [--] <filepattern>...",
+	"git status [options] [--] <filepattern>...",
 	NULL
 };
 
diff --git a/builtin-config.c b/builtin-config.c
index 39f63d7..0cf191a 100644
--- a/builtin-config.c
+++ b/builtin-config.c
@@ -3,7 +3,7 @@
 #include "color.h"
 
 static const char git_config_set_usage[] =
-"git-config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int | --bool-or-int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default] | --get-colorbool name [stdout-is-tty]";
+"git config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int | --bool-or-int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default] | --get-colorbool name [stdout-is-tty]";
 
 static char *key;
 static regex_t *key_regexp;
diff --git a/builtin-count-objects.c b/builtin-count-objects.c
index f00306f..91b5487 100644
--- a/builtin-count-objects.c
+++ b/builtin-count-objects.c
@@ -67,7 +67,7 @@ static void count_objects(DIR *d, char *path, int len, int verbose,
 }
 
 static char const * const count_objects_usage[] = {
-	"git-count-objects [-v]",
+	"git count-objects [-v]",
 	NULL
 };
 
diff --git a/builtin-describe.c b/builtin-describe.c
index e515f9c..5dabca9 100644
--- a/builtin-describe.c
+++ b/builtin-describe.c
@@ -10,7 +10,7 @@
 #define MAX_TAGS	(FLAG_BITS - 1)
 
 static const char * const describe_usage[] = {
-	"git-describe [options] <committish>*",
+	"git describe [options] <committish>*",
 	NULL
 };
 
diff --git a/builtin-diff-files.c b/builtin-diff-files.c
index 384d871..9bf10bb 100644
--- a/builtin-diff-files.c
+++ b/builtin-diff-files.c
@@ -10,7 +10,7 @@
 #include "builtin.h"
 
 static const char diff_files_usage[] =
-"git-diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]"
+"git diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]"
 COMMON_DIFF_OPTIONS_HELP;
 
 int cmd_diff_files(int argc, const char **argv, const char *prefix)
diff --git a/builtin-diff-index.c b/builtin-diff-index.c
index 2f44ebf..17d851b 100644
--- a/builtin-diff-index.c
+++ b/builtin-diff-index.c
@@ -5,7 +5,7 @@
 #include "builtin.h"
 
 static const char diff_cache_usage[] =
-"git-diff-index [-m] [--cached] "
+"git diff-index [-m] [--cached] "
 "[<common diff options>] <tree-ish> [<path>...]"
 COMMON_DIFF_OPTIONS_HELP;
 
diff --git a/builtin-diff-tree.c b/builtin-diff-tree.c
index 9d2a48f..415cb16 100644
--- a/builtin-diff-tree.c
+++ b/builtin-diff-tree.c
@@ -53,7 +53,7 @@ static int diff_tree_stdin(char *line)
 }
 
 static const char diff_tree_usage[] =
-"git-diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] "
+"git diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] "
 "[<common diff options>] <tree-ish> [<tree-ish>] [<path>...]\n"
 "  -r            diff recursively\n"
 "  --root        include the initial commit as diff against /dev/null\n"
diff --git a/builtin-diff.c b/builtin-diff.c
index 4c289e7..faaa85a 100644
--- a/builtin-diff.c
+++ b/builtin-diff.c
@@ -21,7 +21,7 @@ struct blobinfo {
 };
 
 static const char builtin_diff_usage[] =
-"git-diff <options> <rev>{0,2} -- <path>*";
+"git diff <options> <rev>{0,2} -- <path>*";
 
 static void stuff_change(struct diff_options *opt,
 			 unsigned old_mode, unsigned new_mode,
diff --git a/builtin-fast-export.c b/builtin-fast-export.c
index 75132ba..76f3167 100644
--- a/builtin-fast-export.c
+++ b/builtin-fast-export.c
@@ -18,7 +18,7 @@
 #include "parse-options.h"
 
 static const char *fast_export_usage[] = {
-	"git-fast-export [rev-list-opts]",
+	"git fast-export [rev-list-opts]",
 	NULL
 };
 
diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c
index 1ea7040..273239a 100644
--- a/builtin-fetch-pack.c
+++ b/builtin-fetch-pack.c
@@ -18,7 +18,7 @@ static struct fetch_pack_args args = {
 };
 
 static const char fetch_pack_usage[] =
-"git-fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]";
+"git fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]";
 
 #define COMPLETE	(1U << 0)
 #define COMMON		(1U << 1)
diff --git a/builtin-fetch.c b/builtin-fetch.c
index 97fdc51..61de50a 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -12,7 +12,7 @@
 #include "parse-options.h"
 
 static const char * const builtin_fetch_usage[] = {
-	"git-fetch [options] [<repository> <refspec>...]",
+	"git fetch [options] [<repository> <refspec>...]",
 	NULL
 };
 
diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c
index b892621..b34b01f 100644
--- a/builtin-fmt-merge-msg.c
+++ b/builtin-fmt-merge-msg.c
@@ -6,7 +6,7 @@
 #include "tag.h"
 
 static const char *fmt_merge_msg_usage =
-	"git-fmt-merge-msg [--log] [--no-log] [--file <file>]";
+	"git fmt-merge-msg [--log] [--no-log] [--file <file>]";
 
 static int merge_summary;
 
diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c
index fef93d7..76282ad 100644
--- a/builtin-for-each-ref.c
+++ b/builtin-for-each-ref.c
@@ -831,7 +831,7 @@ int opt_parse_sort(const struct option *opt, const char *arg, int unset)
 }
 
 static char const * const for_each_ref_usage[] = {
-	"git-for-each-ref [options] [<pattern>]",
+	"git for-each-ref [options] [<pattern>]",
 	NULL
 };
 
diff --git a/builtin-fsck.c b/builtin-fsck.c
index b0f9648..7326dc3 100644
--- a/builtin-fsck.c
+++ b/builtin-fsck.c
@@ -539,7 +539,7 @@ static int fsck_cache_tree(struct cache_tree *it)
 }
 
 static char const * const fsck_usage[] = {
-	"git-fsck [options] [<object>...]",
+	"git fsck [options] [<object>...]",
 	NULL
 };
 
diff --git a/builtin-gc.c b/builtin-gc.c
index f5625bb..fac200e 100644
--- a/builtin-gc.c
+++ b/builtin-gc.c
@@ -18,7 +18,7 @@
 #define FAILED_RUN "failed to run %s"
 
 static const char * const builtin_gc_usage[] = {
-	"git-gc [options]",
+	"git gc [options]",
 	NULL
 };
 
diff --git a/builtin-grep.c b/builtin-grep.c
index ef29910..0cac395 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -495,7 +495,7 @@ static int grep_object(struct grep_opt *opt, const char **paths,
 }
 
 static const char builtin_grep_usage[] =
-"git-grep <option>* <rev>* [-e] <pattern> [<path>...]";
+"git grep <option>* <rev>* [-e] <pattern> [<path>...]";
 
 static const char emsg_invalid_context_len[] =
 "%s: invalid context length argument";
diff --git a/builtin-init-db.c b/builtin-init-db.c
index e23b843..53aff68 100644
--- a/builtin-init-db.c
+++ b/builtin-init-db.c
@@ -364,7 +364,7 @@ static int guess_repository_type(const char *git_dir)
 }
 
 static const char init_db_usage[] =
-"git-init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]";
+"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]";
 
 /*
  * If you want to, you can share the DB area with any number of branches.
diff --git a/builtin-log.c b/builtin-log.c
index 430d876..cb3b33a 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -1082,7 +1082,7 @@ static int add_pending_commit(const char *arg, struct rev_info *revs, int flags)
 }
 
 static const char cherry_usage[] =
-"git-cherry [-v] <upstream> [<head>] [<limit>]";
+"git cherry [-v] <upstream> [<head>] [<limit>]";
 int cmd_cherry(int argc, const char **argv, const char *prefix)
 {
 	struct rev_info revs;
diff --git a/builtin-ls-files.c b/builtin-ls-files.c
index 75ba422..e8d568e 100644
--- a/builtin-ls-files.c
+++ b/builtin-ls-files.c
@@ -423,7 +423,7 @@ int report_path_error(const char *ps_matched, const char **pathspec, int prefix_
 }
 
 static const char ls_files_usage[] =
-	"git-ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
+	"git ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
 	"[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] "
 	"[ --exclude-per-directory=<filename> ] [--exclude-standard] "
 	"[--full-name] [--abbrev] [--] [<file>]*";
diff --git a/builtin-ls-remote.c b/builtin-ls-remote.c
index 06ab8da..c21b841 100644
--- a/builtin-ls-remote.c
+++ b/builtin-ls-remote.c
@@ -4,7 +4,7 @@
 #include "remote.h"
 
 static const char ls_remote_usage[] =
-"git-ls-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>";
+"git ls-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>";
 
 /*
  * Is there one among the list of patterns that match the tail part
diff --git a/builtin-ls-tree.c b/builtin-ls-tree.c
index f4a75dd..ac71358 100644
--- a/builtin-ls-tree.c
+++ b/builtin-ls-tree.c
@@ -23,7 +23,7 @@ static int chomp_prefix;
 static const char *ls_tree_prefix;
 
 static const char ls_tree_usage[] =
-	"git-ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--abbrev[=<n>]] <tree-ish> [path...]";
+	"git ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--abbrev[=<n>]] <tree-ish> [path...]";
 
 static int show_recursive(const char *base, int baselen, const char *pathname)
 {
diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
index fa6e8f9..b3d281e 100644
--- a/builtin-mailinfo.c
+++ b/builtin-mailinfo.c
@@ -960,7 +960,7 @@ static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
 }
 
 static const char mailinfo_usage[] =
-	"git-mailinfo [-k] [-u | --encoding=<encoding>] msg patch <mail >info";
+	"git mailinfo [-k] [-u | --encoding=<encoding>] msg patch <mail >info";
 
 int cmd_mailinfo(int argc, const char **argv, const char *prefix)
 {
diff --git a/builtin-mailsplit.c b/builtin-mailsplit.c
index ae2b4cb..0dc4cd9 100644
--- a/builtin-mailsplit.c
+++ b/builtin-mailsplit.c
@@ -9,7 +9,7 @@
 #include "path-list.h"
 
 static const char git_mailsplit_usage[] =
-"git-mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> <mbox>|<Maildir>...";
+"git mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> <mbox>|<Maildir>...";
 
 static int is_from_line(const char *line, int len)
 {
diff --git a/builtin-merge-base.c b/builtin-merge-base.c
index bcf9395..1cb2925 100644
--- a/builtin-merge-base.c
+++ b/builtin-merge-base.c
@@ -20,7 +20,7 @@ static int show_merge_base(struct commit *rev1, struct commit *rev2, int show_al
 }
 
 static const char merge_base_usage[] =
-"git-merge-base [--all] <commit-id> <commit-id>";
+"git merge-base [--all] <commit-id> <commit-id>";
 
 int cmd_merge_base(int argc, const char **argv, const char *prefix)
 {
diff --git a/builtin-mv.c b/builtin-mv.c
index 5530e11..ba9ceda 100644
--- a/builtin-mv.c
+++ b/builtin-mv.c
@@ -11,7 +11,7 @@
 #include "parse-options.h"
 
 static const char * const builtin_mv_usage[] = {
-	"git-mv [options] <source>... <destination>",
+	"git mv [options] <source>... <destination>",
 	NULL
 };
 
diff --git a/builtin-name-rev.c b/builtin-name-rev.c
index f153da0..85612c4 100644
--- a/builtin-name-rev.c
+++ b/builtin-name-rev.c
@@ -172,7 +172,7 @@ static void show_name(const struct object *obj,
 }
 
 static char const * const name_rev_usage[] = {
-	"git-name-rev [options] ( --all | --stdin | <commit>... )",
+	"git name-rev [options] ( --all | --stdin | <commit>... )",
 	NULL
 };
 
diff --git a/builtin-pack-refs.c b/builtin-pack-refs.c
index ff90aef..34246df 100644
--- a/builtin-pack-refs.c
+++ b/builtin-pack-refs.c
@@ -3,7 +3,7 @@
 #include "pack-refs.h"
 
 static char const * const pack_refs_usage[] = {
-	"git-pack-refs [options]",
+	"git pack-refs [options]",
 	NULL
 };
 
diff --git a/builtin-prune-packed.c b/builtin-prune-packed.c
index 241afbb..10cb8df 100644
--- a/builtin-prune-packed.c
+++ b/builtin-prune-packed.c
@@ -3,7 +3,7 @@
 #include "progress.h"
 
 static const char prune_packed_usage[] =
-"git-prune-packed [-n] [-q]";
+"git prune-packed [-n] [-q]";
 
 #define DRY_RUN 01
 #define VERBOSE 02
diff --git a/builtin-prune.c b/builtin-prune.c
index bd3d2f6..7de4cab 100644
--- a/builtin-prune.c
+++ b/builtin-prune.c
@@ -7,7 +7,7 @@
 #include "parse-options.h"
 
 static const char * const prune_usage[] = {
-	"git-prune [-n] [--expire <time>] [--] [<head>...]",
+	"git prune [-n] [--expire <time>] [--] [<head>...]",
 	NULL
 };
 static int show_only;
diff --git a/builtin-push.c b/builtin-push.c
index b35aad6..03db28c 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -10,7 +10,7 @@
 #include "parse-options.h"
 
 static const char * const push_usage[] = {
-	"git-push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]",
+	"git push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]",
 	NULL,
 };
 
diff --git a/builtin-reflog.c b/builtin-reflog.c
index 125d455..0c34e37 100644
--- a/builtin-reflog.c
+++ b/builtin-reflog.c
@@ -13,9 +13,9 @@
  */
 
 static const char reflog_expire_usage[] =
-"git-reflog (show|expire) [--verbose] [--dry-run] [--stale-fix] [--expire=<time>] [--expire-unreachable=<time>] [--all] <refs>...";
+"git reflog (show|expire) [--verbose] [--dry-run] [--stale-fix] [--expire=<time>] [--expire-unreachable=<time>] [--all] <refs>...";
 static const char reflog_delete_usage[] =
-"git-reflog delete [--verbose] [--dry-run] [--rewrite] [--updateref] <refs>...";
+"git reflog delete [--verbose] [--dry-run] [--rewrite] [--updateref] <refs>...";
 
 static unsigned long default_reflog_expire;
 static unsigned long default_reflog_expire_unreachable;
@@ -630,7 +630,7 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)
  */
 
 static const char reflog_usage[] =
-"git-reflog (expire | ...)";
+"git reflog (expire | ...)";
 
 int cmd_reflog(int argc, const char **argv, const char *prefix)
 {
diff --git a/builtin-rerere.c b/builtin-rerere.c
index 839b26e..62ef7cf 100644
--- a/builtin-rerere.c
+++ b/builtin-rerere.c
@@ -7,7 +7,7 @@
 #include <time.h>
 
 static const char git_rerere_usage[] =
-"git-rerere [clear | status | diff | gc]";
+"git rerere [clear | status | diff | gc]";
 
 /* these values are days */
 static int cutoff_noresolve = 15;
diff --git a/builtin-reset.c b/builtin-reset.c
index a032169..2e5a886 100644
--- a/builtin-reset.c
+++ b/builtin-reset.c
@@ -20,8 +20,8 @@
 #include "parse-options.h"
 
 static const char * const git_reset_usage[] = {
-	"git-reset [--mixed | --soft | --hard] [-q] [<commit>]",
-	"git-reset [--mixed] <commit> [--] <paths>...",
+	"git reset [--mixed | --soft | --hard] [-q] [<commit>]",
+	"git reset [--mixed] <commit> [--] <paths>...",
 	NULL
 };
 
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index 54b6672..114114b 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -17,7 +17,7 @@
 #define COUNTED		(1u<<16)
 
 static const char rev_list_usage[] =
-"git-rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
+"git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
 "  limiting output:\n"
 "    --max-count=nr\n"
 "    --max-age=epoch\n"
diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index a7860ed..aa71f4a 100644
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
@@ -268,7 +268,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
 {
 	static int keep_dashdash = 0;
 	static char const * const parseopt_usage[] = {
-		"git-rev-parse --parseopt [options] -- [<args>...]",
+		"git rev-parse --parseopt [options] -- [<args>...]",
 		NULL
 	};
 	static struct option parseopt_opts[] = {
diff --git a/builtin-revert.c b/builtin-revert.c
index 0270f9b..ebfa3bb 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -24,12 +24,12 @@
  */
 
 static const char * const revert_usage[] = {
-	"git-revert [options] <commit-ish>",
+	"git revert [options] <commit-ish>",
 	NULL
 };
 
 static const char * const cherry_pick_usage[] = {
-	"git-cherry-pick [options] <commit-ish>",
+	"git cherry-pick [options] <commit-ish>",
 	NULL
 };
 
diff --git a/builtin-rm.c b/builtin-rm.c
index 22c9bd1..56454ec 100644
--- a/builtin-rm.c
+++ b/builtin-rm.c
@@ -11,7 +11,7 @@
 #include "parse-options.h"
 
 static const char * const builtin_rm_usage[] = {
-	"git-rm [options] [--] <file>...",
+	"git rm [options] [--] <file>...",
 	NULL
 };
 
diff --git a/builtin-send-pack.c b/builtin-send-pack.c
index a708d0a..7588d22 100644
--- a/builtin-send-pack.c
+++ b/builtin-send-pack.c
@@ -8,7 +8,7 @@
 #include "send-pack.h"
 
 static const char send_pack_usage[] =
-"git-send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
+"git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
 "  --all and explicit <ref> specification are mutually exclusive.";
 
 static struct send_pack_args args = {
diff --git a/builtin-shortlog.c b/builtin-shortlog.c
index e6a2865..fcb0da9 100644
--- a/builtin-shortlog.c
+++ b/builtin-shortlog.c
@@ -9,7 +9,7 @@
 #include "shortlog.h"
 
 static const char shortlog_usage[] =
-"git-shortlog [-n] [-s] [-e] [-w] [<commit-id>... ]";
+"git shortlog [-n] [-s] [-e] [-w] [<commit-id>... ]";
 
 static int compare_by_number(const void *a1, const void *a2)
 {
diff --git a/builtin-show-branch.c b/builtin-show-branch.c
index 93047f5..233eed4 100644
--- a/builtin-show-branch.c
+++ b/builtin-show-branch.c
@@ -4,7 +4,7 @@
 #include "builtin.h"
 
 static const char show_branch_usage[] =
-"git-show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base ] [--topics] [<refs>...] | --reflog[=n[,b]] <branch>";
+"git show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base ] [--topics] [<refs>...] | --reflog[=n[,b]] <branch>";
 static const char show_branch_usage_reflog[] =
 "--reflog is incompatible with --all, --remotes, --independent or --merge-base";
 
diff --git a/builtin-symbolic-ref.c b/builtin-symbolic-ref.c
index b49bdb6..bfc78bb 100644
--- a/builtin-symbolic-ref.c
+++ b/builtin-symbolic-ref.c
@@ -4,7 +4,7 @@
 #include "parse-options.h"
 
 static const char * const git_symbolic_ref_usage[] = {
-	"git-symbolic-ref [options] name [ref]",
+	"git symbolic-ref [options] name [ref]",
 	NULL
 };
 
diff --git a/builtin-tag.c b/builtin-tag.c
index 3c97c69..73cb7bf 100644
--- a/builtin-tag.c
+++ b/builtin-tag.c
@@ -14,10 +14,10 @@
 #include "parse-options.h"
 
 static const char * const git_tag_usage[] = {
-	"git-tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
-	"git-tag -d <tagname>...",
-	"git-tag -l [-n[<num>]] [<pattern>]",
-	"git-tag -v <tagname>...",
+	"git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
+	"git tag -d <tagname>...",
+	"git tag -l [-n[<num>]] [<pattern>]",
+	"git tag -v <tagname>...",
 	NULL
 };
 
diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c
index b04719e..f4bea4a 100644
--- a/builtin-tar-tree.c
+++ b/builtin-tar-tree.c
@@ -8,7 +8,7 @@
 #include "quote.h"
 
 static const char tar_tree_usage[] =
-"git-tar-tree [--remote=<repo>] <tree-ish> [basedir]\n"
+"git tar-tree [--remote=<repo>] <tree-ish> [basedir]\n"
 "*** Note that this command is now deprecated; use git-archive instead.";
 
 int cmd_tar_tree(int argc, const char **argv, const char *prefix)
diff --git a/builtin-update-index.c b/builtin-update-index.c
index 9e0d7ab..38eb53c 100644
--- a/builtin-update-index.c
+++ b/builtin-update-index.c
@@ -387,7 +387,7 @@ static void read_index_info(int line_termination)
 }
 
 static const char update_index_usage[] =
-"git-update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--really-refresh] [--cacheinfo] [--chmod=(+|-)x] [--assume-unchanged] [--info-only] [--force-remove] [--stdin] [--index-info] [--unresolve] [--again | -g] [--ignore-missing] [-z] [--verbose] [--] <file>...";
+"git update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--really-refresh] [--cacheinfo] [--chmod=(+|-)x] [--assume-unchanged] [--info-only] [--force-remove] [--stdin] [--index-info] [--unresolve] [--again | -g] [--ignore-missing] [-z] [--verbose] [--] <file>...";
 
 static unsigned char head_sha1[20];
 static unsigned char merge_head_sha1[20];
diff --git a/builtin-update-ref.c b/builtin-update-ref.c
index d90d11d..56a0b1b 100644
--- a/builtin-update-ref.c
+++ b/builtin-update-ref.c
@@ -4,8 +4,8 @@
 #include "parse-options.h"
 
 static const char * const git_update_ref_usage[] = {
-	"git-update-ref [options] -d <refname> [<oldval>]",
-	"git-update-ref [options]    <refname> <newval> [<oldval>]",
+	"git update-ref [options] -d <refname> [<oldval>]",
+	"git update-ref [options]    <refname> <newval> [<oldval>]",
 	NULL
 };
 
diff --git a/builtin-upload-archive.c b/builtin-upload-archive.c
index 371400d..6438133 100644
--- a/builtin-upload-archive.c
+++ b/builtin-upload-archive.c
@@ -8,13 +8,13 @@
 #include "sideband.h"
 
 static const char upload_archive_usage[] =
-	"git-upload-archive <repo>";
+	"git upload-archive <repo>";
 
 static const char deadchild[] =
-"git-upload-archive: archiver died with error";
+"git upload-archive: archiver died with error";
 
 static const char lostchild[] =
-"git-upload-archive: archiver process was lost";
+"git upload-archive: archiver process was lost";
 
 
 static int run_upload_archive(int argc, const char **argv, const char *prefix)
diff --git a/builtin-verify-tag.c b/builtin-verify-tag.c
index 92eaa89..7d837f0 100644
--- a/builtin-verify-tag.c
+++ b/builtin-verify-tag.c
@@ -12,7 +12,7 @@
 #include <signal.h>
 
 static const char builtin_verify_tag_usage[] =
-		"git-verify-tag [-v|--verbose] <tag>...";
+		"git verify-tag [-v|--verbose] <tag>...";
 
 #define PGP_SIGNATURE "-----BEGIN PGP SIGNATURE-----"
 
diff --git a/builtin-write-tree.c b/builtin-write-tree.c
index c218799..52a3c01 100644
--- a/builtin-write-tree.c
+++ b/builtin-write-tree.c
@@ -9,7 +9,7 @@
 #include "cache-tree.h"
 
 static const char write_tree_usage[] =
-"git-write-tree [--missing-ok] [--prefix=<prefix>/]";
+"git write-tree [--missing-ok] [--prefix=<prefix>/]";
 
 int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
 {
diff --git a/daemon.c b/daemon.c
index ce3a6f5..7df41a6 100644
--- a/daemon.c
+++ b/daemon.c
@@ -18,7 +18,7 @@ static int verbose;
 static int reuseaddr;
 
 static const char daemon_usage[] =
-"git-daemon [--verbose] [--syslog] [--export-all]\n"
+"git daemon [--verbose] [--syslog] [--export-all]\n"
 "           [--timeout=n] [--init-timeout=n] [--strict-paths]\n"
 "           [--base-path=path] [--base-path-relaxed]\n"
 "           [--user-path | --user-path=path]\n"
diff --git a/fast-import.c b/fast-import.c
index e72b286..c4d054e 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -2374,7 +2374,7 @@ static int git_pack_config(const char *k, const char *v, void *cb)
 }
 
 static const char fast_import_usage[] =
-"git-fast-import [--date-format=f] [--max-pack-size=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]";
+"git fast-import [--date-format=f] [--max-pack-size=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]";
 
 int main(int argc, const char **argv)
 {
diff --git a/git-am.sh b/git-am.sh
index 2c517ed..14578ce 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -5,9 +5,9 @@
 SUBDIRECTORY_OK=Yes
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
-git-am [options] <mbox>|<Maildir>...
-git-am [options] --resolved
-git-am [options] --skip
+git am [options] <mbox>|<Maildir>...
+git am [options] --resolved
+git am [options] --skip
 --
 d,dotest=       (removed -- do not use)
 i,interactive   run interactively
diff --git a/git-archimport.perl b/git-archimport.perl
index 9a7a906..98f3ede 100755
--- a/git-archimport.perl
+++ b/git-archimport.perl
@@ -9,7 +9,7 @@
 
 =head1 Invocation
 
-    git-archimport [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ]
+    git archimport [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ]
 	[ -D depth] [ -t tempdir ] <archive>/<branch> [ <archive>/<branch> ]
 
 Imports a project from one or more Arch repositories. It will follow branches
@@ -74,7 +74,7 @@ our($opt_h,$opt_f,$opt_v,$opt_T,$opt_t,$opt_D,$opt_a,$opt_o);
 
 sub usage() {
     print STDERR <<END;
-Usage: ${\basename $0}     # fetch/update GIT from Arch
+Usage: git archimport     # fetch/update GIT from Arch
        [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] [ -D depth ] [ -t tempdir ]
        repository/arch-branch [ repository/arch-branch] ...
 END
diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl
index c6c70e9..6d9f0ef 100755
--- a/git-cvsexportcommit.perl
+++ b/git-cvsexportcommit.perl
@@ -370,7 +370,7 @@ sleep(1);
 
 sub usage {
 	print STDERR <<END;
-Usage: GIT_DIR=/path/to/.git ${\basename $0} [-h] [-p] [-v] [-c] [-f] [-u] [-w cvsworkdir] [-m msgprefix] [ parent ] commit
+Usage: GIT_DIR=/path/to/.git git cvsexportcommit [-h] [-p] [-v] [-c] [-f] [-u] [-w cvsworkdir] [-m msgprefix] [ parent ] commit
 END
 	exit(1);
 }
diff --git a/git-cvsimport.perl b/git-cvsimport.perl
index cacbfc0..e2664ef 100755
--- a/git-cvsimport.perl
+++ b/git-cvsimport.perl
@@ -36,7 +36,7 @@ sub usage(;$) {
 	my $msg = shift;
 	print(STDERR "Error: $msg\n") if $msg;
 	print STDERR <<END;
-Usage: ${\basename $0}     # fetch/update GIT from CVS
+Usage: git cvsimport     # fetch/update GIT from CVS
        [-o branch-for-HEAD] [-h] [-v] [-d CVSROOT] [-A author-conv-file]
        [-p opts-for-cvsps] [-P file] [-C GIT_repository] [-z fuzz] [-i] [-k]
        [-u] [-s subst] [-a] [-m] [-M regex] [-S regex] [-L commitlimit]
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index 920bbe1..d2d374a 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -101,7 +101,7 @@ my $work =
 $log->info("--------------- STARTING -----------------");
 
 my $usage =
-    "Usage: git-cvsserver [options] [pserver|server] [<directory> ...]\n".
+    "Usage: git cvsserver [options] [pserver|server] [<directory> ...]\n".
     "    --base-path <path>  : Prepend to requested CVSROOT\n".
     "    --strict-paths      : Don't allow recursing into subdirectories\n".
     "    --export-all        : Don't check for gitcvs.enabled in config\n".
diff --git a/git-instaweb.sh b/git-instaweb.sh
index af0fde5..0843372 100755
--- a/git-instaweb.sh
+++ b/git-instaweb.sh
@@ -6,7 +6,7 @@
 PERL='@@PERL@@'
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
-git-instaweb [options] (--start | --stop | --restart)
+git instaweb [options] (--start | --stop | --restart)
 --
 l,local        only bind on 127.0.0.1
 p,port=        the port to bind to
diff --git a/git-merge.sh b/git-merge.sh
index 8026ccf..e9588ee 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -5,8 +5,8 @@
 
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
-git-merge [options] <remote>...
-git-merge [options] <msg> HEAD <remote>
+git merge [options] <remote>...
+git merge [options] <msg> HEAD <remote>
 --
 stat                 show a diffstat at the end of the merge
 n                    don't show a diffstat at the end of the merge
diff --git a/git-pull.sh b/git-pull.sh
index 809e537..6afd4e2 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -121,7 +121,7 @@ test true = "$rebase" && {
 		"refs/remotes/$origin/$reflist" 2>/dev/null)"
 }
 orig_head=$(git rev-parse --verify HEAD 2>/dev/null)
-git-fetch --update-head-ok "$@" || exit 1
+git fetch --update-head-ok "$@" || exit 1
 
 curr_head=$(git rev-parse --verify HEAD 2>/dev/null)
 if test "$curr_head" != "$orig_head"
diff --git a/git-quiltimport.sh b/git-quiltimport.sh
index 7cd8f71..e0649cd 100755
--- a/git-quiltimport.sh
+++ b/git-quiltimport.sh
@@ -1,7 +1,7 @@
 #!/bin/sh
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
-git-quiltimport [options]
+git quiltimport [options]
 --
 n,dry-run     dry run
 author=       author name and email address for patches without any
diff --git a/git-relink.perl b/git-relink.perl
index 15fb932..937c69a 100755
--- a/git-relink.perl
+++ b/git-relink.perl
@@ -163,7 +163,7 @@ sub link_two_files($$) {
 
 
 sub usage() {
-	print("Usage: $0 [--safe] <dir> [<dir> ...] <master_dir> \n");
+	print("Usage: git relink [--safe] <dir> [<dir> ...] <master_dir> \n");
 	print("All directories should contain a .git/objects/ subdirectory.\n");
 	print("Options\n");
 	print("\t--safe\t" .
diff --git a/git-repack.sh b/git-repack.sh
index 8c3bc13..683960b 100755
--- a/git-repack.sh
+++ b/git-repack.sh
@@ -5,7 +5,7 @@
 
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
-git-repack [options]
+git repack [options]
 --
 a               pack everything in a single pack
 A               same as -a, and turn unreachable objects loose
diff --git a/git-send-email.perl b/git-send-email.perl
index 6adb669..2e4a44a 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -38,7 +38,7 @@ package main;
 
 sub usage {
 	print <<EOT;
-git-send-email [options] <file | directory>...
+git send-email [options] <file | directory>...
 Options:
    --from         Specify the "From:" line of the email to be sent.
 
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index 9cceb21..dbdf209 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -32,15 +32,16 @@ if test -n "$OPTIONS_SPEC"; then
 		echo exit $?
 	)"
 else
+	dashless=$(basename "$0" | sed -e 's/-/ /')
 	usage() {
-		die "Usage: $0 $USAGE"
+		die "Usage: $dashless $USAGE"
 	}
 
 	if [ -z "$LONG_USAGE" ]
 	then
-		LONG_USAGE="Usage: $0 $USAGE"
+		LONG_USAGE="Usage: $dashless $USAGE"
 	else
-		LONG_USAGE="Usage: $0 $USAGE
+		LONG_USAGE="Usage: $dashless $USAGE
 
 $LONG_USAGE"
 	fi
diff --git a/git-svn.perl b/git-svn.perl
index a366c89..f6b878a 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -261,7 +261,7 @@ sub usage {
 	my $fd = $exit ? \*STDERR : \*STDOUT;
 	print $fd <<"";
 git-svn - bidirectional operations between a single Subversion tree and git
-Usage: $0 <command> [options] [arguments]\n
+Usage: git svn <command> [options] [arguments]\n
 
 	print $fd "Available commands:\n" unless $cmd;
 
diff --git a/hash-object.c b/hash-object.c
index 48d5223..46c06a9 100644
--- a/hash-object.c
+++ b/hash-object.c
@@ -52,7 +52,7 @@ static void hash_stdin_paths(const char *type, int write_objects)
 }
 
 static const char hash_object_usage[] =
-"git-hash-object [ [-t <type>] [-w] [--stdin] <file>... | --stdin-paths < <list-of-paths> ]";
+"git hash-object [ [-t <type>] [-w] [--stdin] <file>... | --stdin-paths < <list-of-paths> ]";
 
 int main(int argc, char **argv)
 {
diff --git a/help.c b/help.c
index ca9632b..ee15955 100644
--- a/help.c
+++ b/help.c
@@ -40,7 +40,7 @@ static struct option builtin_help_options[] = {
 };
 
 static const char * const builtin_help_usage[] = {
-	"git-help [--all] [--man|--web|--info] [command]",
+	"git help [--all] [--man|--web|--info] [command]",
 	NULL
 };
 
diff --git a/http-push.c b/http-push.c
index 2cd068a..6805288 100644
--- a/http-push.c
+++ b/http-push.c
@@ -14,7 +14,7 @@
 #include <expat.h>
 
 static const char http_push_usage[] =
-"git-http-push [--all] [--dry-run] [--force] [--verbose] <remote> [<head>...]\n";
+"git http-push [--all] [--dry-run] [--force] [--verbose] <remote> [<head>...]\n";
 
 #ifndef XML_STATUS_OK
 enum XML_Status {
diff --git a/index-pack.c b/index-pack.c
index 25db5db..bb2e6a3 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -10,7 +10,7 @@
 #include "fsck.h"
 
 static const char index_pack_usage[] =
-"git-index-pack [-v] [-o <index-file>] [{ ---keep | --keep=<msg> }] [--strict] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }";
+"git index-pack [-v] [-o <index-file>] [{ ---keep | --keep=<msg> }] [--strict] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }";
 
 struct object_entry
 {
diff --git a/pack-redundant.c b/pack-redundant.c
index f5cd0ac..25b81a4 100644
--- a/pack-redundant.c
+++ b/pack-redundant.c
@@ -11,7 +11,7 @@
 #define BLKSIZE 512
 
 static const char pack_redundant_usage[] =
-"git-pack-redundant [ --verbose ] [ --alt-odb ] < --all | <.pack filename> ...>";
+"git pack-redundant [ --verbose ] [ --alt-odb ] < --all | <.pack filename> ...>";
 
 static int load_all_packs, verbose, alt_odb;
 
diff --git a/update-server-info.c b/update-server-info.c
index 0b6c383..7e8209e 100644
--- a/update-server-info.c
+++ b/update-server-info.c
@@ -1,7 +1,7 @@
 #include "cache.h"
 
 static const char update_server_info_usage[] =
-"git-update-server-info [--force]";
+"git update-server-info [--force]";
 
 int main(int ac, char **av)
 {
-- 
1.5.6.2.306.gcc0c

^ permalink raw reply related

* Re: [HACK] t/test-lib.sh HACK: Add -s/--show-hack to test suite.
From: Johannes Schindelin @ 2008-07-13 13:21 UTC (permalink / raw)
  To: Stephan Beyer; +Cc: git
In-Reply-To: <20080713110904.GG22323@leksak.fem-net>

Hi,

On Sun, 13 Jul 2008, Stephan Beyer wrote:

> I want to see that the test failed at "! :" and I can't see that
> on this output.
> 
> But perhaps I just have to reconfigure something, so that it will show 
> me.

Ah, I implicitely assumed that you would also pass the "-i -v" flags to 
the test script, as my fingers are already trained to do so whenever I 
call a test script:

$ sh -x t4150-am.sh -i -v

You will have to scroll back a few lines to see exactly what failed, but 
you will see the exact commands (also of functions that were called), 
together with their return values (i.e. what the function output, and what 
was assigned to variables).

All that using the screen estate much more cautiously than your output.

I use "sh -x t* -i -v" all the time,
Dscho

^ permalink raw reply

* Re: [PATCH] bisect: test merge base if good rev is not an ancestor of bad rev
From: Johannes Schindelin @ 2008-07-13 13:14 UTC (permalink / raw)
  To: Christian Couder; +Cc: Junio C Hamano, Michael Haggerty, Jeff King, git
In-Reply-To: <200807130837.40961.chriscool@tuxfamily.org>

Hi,

On Sun, 13 Jul 2008, Christian Couder wrote:

> [PATCH] bisect: check all merge bases instead of only one

It would have been so much nicer to squash the two patches into one, as we 
generally frown upon "let's submit one patch that we know is faulty, and 
then another that fixes it".  That's so CVS/SVN.

> @@ -384,19 +383,21 @@ check_merge_bases() {
>  	_skip="$3"
>  	for _g in $_good; do

I really wonder if we can be blessed with less ugly variable names.  Maybe 
some that do not start with an underscore for no apparent reason, and 
maybe some that are longer than one letter, so that you have a chance to 
understand later what it is supposed to contain.  I.e. something like:

	for good in $good_revisions
	do

(You see that I also broke up the "for" and "do" into two lines, as is 
common practice in the rest of Git's shell code.)

>  		is_merge_base_ok "$_bad" "$_g" && continue
> -		_mb=$(git merge-base $_g $_bad)
> -		if test "$_mb" = "$_g" || is_among "$_mb" "$_good"; then
> -			mark_merge_base_ok "$_bad" "$_g"
> -		elif test "$_mb" = "$_bad"; then
> -			handle_bad_merge_base "$_bad" "$_g"
> -		elif is_among "$_mb" "$_skip"; then
> -			handle_skipped_merge_base "$_bad" "$_g" "_mb"
> -		else
> -			mark_testing_merge_base "$_mb"
> -			checkout "$_mb" "a merge base must be tested"
> -			checkout_done=1
> -			break
> -		fi
> +		for _mb in $(git merge-base --all $_g $_bad); do
> +			if test "$_mb" = "$_g" || is_among "$_mb" "$_good"; then
> +				continue
> +			elif test "$_mb" = "$_bad"; then
> +				handle_bad_merge_base "$_bad" "$_g"
> +			elif is_among "$_mb" "$_skip"; then
> +				handle_skipped_merge_base "$_bad" "$_g" "_mb"
> +			else
> +				mark_testing_merge_base "$_mb"
> +				checkout "$_mb" "a merge base must be tested"
> +				checkout_done=1
> +				return
> +			fi
> +		done
> +		mark_merge_base_ok "$_bad" "$_g"
>  	done
>  }

I really wonder if we cannot do better than that, in terms of code 
complexity.

For example, I wonder if we should special-case the start, and not just 
check everytime if there are unchecked merge bases instead.  If there are, 
check the first.

But that can wait until you come back from your vacation...

Have fun,
Dscho

^ permalink raw reply

* Re: [PATCH/Test] Build in merge is broken
From: Miklos Vajna @ 2008-07-13 12:41 UTC (permalink / raw)
  To: Sverre Hvammen Johansen; +Cc: git
In-Reply-To: <loom.20080713T073129-112@post.gmane.org>

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

On Sun, Jul 13, 2008 at 08:13:55AM +0000, Sverre Hvammen Johansen <hvammen+git@gmail.com> wrote:
> Great that we now are introducing merge in C.  Great job Miklos.
> However, it is broken as this patch shows.  This have been
> bisected to 1c7b76be Build in merge.
> 
> The test case when run will record the parents that were asked for which is
> fine.  However, only c2 is recorded as a parent in the commit object.  Both
> c1 and c2 should have been recorded.  The merge is otherwise working
> correctly.

Thanks for the testcase, I'm on it. ;-)

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

^ permalink raw reply

* Re: tests for git-p4
From: Simon Hausmann @ 2008-07-13 12:26 UTC (permalink / raw)
  To: Matt McClure; +Cc: git
In-Reply-To: <e48c5e540807120524rabdcfa6vd91c16ef1b0f80a0@mail.gmail.com>

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

On Saturday 12 July 2008 14:24:10 Matt McClure wrote:
> I'm planning to write a "p4-fast-export" that will facilitate using
> Bazaar on projects maintained in Perforce.  I'd like to reuse code
> from git-p4 since it appears to have much of the functionality I want.
>  In fact, the main reason I can't just use git-p4 today is that it
> does too much: it pushes the Perforce fast-export representation
> directly into Git.  I'm going to work on covering the existing
> functionality in tests before I start modifying the code, and I could
> try to write those tests such that they'll be useful to the Git
> project as well.
>
> Would my tests be of interest to git-p4's authors?  Is there any
> existing test framework for git-p4 that I missed?

There are currently no automated tests for git-p4. I would certainly be 
interested, but I forsee difficulties testing the interaction with p4 in a 
general way independent from a specific server setup.


Simon

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: [PATCH] bash completion: Fix the . -> .. revision range completion
From: Jakub Narebski @ 2008-07-13 12:11 UTC (permalink / raw)
  To: git
In-Reply-To: <20080713111847.29801.8969.stgit@localhost>

Petr Baudis wrote:

> This patch will make Git perform the . -> .. completion in
> __git_complete_revlist only if there is no filename starting with
> the entered prefix available.  At few places, filename could not occur
> when calling __git_complete_revlist; however, taking this into account
> did not seem worth complicating the code further.

Thanks a lot!  This is what I was waiting for...

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

^ permalink raw reply

* Vanilla gitweb vs repo.or.cz
From: Petr Baudis @ 2008-07-13 11:59 UTC (permalink / raw)
  To: Sylvain Beucler; +Cc: savannah-hackers-public, git
In-Reply-To: <20080713082812.GA4944@perso.beuc.net>

  Hi,

On Sun, Jul 13, 2008 at 10:28:12AM +0200, Sylvain Beucler wrote:
> >   By the way, where can I see the source code of the gitweb you are
> > using?
> 
> We're using vanilla gitweb from the official Git, actually.

  ah, of course! Somehow, I forgot that you can customize the project
URLs shown without modifying the source code nowadays.

> Apparently that version begins to be outdated, doesn't it? For
> example, a user recently suggested we use a cache for the start page
> project list but that feature doesn't seem to be merged yet. Maybe
> should we switch to repo.or.cz's version directly?

  This is a bit more complicated; I've cc'd the Git mailing list in case
someone else finds this informative.

  The upstream gitweb is under active development; most importantly,
Lea Wiemann is intensively working on a new caching infrastructure and
is doing some cleanups, while Jakub Narebski tries to fight the general
apathy by posting various interesting RFC patches I keep promising
myself to finally check out (most importantly for an index page
overhaul; the recently introduced content tags were the first step
to this).

  Then, there is the http://repo.or.cz/w/git/gitweb.git repository,
which was my old attempt at maintaining gitweb actively. Unfortunately,
this didn't quite work out because of my general lack of time and
dedication. However, the next and pu branches still contain some patches
and these patches are actively used on repo.or.cz; I still hope to get
to clean them up and resubmit sometime soon. I'm working on a certain
Git-based project essentially fulltime this summer, so I hope to do get
around to it. :-)

  Finally, there is the http://repo.or.cz/w/git/repo.git repository.
This is the Git variant repo.or.cz uses - both for gitweb and the rest
of Git binaries too (e.g. git-daemon and gc cronjobs; however, I need to
do the ssh chroot updates manually, so that might lag a lot behind;
until just a few days ago, Git version in the chroot was from December
2007).  It dubbles as my personal Git patch queue, but most of the
non-gitweb patches aren't generally interesting (and mostly remind me
of "what all should I redo differently sometime").

  The gitweb patches in git/repo.git are superset of git/gitweb.git
patches and the extra patches are I believe (at least not currently)
interesting for general gitweb public. However, some of them _might_
be interesting for large-scale gitweb hosting like yours. Some of them
might end up in git/gitweb.git after some cleanup (graphiclog link,
email addresses obfuscation, ...).

  Thus, my recommendation for now would be to check out the patches
queued in

	http://repo.or.cz/w/git/gitweb.git
	http://repo.or.cz/w/git/repo.git

and maybe cherrypick some interesting ones; basing your gitweb directly
on git/repo.git probably does not make much sense unless you revert
"Custom gitweb changes" and probably others. Basing your gitweb on
git/gitweb.git might work, but would be a little bit adventurous. ;-)

-- 
				Petr "Pasky" Baudis
GNU, n. An animal of South Africa, which in its domesticated state
resembles a horse, a buffalo and a stag. In its wild condition it is
something like a thunderbolt, an earthquake and a cyclone. -- A. Pierce

^ permalink raw reply

* Re: [PATCH 0/4] Proposed patches
From: Catalin Marinas @ 2008-07-13 11:42 UTC (permalink / raw)
  To: Karl Hasselström, git
In-Reply-To: <20080713113853.18845.37686.stgit@localhost.localdomain>

2008/7/13 Catalin Marinas <catalin.marinas@gmail.com>:
> A new post of the proposed patches after implementing Karl's comments.

BTW, these are StGIT patches, I forgot to add the prefix in the subject line.

-- 
Catalin

^ permalink raw reply

* [PATCH 4/4] Remove the applied/unapplied commands
From: Catalin Marinas @ 2008-07-13 11:40 UTC (permalink / raw)
  To: Karl Hasselström, git
In-Reply-To: <20080713113853.18845.37686.stgit@localhost.localdomain>

This patch moves the applied/unapplied functionality to the 'series'
command via the corresponding options.

Signed-off-by: Catalin Marinas <catalin.marinas@gmail.com>
---

 stgit/commands/applied.py   |   51 -------------------------------------------
 stgit/commands/series.py    |   25 ++++++++++++++++-----
 stgit/commands/unapplied.py |   50 ------------------------------------------
 stgit/main.py               |    4 ---
 t/t1002-branch-clone.sh     |    6 +++--
 t/t1003-new.sh              |    4 ++-
 t/t1200-push-modified.sh    |   12 +++++-----
 t/t1203-pop.sh              |   12 +++++-----
 t/t1204-pop-keep.sh         |   12 +++++-----
 t/t1205-push-subdir.sh      |    4 ++-
 t/t1301-repair.sh           |   12 +++++-----
 t/t1302-repair-interop.sh   |   20 ++++++++---------
 t/t1500-float.sh            |   14 ++++++------
 t/t1501-sink.sh             |    2 +-
 t/t1600-delete-one.sh       |   28 ++++++++++++------------
 t/t1601-delete-many.sh      |   24 ++++++++++----------
 t/t2000-sync.sh             |   48 ++++++++++++++++++++--------------------
 t/t2200-rebase.sh           |    4 ++-
 t/t2500-clean.sh            |   12 +++++-----
 t/t2600-coalesce.sh         |   12 +++++-----
 t/t3000-dirty-merge.sh      |    8 +++----
 t/t4000-upgrade.sh          |    4 ++-
 22 files changed, 138 insertions(+), 230 deletions(-)
 delete mode 100644 stgit/commands/applied.py
 delete mode 100644 stgit/commands/unapplied.py

diff --git a/stgit/commands/applied.py b/stgit/commands/applied.py
deleted file mode 100644
index e57c796..0000000
--- a/stgit/commands/applied.py
+++ /dev/null
@@ -1,51 +0,0 @@
-
-__copyright__ = """
-Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License version 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-"""
-
-from optparse import make_option
-from stgit.out import *
-from stgit.commands import common
-
-
-help = 'print the applied patches'
-usage = """%prog [options]
-
-List the patches from the series which have already been pushed onto
-the stack. They are listed in the order in which they were pushed, the
-last one being the current (topmost) patch."""
-
-directory = common.DirectoryHasRepositoryLib()
-options = [make_option('-b', '--branch',
-                       help = 'use BRANCH instead of the default branch'),
-           make_option('-c', '--count',
-                       help = 'print the number of applied patches',
-                       action = 'store_true')]
-
-
-def func(parser, options, args):
-    """Show the applied patches
-    """
-    if len(args) != 0:
-        parser.error('incorrect number of arguments')
-
-    s = directory.repository.get_stack(options.branch)
-
-    if options.count:
-        out.stdout(len(s.patchorder.applied))
-    else:
-        for pn in s.patchorder.applied:
-            out.stdout(pn)
diff --git a/stgit/commands/series.py b/stgit/commands/series.py
index c11c74f..b7899d7 100644
--- a/stgit/commands/series.py
+++ b/stgit/commands/series.py
@@ -37,7 +37,13 @@ options = [make_option('-b', '--branch',
            make_option('-a', '--all',
                        help = 'show all patches, including the hidden ones',
                        action = 'store_true'),
-           make_option('--hidden',
+           make_option('-A', '--applied',
+                       help = 'show the applied patches only',
+                       action = 'store_true'),
+           make_option('-U', '--unapplied',
+                       help = 'show the unapplied patches only',
+                       action = 'store_true'),
+           make_option('-H', '--hidden',
                        help = 'show the hidden patches only',
                        action = 'store_true'),
            make_option('-m', '--missing', metavar = 'BRANCH',
@@ -112,17 +118,24 @@ def func(parser, options, args):
         stack = directory.repository.get_stack(options.missing)
 
     # current series patches
-    if options.all:
+    applied = unapplied = hidden = ()
+    if options.applied or options.unapplied or options.hidden:
+        if options.all:
+            raise common.CmdException, \
+                '--all cannot be used with --applied/unapplied/hidden'
+        if options.applied:
+            applied = stack.patchorder.applied
+        if options.unapplied:
+            unapplied = stack.patchorder.unapplied
+        if options.hidden:
+            hidden = stack.patchorder.hidden
+    elif options.all:
         applied = stack.patchorder.applied
         unapplied = stack.patchorder.unapplied
         hidden = stack.patchorder.hidden
-    elif options.hidden:
-        applied = unapplied = ()
-        hidden = stack.patchorder.hidden
     else:
         applied = stack.patchorder.applied
         unapplied = stack.patchorder.unapplied
-        hidden = ()
 
     if options.missing:
         cmp_patches = cmp_stack.patchorder.all
diff --git a/stgit/commands/unapplied.py b/stgit/commands/unapplied.py
deleted file mode 100644
index 7323346..0000000
--- a/stgit/commands/unapplied.py
+++ /dev/null
@@ -1,50 +0,0 @@
-
-__copyright__ = """
-Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License version 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-"""
-
-from optparse import make_option
-from stgit.out import *
-from stgit.commands import common
-
-
-help = 'print the unapplied patches'
-usage = """%prog [options]
-
-List the patches from the series which are not pushed onto the stack.
-They are listed in the reverse order in which they were popped."""
-
-directory = common.DirectoryHasRepositoryLib()
-options = [make_option('-b', '--branch',
-                       help = 'use BRANCH instead of the default branch'),
-           make_option('-c', '--count',
-                       help = 'print the number of unapplied patches',
-                       action = 'store_true')]
-
-
-def func(parser, options, args):
-    """Show the unapplied patches
-    """
-    if len(args) != 0:
-        parser.error('incorrect number of arguments')
-
-    s = directory.repository.get_stack(options.branch)
-
-    if options.count:
-        out.stdout(len(s.patchorder.unapplied))
-    else:
-        for pn in s.patchorder.unapplied:
-            out.stdout(pn)
diff --git a/stgit/main.py b/stgit/main.py
index aa1f8ef..7be8e14 100644
--- a/stgit/main.py
+++ b/stgit/main.py
@@ -59,7 +59,6 @@ class Commands(dict):
         return getattr(stgit.commands, cmd_mod)
 
 commands = Commands({
-    'applied':          'applied',
     'branch':           'branch',
     'delete':           'delete',
     'diff':             'diff',
@@ -96,7 +95,6 @@ commands = Commands({
     'status':           'status',
     'sync':             'sync',
     'top':              'top',
-    'unapplied':        'unapplied',
     'uncommit':         'uncommit',
     'unhide':           'unhide'
     })
@@ -107,7 +105,6 @@ repocommands = (
     'id',
     )
 stackcommands = (
-    'applied',
     'branch',
     'clean',
     'coalesce',
@@ -125,7 +122,6 @@ stackcommands = (
     'series',
     'sink',
     'top',
-    'unapplied',
     'uncommit',
     'unhide',
     )
diff --git a/t/t1002-branch-clone.sh b/t/t1002-branch-clone.sh
index 19bdc45..1303b41 100755
--- a/t/t1002-branch-clone.sh
+++ b/t/t1002-branch-clone.sh
@@ -29,16 +29,16 @@ test_expect_success \
     '
     stg branch --clone foo &&
     stg new p1 -m "p1" &&
-    test $(stg applied -c) -eq 1
+    test $(stg series --applied -c) -eq 1
     '
 
 test_expect_success \
     'Clone the current StGIT branch' \
     '
     stg branch --clone bar &&
-    test $(stg applied -c) -eq 1 &&
+    test $(stg series --applied -c) -eq 1 &&
     stg new p2 -m "p2" &&
-    test $(stg applied -c) -eq 2
+    test $(stg series --applied -c) -eq 2
     '
 
 test_done
diff --git a/t/t1003-new.sh b/t/t1003-new.sh
index 0be5d9b..826e41d 100755
--- a/t/t1003-new.sh
+++ b/t/t1003-new.sh
@@ -17,13 +17,13 @@ test_expect_success \
 test_expect_success \
     'Create a named patch' '
     stg new foo -m foobar &&
-    [ $(stg applied -c) -eq 1 ]
+    [ $(stg series --applied -c) -eq 1 ]
 '
 
 test_expect_success \
     'Create a patch without giving a name' '
     stg new -m yo &&
-    [ $(stg applied -c) -eq 2 ]
+    [ $(stg series --applied -c) -eq 2 ]
 '
 
 test_done
diff --git a/t/t1200-push-modified.sh b/t/t1200-push-modified.sh
index 2edc760..113e41d 100755
--- a/t/t1200-push-modified.sh
+++ b/t/t1200-push-modified.sh
@@ -26,8 +26,8 @@ test_expect_success \
         printf "a\nc\n" > file && git add file && stg refresh &&
         stg new p2 -m p2 &&
         printf "a\nb\nc\n" > file && stg refresh &&
-        [ "$(echo $(stg applied))" = "p1 p2" ] &&
-        [ "$(echo $(stg unapplied))" = "" ]
+        [ "$(echo $(stg series --applied --noprefix))" = "p1 p2" ] &&
+        [ "$(echo $(stg series --unapplied --noprefix))" = "" ]
     )
 '
 
@@ -57,8 +57,8 @@ test_expect_success \
     'Rollback the push' '
     (
         cd bar && stg push --undo &&
-        [ "$(echo $(stg applied))" = "" ] &&
-        [ "$(echo $(stg unapplied))" = "p1 p2" ]
+        [ "$(echo $(stg series --applied --noprefix))" = "" ] &&
+        [ "$(echo $(stg series --unapplied --noprefix))" = "p1 p2" ]
     )
 '
 
@@ -66,8 +66,8 @@ test_expect_success \
     'Push those patches while checking they were merged upstream' '
     (
         cd bar && stg push --merged --all
-        [ "$(echo $(stg applied))" = "p1 p2" ] &&
-        [ "$(echo $(stg unapplied))" = "" ]
+        [ "$(echo $(stg series --applied --noprefix))" = "p1 p2" ] &&
+        [ "$(echo $(stg series --unapplied --noprefix))" = "" ]
     )
 '
 
diff --git a/t/t1203-pop.sh b/t/t1203-pop.sh
index 6e49b4d..e1ed577 100755
--- a/t/t1203-pop.sh
+++ b/t/t1203-pop.sh
@@ -12,22 +12,22 @@ test_expect_success \
     for i in 0 1 2 3 4 5 6 7 8 9; do
         stg new p$i -m p$i;
     done &&
-    [ "$(echo $(stg applied))" = "p0 p1 p2 p3 p4 p5 p6 p7 p8 p9" ] &&
-    [ "$(echo $(stg unapplied))" = "" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 p1 p2 p3 p4 p5 p6 p7 p8 p9" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ]
 '
 
 test_expect_success \
     'Pop half the patches' '
     stg pop -n 5 &&
-    [ "$(echo $(stg applied))" = "p0 p1 p2 p3 p4" ] &&
-    [ "$(echo $(stg unapplied))" = "p5 p6 p7 p8 p9" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 p1 p2 p3 p4" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p5 p6 p7 p8 p9" ]
 '
 
 test_expect_success \
     'Pop the remaining patches' '
     stg pop -a &&
-    [ "$(echo $(stg applied))" = "" ] &&
-    [ "$(echo $(stg unapplied))" = "p0 p1 p2 p3 p4 p5 p6 p7 p8 p9" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p0 p1 p2 p3 p4 p5 p6 p7 p8 p9" ]
 '
 
 test_done
diff --git a/t/t1204-pop-keep.sh b/t/t1204-pop-keep.sh
index 35f4ec0..db473f2 100755
--- a/t/t1204-pop-keep.sh
+++ b/t/t1204-pop-keep.sh
@@ -11,8 +11,8 @@ test_expect_success 'Create a few patches' '
         git add patch$i.txt &&
         stg refresh
     done &&
-    [ "$(echo $(stg applied))" = "p0 p1 p2" ] &&
-    [ "$(echo $(stg unapplied))" = "" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 p1 p2" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ]
 '
 
 test_expect_success 'Make some non-conflicting local changes' '
@@ -21,8 +21,8 @@ test_expect_success 'Make some non-conflicting local changes' '
 
 test_expect_success 'Pop two patches, keeping local changes' '
     stg pop -n 2 --keep &&
-    [ "$(echo $(stg applied))" = "p0" ] &&
-    [ "$(echo $(stg unapplied))" = "p1 p2" ] &&
+    [ "$(echo $(stg series --applied --noprefix))" = "p0" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p1 p2" ] &&
     [ "$(echo $(ls patch?.txt))" = "patch0.txt" ] &&
     [ "$(echo $(cat patch0.txt))" = "patch0 local" ]
 '
@@ -34,8 +34,8 @@ test_expect_success 'Reset and push patches again' '
 
 test_expect_success 'Pop a patch without local changes' '
     stg pop --keep &&
-    [ "$(echo $(stg applied))" = "p0 p1" ] &&
-    [ "$(echo $(stg unapplied))" = "p2" ] &&
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 p1" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p2" ] &&
     [ "$(echo $(ls patch?.txt))" = "patch0.txt patch1.txt" ]
 '
 
diff --git a/t/t1205-push-subdir.sh b/t/t1205-push-subdir.sh
index 945eb74..f852762 100755
--- a/t/t1205-push-subdir.sh
+++ b/t/t1205-push-subdir.sh
@@ -12,8 +12,8 @@ test_expect_success 'Create some patches' '
         git add x.txt foo/y.txt &&
         stg refresh
     done &&
-    [ "$(echo $(stg applied))" = "p0 p1 p2" ] &&
-    [ "$(echo $(stg unapplied))" = "" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 p1 p2" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ]
 '
 
 test_expect_success 'Fast-forward push from a subdir' '
diff --git a/t/t1301-repair.sh b/t/t1301-repair.sh
index 33f8f6d..8d5d4e5 100755
--- a/t/t1301-repair.sh
+++ b/t/t1301-repair.sh
@@ -37,9 +37,9 @@ test_expect_success \
     '
 
 test_expect_success 'Turn one GIT commit into a patch' '
-    [ $(stg applied | wc -l) -eq 1 ] &&
+    [ $(stg series --applied -c) -eq 1 ] &&
     stg repair &&
-    [ $(stg applied | wc -l) -eq 2 ]
+    [ $(stg series --applied -c) -eq 2 ]
     '
 
 test_expect_success \
@@ -55,9 +55,9 @@ test_expect_success \
     '
 
 test_expect_success 'Turn three GIT commits into patches' '
-    [ $(stg applied | wc -l) -eq 2 ] &&
+    [ $(stg series --applied -c) -eq 2 ] &&
     stg repair &&
-    [ $(stg applied | wc -l) -eq 5 ]
+    [ $(stg series --applied -c) -eq 5 ]
     '
 
 test_expect_success \
@@ -72,9 +72,9 @@ test_expect_success \
     '
 
 test_expect_success 'Repair in the presence of a merge commit' '
-    [ $(stg applied | wc -l) -eq 5 ] &&
+    [ $(stg series --applied -c) -eq 5 ] &&
     stg repair &&
-    [ $(stg applied | wc -l) -eq 0 ]
+    [ $(stg series --applied -c) -eq 0 ]
 '
 
 test_done
diff --git a/t/t1302-repair-interop.sh b/t/t1302-repair-interop.sh
index 3ea48e7..224c4ba 100755
--- a/t/t1302-repair-interop.sh
+++ b/t/t1302-repair-interop.sh
@@ -21,8 +21,8 @@ test_expect_success 'Create five patches' '
     for i in 0 1 2 3 4; do
         stg new p$i -m p$i;
     done &&
-    [ "$(echo $(stg applied))" = "p0 p1 p2 p3 p4" ] &&
-    [ "$(echo $(stg unapplied))" = "" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 p1 p2 p3 p4" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ]
 '
 
 test_expect_success 'Pop two patches with git-reset' '
@@ -30,14 +30,14 @@ test_expect_success 'Pop two patches with git-reset' '
     command_error stg refresh &&
     stg repair &&
     stg refresh &&
-    [ "$(echo $(stg applied))" = "p0 p1 p2" ] &&
-    [ "$(echo $(stg unapplied))" = "p3 p4" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 p1 p2" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p3 p4" ]
 '
 
 test_expect_success 'Create a new patch' '
     stg new q0 -m q0 &&
-    [ "$(echo $(stg applied))" = "p0 p1 p2 q0" ] &&
-    [ "$(echo $(stg unapplied))" = "p3 p4" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 p1 p2 q0" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p3 p4" ]
 '
 
 test_expect_success 'Go to an unapplied patch with with git-reset' '
@@ -45,15 +45,15 @@ test_expect_success 'Go to an unapplied patch with with git-reset' '
     command_error stg refresh &&
     stg repair &&
     stg refresh &&
-    [ "$(echo $(stg applied))" = "p0 p1 p2 p3" ] &&
-    [ "$(echo $(stg unapplied))" = "q0 p4" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 p1 p2 p3" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "q0 p4" ]
 '
 
 test_expect_success 'Go back to below the stack base with git-reset' '
     git reset --hard foo-tag &&
     stg repair &&
-    [ "$(echo $(stg applied))" = "" ] &&
-    [ "$(echo $(stg unapplied))" = "p0 p1 p2 p3 q0 p4" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p0 p1 p2 p3 q0 p4" ]
 '
 
 test_done
diff --git a/t/t1500-float.sh b/t/t1500-float.sh
index 778fde4..e44af3a 100755
--- a/t/t1500-float.sh
+++ b/t/t1500-float.sh
@@ -20,37 +20,37 @@ test_expect_success \
 	 stg new F -m "f" && echo F >f.txt && git add f.txt && stg refresh &&
 	 stg new G -m "g" && echo G >g.txt && git add g.txt && stg refresh &&
 	 stg pop &&
-	 test "$(echo $(stg applied))" = "A B C D E F"
+	 test "$(echo $(stg series --applied --noprefix))" = "A B C D E F"
 	'
 
 test_expect_success \
 	'Float A to top' \
 	'stg float A &&
-	 test "$(echo $(stg applied))" = "B C D E F A"
+	 test "$(echo $(stg series --applied --noprefix))" = "B C D E F A"
 	'
 test_expect_success \
 	'Float A to top (noop)' \
 	'stg float A &&
-	 test "$(echo $(stg applied))" = "B C D E F A"
+	 test "$(echo $(stg series --applied --noprefix))" = "B C D E F A"
 	'
 test_expect_success \
 	'Float B C to top' \
 	'stg float B C &&
-	 test "$(echo $(stg applied))" = "D E F A B C"
+	 test "$(echo $(stg series --applied --noprefix))" = "D E F A B C"
 	'
 test_expect_success \
 	'Float E A to top' \
 	'stg float E A &&
-	 test "$(echo $(stg applied))" = "D F B C E A"
+	 test "$(echo $(stg series --applied --noprefix))" = "D F B C E A"
 	'
 test_expect_success \
 	'Float E to top' \
 	'stg float E &&
-	 test "$(echo $(stg applied))" = "D F B C A E"
+	 test "$(echo $(stg series --applied --noprefix))" = "D F B C A E"
 	'
 test_expect_success \
 	'Float G F to top' \
 	'stg float G F &&
-	 test "$(echo $(stg applied))" = "D B C A E G F"
+	 test "$(echo $(stg series --applied --noprefix))" = "D B C A E G F"
 	'
 test_done
diff --git a/t/t1501-sink.sh b/t/t1501-sink.sh
index ac9e25d..32931cd 100755
--- a/t/t1501-sink.sh
+++ b/t/t1501-sink.sh
@@ -22,7 +22,7 @@ test_expect_success 'sink without applied patches' '
 
 test_expect_success 'sink a specific patch without applied patches' '
     stg sink y &&
-    test $(echo $(stg applied)) = "y"
+    test $(echo $(stg series --applied --noprefix)) = "y"
 '
 
 test_done
diff --git a/t/t1600-delete-one.sh b/t/t1600-delete-one.sh
index b526a55..ef0b29d 100755
--- a/t/t1600-delete-one.sh
+++ b/t/t1600-delete-one.sh
@@ -19,27 +19,27 @@ test_expect_success \
 test_expect_success \
     'Try to delete a non-existing patch' \
     '
-    [ $(stg applied | wc -l) -eq 1 ] &&
+    [ $(stg series --applied -c) -eq 1 ] &&
     command_error stg delete bar &&
-    [ $(stg applied | wc -l) -eq 1 ]
+    [ $(stg series --applied -c) -eq 1 ]
     '
 
 test_expect_success \
     'Try to delete the topmost patch while dirty' \
     '
     echo dirty >> foo.txt &&
-    [ $(stg applied | wc -l) -eq 1 ] &&
+    [ $(stg series --applied -c) -eq 1 ] &&
     command_error stg delete foo &&
-    [ $(stg applied | wc -l) -eq 1 ] &&
+    [ $(stg series --applied -c) -eq 1 ] &&
     git reset --hard
     '
 
 test_expect_success \
     'Delete the topmost patch' \
     '
-    [ $(stg applied | wc -l) -eq 1 ] &&
+    [ $(stg series --applied -c) -eq 1 ] &&
     stg delete foo &&
-    [ $(stg applied | wc -l) -eq 0 ]
+    [ $(stg series --applied -c) -eq 0 ]
     '
 
 test_expect_success \
@@ -55,9 +55,9 @@ test_expect_success \
 test_expect_success \
     'Delete an unapplied patch' \
     '
-    [ $(stg unapplied | wc -l) -eq 1 ] &&
+    [ $(stg series --unapplied -c) -eq 1 ] &&
     stg delete foo &&
-    [ $(stg unapplied | wc -l) -eq 0 ]
+    [ $(stg series --unapplied -c) -eq 0 ]
     '
 
 test_expect_success \
@@ -76,9 +76,9 @@ test_expect_success \
 test_expect_success \
     'Try to delete a non-topmost applied patch' \
     '
-    [ $(stg applied | wc -l) -eq 2 ] &&
+    [ $(stg series --applied -c) -eq 2 ] &&
     stg delete foo &&
-    [ $(stg applied | wc -l) -eq 1 ]
+    [ $(stg series --applied -c) -eq 1 ]
     '
 
 test_expect_success \
@@ -99,11 +99,11 @@ test_expect_success \
 test_expect_success \
     'Delete a patch in another branch' \
     '
-    [ $(stg applied | wc -l) -eq 2 ] &&
-    [ $(stg applied -b br | wc -l) -eq 1 ] &&
+    [ $(stg series --applied -c) -eq 2 ] &&
+    [ $(stg series --applied -b br -c) -eq 1 ] &&
     stg delete -b br baz &&
-    [ $(stg applied | wc -l) -eq 2 ] &&
-    [ $(stg applied -b br | wc -l) -eq 0 ]
+    [ $(stg series --applied -c) -eq 2 ] &&
+    [ $(stg series --applied -b br -c) -eq 0 ]
     '
 
 test_done
diff --git a/t/t1601-delete-many.sh b/t/t1601-delete-many.sh
index bc5364f..cb7fb0d 100755
--- a/t/t1601-delete-many.sh
+++ b/t/t1601-delete-many.sh
@@ -25,31 +25,31 @@ test_expect_success \
 test_expect_success \
     'Delete some patches' \
     '
-    [ "$(echo $(stg applied))" = "p0 p1 p2 p3 p4" ] &&
-    [ "$(echo $(stg unapplied))" = "p5 p6 p7 p8 p9" ] &&
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 p1 p2 p3 p4" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p5 p6 p7 p8 p9" ] &&
     stg delete p7 p6 p3 p4 &&
-    [ "$(echo $(stg applied))" = "p0 p1 p2" ] &&
-    [ "$(echo $(stg unapplied))" = "p5 p8 p9" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 p1 p2" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p5 p8 p9" ]
     '
 
 test_expect_success \
     'Delete some more patches, some of which do not exist' \
     '
-    [ "$(echo $(stg applied))" = "p0 p1 p2" ] &&
-    [ "$(echo $(stg unapplied))" = "p5 p8 p9" ] &&
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 p1 p2" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p5 p8 p9" ] &&
     command_error stg delete p7 p8 p2 p0 &&
-    [ "$(echo $(stg applied))" = "p0 p1 p2" ] &&
-    [ "$(echo $(stg unapplied))" = "p5 p8 p9" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 p1 p2" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p5 p8 p9" ]
     '
 
 test_expect_success \
     'Delete a range of patches' \
     '
-    [ "$(echo $(stg applied))" = "p0 p1 p2" ] &&
-    [ "$(echo $(stg unapplied))" = "p5 p8 p9" ] &&
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 p1 p2" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p5 p8 p9" ] &&
     stg delete p1..p8 &&
-    [ "$(echo $(stg applied))" = "p0" ] &&
-    [ "$(echo $(stg unapplied))" = "p9" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p0" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p9" ]
     '
 
 test_done
diff --git a/t/t2000-sync.sh b/t/t2000-sync.sh
index f4e8b07..00ea7bd 100755
--- a/t/t2000-sync.sh
+++ b/t/t2000-sync.sh
@@ -30,8 +30,8 @@ test_expect_success \
     stg refresh &&
     stg export &&
     stg pop &&
-    [ "$(echo $(stg applied))" = "p1 p2" ] &&
-    [ "$(echo $(stg unapplied))" = "p3" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p1 p2" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p3" ]
     '
 
 test_expect_success \
@@ -41,16 +41,16 @@ test_expect_success \
     stg new p1 -m p1 &&
     stg new p2 -m p2 &&
     stg new p3 -m p3 &&
-    [ "$(echo $(stg applied))" = "p1 p2 p3" ] &&
-    [ "$(echo $(stg unapplied))" = "" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p1 p2 p3" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ]
     '
 
 test_expect_success \
     'Synchronise second patch with the master branch' \
     '
     stg sync -B master p2 &&
-    [ "$(echo $(stg applied))" = "p1 p2 p3" ] &&
-    [ "$(echo $(stg unapplied))" = "" ] &&
+    [ "$(echo $(stg series --applied --noprefix))" = "p1 p2 p3" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ] &&
     test $(cat foo2.txt) = "foo2"
     '
 
@@ -58,8 +58,8 @@ test_expect_success \
     'Synchronise the first two patches with the master branch' \
     '
     stg sync -B master -a &&
-    [ "$(echo $(stg applied))" = "p1 p2 p3" ] &&
-    [ "$(echo $(stg unapplied))" = "" ] &&
+    [ "$(echo $(stg series --applied --noprefix))" = "p1 p2 p3" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ] &&
     test $(cat foo1.txt) = "foo1" &&
     test $(cat foo2.txt) = "foo2"
     '
@@ -68,8 +68,8 @@ test_expect_success \
     'Synchronise all the patches with the exported series' \
     '
     stg sync -s patches-master/series -a &&
-    [ "$(echo $(stg applied))" = "p1 p2 p3" ] &&
-    [ "$(echo $(stg unapplied))" = "" ] &&
+    [ "$(echo $(stg series --applied --noprefix))" = "p1 p2 p3" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ] &&
     test $(cat foo1.txt) = "foo1" &&
     test $(cat foo2.txt) = "foo2" &&
     test $(cat foo3.txt) = "foo3"
@@ -79,8 +79,8 @@ test_expect_success \
     'Modify the master patches' \
     '
     stg branch master &&
-    [ "$(echo $(stg applied))" = "p1 p2" ] &&
-    [ "$(echo $(stg unapplied))" = "p3" ] &&
+    [ "$(echo $(stg series --applied --noprefix))" = "p1 p2" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p3" ] &&
     stg goto p1 &&
     echo bar1 >> foo1.txt &&
     stg refresh &&
@@ -91,8 +91,8 @@ test_expect_success \
     stg goto p3 &&
     echo bar3 >> foo3.txt &&
     stg refresh &&
-    [ "$(echo $(stg applied))" = "p1 p2 p3" ] &&
-    [ "$(echo $(stg unapplied))" = "" ] &&
+    [ "$(echo $(stg series --applied --noprefix))" = "p1 p2 p3" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ] &&
     stg export &&
     stg branch foo
     '
@@ -101,8 +101,8 @@ test_expect_success \
     'Synchronise second patch with the master branch' \
     '
     stg sync -B master p2 &&
-    [ "$(echo $(stg applied))" = "p1 p2 p3" ] &&
-    [ "$(echo $(stg unapplied))" = "" ] &&
+    [ "$(echo $(stg series --applied --noprefix))" = "p1 p2 p3" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ] &&
     test $(cat bar2.txt) = "bar2"
     '
 
@@ -115,13 +115,13 @@ test_expect_success \
 test_expect_success \
     'Restore the stack status after the failed sync' \
     '
-    [ "$(echo $(stg applied))" = "p1" ] &&
-    [ "$(echo $(stg unapplied))" = "p2 p3" ] &&
+    [ "$(echo $(stg series --applied --noprefix))" = "p1" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p2 p3" ] &&
     stg resolved -a &&
     stg refresh &&
     stg goto p3
-    [ "$(echo $(stg applied))" = "p1 p2 p3" ] &&
-    [ "$(echo $(stg unapplied))" = "" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p1 p2 p3" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ]
     '
 
 test_expect_success \
@@ -133,12 +133,12 @@ test_expect_success \
 test_expect_success \
     'Restore the stack status after the failed sync' \
     '
-    [ "$(echo $(stg applied))" = "p1 p2 p3" ] &&
-    [ "$(echo $(stg unapplied))" = "" ] &&
+    [ "$(echo $(stg series --applied --noprefix))" = "p1 p2 p3" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ] &&
     stg resolved -a &&
     stg refresh &&
-    [ "$(echo $(stg applied))" = "p1 p2 p3" ] &&
-    [ "$(echo $(stg unapplied))" = "" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p1 p2 p3" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ]
     '
 
 test_done
diff --git a/t/t2200-rebase.sh b/t/t2200-rebase.sh
index 256eaaa..adbf242 100755
--- a/t/t2200-rebase.sh
+++ b/t/t2200-rebase.sh
@@ -28,7 +28,7 @@ test_expect_success \
 	'
 	stg rebase master~1 &&
 	test `stg id stack:{base}` = `git rev-parse master~1` &&
-	test `stg applied | wc -l` = 1
+	test `stg series --applied -c` = 1
 	'
 
 test_expect_success \
@@ -40,7 +40,7 @@ test_expect_success \
 test_expect_success \
 	'Check patches were re-applied' \
 	'
-	test $(stg applied | wc -l) = 1
+	test $(stg series --applied -c) = 1
 	'
 
 test_done
diff --git a/t/t2500-clean.sh b/t/t2500-clean.sh
index abde9cf..99fd29f 100755
--- a/t/t2500-clean.sh
+++ b/t/t2500-clean.sh
@@ -17,11 +17,11 @@ test_expect_success 'Initialize StGit stack' '
 '
 
 test_expect_success 'Clean empty patches' '
-    [ "$(echo $(stg applied))" = "e0 p0 e1" ] &&
-    [ "$(echo $(stg unapplied))" = "e2" ] &&
+    [ "$(echo $(stg series --applied --noprefix))" = "e0 p0 e1" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "e2" ] &&
     stg clean &&
-    [ "$(echo $(stg applied))" = "p0" ] &&
-    [ "$(echo $(stg unapplied))" = "" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p0" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ]
 '
 
 test_expect_success 'Create a conflict' '
@@ -37,8 +37,8 @@ test_expect_success 'Create a conflict' '
 
 test_expect_success 'Make sure conflicting patches are preserved' '
     stg clean &&
-    [ "$(echo $(stg applied))" = "p0 p2 p1" ] &&
-    [ "$(echo $(stg unapplied))" = "" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 p2 p1" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ]
 '
 
 test_done
diff --git a/t/t2600-coalesce.sh b/t/t2600-coalesce.sh
index f13a309..ef5bf99 100755
--- a/t/t2600-coalesce.sh
+++ b/t/t2600-coalesce.sh
@@ -15,17 +15,17 @@ test_expect_success 'Initialize StGit stack' '
 '
 
 test_expect_success 'Coalesce some patches' '
-    [ "$(echo $(stg applied))" = "p0 p1 p2 p3" ] &&
-    [ "$(echo $(stg unapplied))" = "" ] &&
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 p1 p2 p3" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ] &&
     stg coalesce --name=q0 --message="wee woo" p1 p2 &&
-    [ "$(echo $(stg applied))" = "p0 q0 p3" ] &&
-    [ "$(echo $(stg unapplied))" = "" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 q0 p3" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ]
 '
 
 test_expect_success 'Coalesce at stack top' '
     stg coalesce --name=q1 --message="wee woo wham" q0 p3 &&
-    [ "$(echo $(stg applied))" = "p0 q1" ] &&
-    [ "$(echo $(stg unapplied))" = "" ]
+    [ "$(echo $(stg series --applied --noprefix))" = "p0 q1" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "" ]
 '
 
 test_done
diff --git a/t/t3000-dirty-merge.sh b/t/t3000-dirty-merge.sh
index 4dd6da3..f0f79d5 100755
--- a/t/t3000-dirty-merge.sh
+++ b/t/t3000-dirty-merge.sh
@@ -24,11 +24,11 @@ test_expect_success 'Pop one patch and update the other' '
 
 test_expect_success 'Push with dirty worktree' '
     echo 4 > a &&
-    [ "$(echo $(stg applied))" = "p1" ] &&
-    [ "$(echo $(stg unapplied))" = "p2" ] &&
+    [ "$(echo $(stg series --applied --noprefix))" = "p1" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p2" ] &&
     conflict stg goto p2 &&
-    [ "$(echo $(stg applied))" = "p1" ] &&
-    [ "$(echo $(stg unapplied))" = "p2" ] &&
+    [ "$(echo $(stg series --applied --noprefix))" = "p1" ] &&
+    [ "$(echo $(stg series --unapplied --noprefix))" = "p2" ] &&
     [ "$(echo $(cat a))" = "4" ]
 '
 
diff --git a/t/t4000-upgrade.sh b/t/t4000-upgrade.sh
index ea9bf0b..b89c720 100755
--- a/t/t4000-upgrade.sh
+++ b/t/t4000-upgrade.sh
@@ -14,8 +14,8 @@ for ver in 0.12 0.8; do
 
     test_expect_success \
         "v$ver: Check the list of applied and unapplied patches" '
-        [ "$(echo $(stg applied))" = "p0 p1 p2" ] &&
-        [ "$(echo $(stg unapplied))" = "p3 p4" ]
+        [ "$(echo $(stg series --applied --noprefix))" = "p0 p1 p2" ] &&
+        [ "$(echo $(stg series --unapplied --noprefix))" = "p3 p4" ]
     '
 
     test_expect_success \

^ permalink raw reply related

* [PATCH 3/4] Convert git_id() to the new id format
From: Catalin Marinas @ 2008-07-13 11:40 UTC (permalink / raw)
  To: Karl Hasselström, git
In-Reply-To: <20080713113853.18845.37686.stgit@localhost.localdomain>

The patch rewrites git_id() to use the new id format and coverts the
commands using this function. The git_id() will be removed once all the
commands are converted to the new infrastructure where git_commit() will
be used instead.

Signed-off-by: Catalin Marinas <catalin.marinas@gmail.com>
---

 stgit/commands/common.py  |   98 +++++++--------------------------------------
 stgit/commands/diff.py    |   23 +++++------
 stgit/commands/files.py   |   10 ++---
 stgit/commands/mail.py    |    8 ++--
 stgit/commands/pick.py    |   10 ++---
 stgit/commands/refresh.py |    4 +-
 stgit/commands/series.py  |    4 +-
 t/t2000-sync.sh           |    2 -
 8 files changed, 43 insertions(+), 116 deletions(-)

diff --git a/stgit/commands/common.py b/stgit/commands/common.py
index 0133f1a..0413aac 100644
--- a/stgit/commands/common.py
+++ b/stgit/commands/common.py
@@ -35,101 +35,35 @@ class CmdException(StgException):
     pass
 
 # Utility functions
-class RevParseException(StgException):
-    """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 //."""
-    if '/' in ''.join(git.get_heads()):
-        # We have branch names with / in them.
-        branch_chars = r'[^@]'
-        patch_id_mark = r'//'
-    else:
-        # No / in branch names.
-        branch_chars = r'[^@/]'
-        patch_id_mark = r'(/|//)'
-    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 path[@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')
-
-    # Try patch[@branch].
-    m = re.match(r'^%s(%s)?$' % (patch_re, branch_re), rev)
-    if m:
-        return m.group('patch'), m.group('branch'), None
-
-    # No, we can't parse that.
-    raise RevParseException
-
-def git_id(crt_series, rev):
-    """Return the GIT id
+    """Parse a revision specification into its branch:patch parts.
     """
-    if not rev:
-        return None
-
-    # try a GIT revision first
     try:
-        return git.rev_parse(rev + '^{commit}')
-    except git.GitException:
-        pass
+        branch, patch = rev.split(':', 1)
+    except ValueError:
+        branch = None
+        patch = rev
 
-    # try an StGIT patch name
-    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() or \
-               patch in series.get_hidden():
-            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()
-            elif patch_id == 'log':
-                return series.get_patch(patch).get_log()
-        if patch == 'base' and patch_id == None:
-            return series.get_base()
-    except RevParseException:
-        pass
-    except stack.StackException:
-        pass
+    return (branch, patch)
 
-    raise CmdException, 'Unknown patch or revision: %s' % rev
+def git_id(crt_series, rev):
+    """Return the GIT id
+    """
+    # TODO: remove this function once all the occurrences were converted
+    # to git_commit()
+    repository = libstack.Repository.default()
+    return git_commit(rev, repository, crt_series.get_name()).sha1
 
-def git_commit(name, repository, branch = None):
+def git_commit(name, repository, branch_name = None):
     """Return the a Commit object if 'name' is a patch name or Git commit.
     The patch names allowed are in the form '<branch>:<patch>' and can
     be followed by standard symbols used by git-rev-parse. If <patch>
     is '{base}', it represents the bottom of the stack.
     """
     # Try a [branch:]patch name first
-    try:
-        branch, patch = name.split(':', 1)
-    except ValueError:
-        patch = name
+    branch, patch = parse_rev(name)
     if not branch:
-        branch = repository.current_branch_name
+        branch = branch_name or repository.current_branch_name
 
     # The stack base
     if patch.startswith('{base}'):
diff --git a/stgit/commands/diff.py b/stgit/commands/diff.py
index fd6be34..c57f720 100644
--- a/stgit/commands/diff.py
+++ b/stgit/commands/diff.py
@@ -30,17 +30,14 @@ help = 'show the tree diff'
 usage = """%prog [options] [<files or dirs>]
 
 Show the diff (default) or diffstat between the current working copy
-or a tree-ish object and another tree-ish object. File names can also
-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
-the current one):
+or a tree-ish object and another tree-ish object (defaulting to HEAD).
+File names can also be given to restrict the diff output. The
+tree-ish object can be an StGIT patch, a standard git commit, tag or
+tree. In addition to these, the command also supports '{base}',
+representing the bottom of the current stack.
 
-rev = '([patch][//[bottom | top]]) | <tree-ish> | base'
-
-If neither bottom nor top are given but a '//' is present, the command
-shows the specified patch (defaulting to the current one)."""
+rev = '[branch:](<patch>|{base}) | <tree-ish>'
+"""
 
 directory = DirectoryHasRepository()
 options = [make_option('-r', '--range',
@@ -67,8 +64,8 @@ def func(parser, options, args):
                 rev = strip_suffix('/', rev)
                 if rev.endswith('/'):
                     rev = strip_suffix('/', rev)
-                rev1 = rev + '//bottom'
-                rev2 = rev + '//top'
+                rev1 = rev + 'HEAD^'
+                rev2 = rev + 'HEAD'
             else:
                 rev1 = rev_list[0]
                 rev2 = None
@@ -82,7 +79,7 @@ def func(parser, options, args):
         rev2 = None
 
     diff_str = git.diff(args, git_id(crt_series, rev1),
-                        git_id(crt_series, rev2),
+                        rev2 and git_id(crt_series, rev2),
                         diff_flags = options.diff_flags)
     if options.stat:
         out.stdout_raw(git.diffstat(diff_str) + '\n')
diff --git a/stgit/commands/files.py b/stgit/commands/files.py
index b43b12f..d240872 100644
--- a/stgit/commands/files.py
+++ b/stgit/commands/files.py
@@ -26,7 +26,7 @@ from stgit import stack, git
 
 
 help = 'show the files modified by a patch (or the current patch)'
-usage = """%prog [options] [<patch>]
+usage = """%prog [options] [[<branch>:]<patch>]
 
 List the files modified by the given patch (defaulting to the current
 one). Passing the '--stat' option shows the diff statistics for the
@@ -38,8 +38,6 @@ directory = DirectoryHasRepository()
 options = [make_option('-s', '--stat',
                        help = 'show the diff stat',
                        action = 'store_true'),
-           make_option('-b', '--branch',
-                       help = 'use BRANCH instead of the default one'),
            make_option('--bare',
                        help = 'bare file names (useful for scripting)',
                        action = 'store_true')
@@ -50,14 +48,14 @@ def func(parser, options, args):
     """Show the files modified by a patch (or the current patch)
     """
     if len(args) == 0:
-        patch = ''
+        patch = 'HEAD'
     elif len(args) == 1:
         patch = args[0]
     else:
         parser.error('incorrect number of arguments')
 
-    rev1 = git_id(crt_series, '%s//bottom' % patch)
-    rev2 = git_id(crt_series, '%s//top' % patch)
+    rev1 = git_id(crt_series, '%s^' % patch)
+    rev2 = git_id(crt_series, '%s' % patch)
 
     if options.stat:
         out.stdout_raw(git.diffstat(git.diff(rev1 = rev1, rev2 = rev2)) + '\n')
diff --git a/stgit/commands/mail.py b/stgit/commands/mail.py
index c87d67e..e04dc2f 100644
--- a/stgit/commands/mail.py
+++ b/stgit/commands/mail.py
@@ -383,8 +383,8 @@ def __build_cover(tmpl, patches, msg_id, options):
                  'shortlog':     stack.shortlog(crt_series.get_patch(p)
                                                 for p in patches),
                  'diffstat':     git.diffstat(git.diff(
-                     rev1 = git_id(crt_series, '%s//bottom' % patches[0]),
-                     rev2 = git_id(crt_series, '%s//top' % patches[-1])))}
+                     rev1 = git_id(crt_series, '%s^' % patches[0]),
+                     rev2 = git_id(crt_series, '%s' % patches[-1])))}
 
     try:
         msg_string = tmpl % tmpl_dict
@@ -460,8 +460,8 @@ def __build_message(tmpl, patch, patch_nr, total_nr, msg_id, ref_id, options):
     else:
         number_str = ''
 
-    diff = git.diff(rev1 = git_id(crt_series, '%s//bottom' % patch),
-                    rev2 = git_id(crt_series, '%s//top' % patch),
+    diff = git.diff(rev1 = git_id(crt_series, '%s^' % patch),
+                    rev2 = git_id(crt_series, '%s' % patch),
                     diff_flags = options.diff_flags)
     tmpl_dict = {'patch':        patch,
                  'sender':       sender,
diff --git a/stgit/commands/pick.py b/stgit/commands/pick.py
index 1f7c84b..2a670e8 100644
--- a/stgit/commands/pick.py
+++ b/stgit/commands/pick.py
@@ -87,8 +87,8 @@ def __pick_commit(commit_id, patchname, options):
 
         out.done()
     elif options.update:
-        rev1 = git_id(crt_series, '//bottom')
-        rev2 = git_id(crt_series, '//top')
+        rev1 = git_id(crt_series, 'HEAD^')
+        rev2 = git_id(crt_series, 'HEAD')
         files = git.barefiles(rev1, rev2).split('\n')
 
         out.start('Updating with commit %s' % commit_id)
@@ -115,10 +115,8 @@ def __pick_commit(commit_id, patchname, options):
         patchname = newpatch.get_name()
 
         # find a patchlog to fork from
-        (refpatchname, refbranchname, refpatchid) = parse_rev(patchname)
-        if refpatchname and not refpatchid and \
-               (not refpatchid or refpatchid == 'top'):
-            # FIXME: should also support picking //top.old
+        refbranchname, refpatchname = parse_rev(patchname)
+        if refpatchname:
             if refbranchname:
                 # assume the refseries is OK, since we already resolved
                 # commit_str to a git_id
diff --git a/stgit/commands/refresh.py b/stgit/commands/refresh.py
index 4695c62..73e4ee0 100644
--- a/stgit/commands/refresh.py
+++ b/stgit/commands/refresh.py
@@ -103,8 +103,8 @@ def func(parser, options, args):
             between = applied[:applied.index(patch):-1]
             pop_patches(crt_series, between, keep = True)
         elif options.update:
-            rev1 = git_id(crt_series, '//bottom')
-            rev2 = git_id(crt_series, '//top')
+            rev1 = git_id(crt_series, 'HEAD^')
+            rev2 = git_id(crt_series, 'HEAD')
             patch_files = git.barefiles(rev1, rev2).split('\n')
             files = [f for f in files if f in patch_files]
             if not files:
diff --git a/stgit/commands/series.py b/stgit/commands/series.py
index 04183bd..c11c74f 100644
--- a/stgit/commands/series.py
+++ b/stgit/commands/series.py
@@ -88,7 +88,7 @@ def __print_patch(stack, patch, branch_str, prefix, empty_prefix, length, option
     elif options.empty and stack.patches.get(patch).is_empty():
         prefix = empty_prefix
 
-    patch_str = patch + branch_str
+    patch_str = branch_str + patch
 
     if options.description or options.author:
         patch_str = patch_str.ljust(length)
@@ -164,7 +164,7 @@ def func(parser, options, args):
         return
 
     if options.showbranch:
-        branch_str = '@' + stack.name
+        branch_str = stack.name + ':'
     else:
         branch_str = ''
 
diff --git a/t/t2000-sync.sh b/t/t2000-sync.sh
index 9852eb8..f4e8b07 100755
--- a/t/t2000-sync.sh
+++ b/t/t2000-sync.sh
@@ -37,7 +37,7 @@ test_expect_success \
 test_expect_success \
     'Create a branch with empty patches' \
     '
-    stg branch -c foo base &&
+    stg branch -c foo {base} &&
     stg new p1 -m p1 &&
     stg new p2 -m p2 &&
     stg new p3 -m p3 &&

^ permalink raw reply related

* [PATCH 2/4] Implement a new patch identification scheme and id command
From: Catalin Marinas @ 2008-07-13 11:40 UTC (permalink / raw)
  To: Karl Hasselström, git
In-Reply-To: <20080713113853.18845.37686.stgit@localhost.localdomain>

The new scheme allows '[<branch>:]<patch>' and '[<branch>:]{base}'
(the latter showing the base of a stack). The former format allows
symbols like ^ and ^{...}.

Signed-off-by: Catalin Marinas <catalin.marinas@gmail.com>
---

 stgit/commands/common.py   |   33 +++++++++++++++++++++++++++++++++
 stgit/commands/id.py       |   28 ++++++++++++----------------
 stgit/lib/git.py           |    4 ++--
 t/t0001-subdir-branches.sh |   24 ++++++++++--------------
 t/t1200-push-modified.sh   |    2 +-
 t/t1201-pull-trailing.sh   |    2 +-
 t/t2200-rebase.sh          |    2 +-
 7 files changed, 60 insertions(+), 35 deletions(-)

diff --git a/stgit/commands/common.py b/stgit/commands/common.py
index 029ec65..0133f1a 100644
--- a/stgit/commands/common.py
+++ b/stgit/commands/common.py
@@ -28,6 +28,7 @@ from stgit.run import *
 from stgit import stack, git, basedir
 from stgit.config import config, file_extensions
 from stgit.lib import stack as libstack
+from stgit.lib import git as libgit
 
 # Command exception class
 class CmdException(StgException):
@@ -116,6 +117,38 @@ def git_id(crt_series, rev):
 
     raise CmdException, 'Unknown patch or revision: %s' % rev
 
+def git_commit(name, repository, branch = None):
+    """Return the a Commit object if 'name' is a patch name or Git commit.
+    The patch names allowed are in the form '<branch>:<patch>' and can
+    be followed by standard symbols used by git-rev-parse. If <patch>
+    is '{base}', it represents the bottom of the stack.
+    """
+    # Try a [branch:]patch name first
+    try:
+        branch, patch = name.split(':', 1)
+    except ValueError:
+        patch = name
+    if not branch:
+        branch = repository.current_branch_name
+
+    # The stack base
+    if patch.startswith('{base}'):
+        base_id = repository.get_stack(branch).base.sha1
+        return repository.rev_parse(base_id + patch[6:])
+
+    # Other combination of branch and patch
+    try:
+        return repository.rev_parse('patches/%s/%s' % (branch, patch),
+                                    discard_stderr = True)
+    except libgit.RepositoryException:
+        pass
+
+    # Try a Git commit
+    try:
+        return repository.rev_parse(name, discard_stderr = True)
+    except libgit.RepositoryException:
+        raise CmdException('%s: Unknown patch or revision name' % name)
+
 def check_local_changes():
     if git.local_changes():
         raise CmdException('local changes in the tree. Use "refresh" or'
diff --git a/stgit/commands/id.py b/stgit/commands/id.py
index 94b0229..3819acc 100644
--- a/stgit/commands/id.py
+++ b/stgit/commands/id.py
@@ -15,28 +15,24 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 """
 
-import sys, os
 from optparse import OptionParser, make_option
 
-from stgit.commands.common import *
-from stgit.utils import *
-from stgit.out import *
-from stgit import stack, git
-
+from stgit.out import out
+from stgit.commands import common
+from stgit.lib import stack
 
 help = 'print the GIT hash value of a StGIT reference'
 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
-'top' or 'bottom' are passed and <patch> is a valid patch name, 'top'
-will be used by default."""
-
-directory = DirectoryHasRepository()
-options = [make_option('-b', '--branch',
-                       help = 'use BRANCH instead of the default one')]
+Print the SHA1 value of a Git id (defaulting to HEAD). In addition to
+the standard Git id's like heads and tags, this command also accepts
+'[<branch>:]<patch>' and '[<branch>:]{base}' showing the id of a patch
+or the base of the stack. If no branch is specified, it defaults to the
+current one. The bottom of a patch is accessible with the
+'[<branch>:]<patch>^' format."""
 
+directory = common.DirectoryHasRepositoryLib()
+options = []
 
 def func(parser, options, args):
     """Show the applied patches
@@ -48,4 +44,4 @@ def func(parser, options, args):
     else:
         parser.error('incorrect number of arguments')
 
-    out.stdout(git_id(crt_series, id_str))
+    out.stdout(common.git_commit(id_str, directory.repository).sha1)
diff --git a/stgit/lib/git.py b/stgit/lib/git.py
index 6ccdfa7..4746da3 100644
--- a/stgit/lib/git.py
+++ b/stgit/lib/git.py
@@ -422,11 +422,11 @@ class Repository(RunWithEnv):
     refs = property(lambda self: self.__refs)
     def cat_object(self, sha1):
         return self.run(['git', 'cat-file', '-p', sha1]).raw_output()
-    def rev_parse(self, rev):
+    def rev_parse(self, rev, discard_stderr = False):
         try:
             return self.get_commit(self.run(
                     ['git', 'rev-parse', '%s^{commit}' % rev]
-                    ).output_one_line())
+                    ).discard_stderr(discard_stderr).output_one_line())
         except run.RunException:
             raise RepositoryException('%s: No such revision' % rev)
     def get_tree(self, sha1):
diff --git a/t/t0001-subdir-branches.sh b/t/t0001-subdir-branches.sh
index 69c11a3..3f7962a 100755
--- a/t/t0001-subdir-branches.sh
+++ b/t/t0001-subdir-branches.sh
@@ -18,25 +18,21 @@ test_expect_success 'Create a patch' \
    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 'Try id with non-slashy branch' \
+  'stg id &&
+   stg id foo &&
+   stg id foo^ &&
+   stg id master:foo &&
+   stg id master:foo^'
 
 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' \
+test_expect_success 'Try new 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'
+   stg id foo^ &&
+   stg id x/y/z:foo &&
+   stg id x/y/z:foo^'
 
 test_expect_success 'Try old id with slashy branch' '
    command_error stg id foo/ &&
diff --git a/t/t1200-push-modified.sh b/t/t1200-push-modified.sh
index 6ebd0a1..2edc760 100755
--- a/t/t1200-push-modified.sh
+++ b/t/t1200-push-modified.sh
@@ -36,7 +36,7 @@ test_expect_success \
     (
         cd foo &&
         GIT_DIR=../bar/.git git-format-patch --stdout \
-          $(cd ../bar && stg id base@master)..HEAD | git-am -3 -k
+          $(cd ../bar && stg id master:{base})..HEAD | git-am -3 -k
     )
 '
 
diff --git a/t/t1201-pull-trailing.sh b/t/t1201-pull-trailing.sh
index 9d70fe0..8a74873 100755
--- a/t/t1201-pull-trailing.sh
+++ b/t/t1201-pull-trailing.sh
@@ -30,7 +30,7 @@ test_expect_success \
     'Port those patches to orig tree' \
     '(cd foo &&
       GIT_DIR=../bar/.git git-format-patch --stdout \
-          $(cd ../bar && stg id base@master)..HEAD |
+          $(cd ../bar && stg id master:{base})..HEAD |
       git-am -3 -k
      )
     '
diff --git a/t/t2200-rebase.sh b/t/t2200-rebase.sh
index a6f43bc..256eaaa 100755
--- a/t/t2200-rebase.sh
+++ b/t/t2200-rebase.sh
@@ -27,7 +27,7 @@ test_expect_success \
 	'Rebase to previous commit' \
 	'
 	stg rebase master~1 &&
-	test `stg id base@stack` = `git rev-parse master~1` &&
+	test `stg id stack:{base}` = `git rev-parse master~1` &&
 	test `stg applied | wc -l` = 1
 	'
 

^ permalink raw reply related

* [PATCH 1/4] Allow e-mails to be sent with the Unix sendmail tool
From: Catalin Marinas @ 2008-07-13 11:40 UTC (permalink / raw)
  To: Karl Hasselström, git
In-Reply-To: <20080713113853.18845.37686.stgit@localhost.localdomain>

If the stgit.smtpserver configuration option does not have a host:port
format, it is assumed to be an external tool. For example, to use
sendmail just set this variable to "/usr/sbin/sendmail -t -i" (see the
examples/gitconfig file).

Signed-off-by: Catalin Marinas <catalin.marinas@gmail.com>
---

 examples/gitconfig     |    1 +
 stgit/commands/mail.py |   46 ++++++++++++++++++++++++++++++++++------------
 2 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/examples/gitconfig b/examples/gitconfig
index c16f786..28d94af 100644
--- a/examples/gitconfig
+++ b/examples/gitconfig
@@ -19,6 +19,7 @@
 	#autoresolved = no
 
 	# SMTP server for sending patches
+	#smtpserver = /usr/sbin/sendmail -t -i
 	#smtpserver = localhost:25
 
 	# Set to 'yes' to use SMTP over TLS
diff --git a/stgit/commands/mail.py b/stgit/commands/mail.py
index b4d4e18..c87d67e 100644
--- a/stgit/commands/mail.py
+++ b/stgit/commands/mail.py
@@ -24,6 +24,7 @@ from stgit.utils import *
 from stgit.out import *
 from stgit import stack, git, version, templates
 from stgit.config import config
+from stgit.run import Run
 
 
 help = 'send a patch or series of patches by e-mail'
@@ -31,13 +32,15 @@ usage = r"""%prog [options] [<patch1>] [<patch2>] [<patch3>..<patch4>]
 
 Send a patch or a range of patches by e-mail using the SMTP server
 specified by the 'stgit.smtpserver' configuration option, or the
-'--smtp-server' command line option. The From address and the e-mail
-format are generated from the template file passed as argument to
-'--template' (defaulting to '.git/patchmail.tmpl' or
-'~/.stgit/templates/patchmail.tmpl' or
+'--smtp-server' command line option. This option can also be an
+absolute path to 'sendmail' followed by command line arguments.
+
+The From address and the e-mail format are generated from the template
+file passed as argument to '--template' (defaulting to
+'.git/patchmail.tmpl' or '~/.stgit/templates/patchmail.tmpl' or
 '/usr/share/stgit/templates/patchmail.tmpl'). A patch can be sent as
-attachment using the --attach option in which case the 'mailattch.tmpl'
-template will be used instead of 'patchmail.tmpl'.
+attachment using the --attach option in which case the
+'mailattch.tmpl' template will be used instead of 'patchmail.tmpl'.
 
 The To/Cc/Bcc addresses can either be added to the template file or
 passed via the corresponding command line options. They can be e-mail
@@ -133,8 +136,9 @@ options = [make_option('-a', '--all',
                        help = 'sleep for SECONDS between e-mails sending'),
            make_option('--refid',
                        help = 'use REFID as the reference id'),
-           make_option('--smtp-server', metavar = 'HOST[:PORT]',
-                       help = 'SMTP server to use for sending mail'),
+           make_option('--smtp-server',
+                       metavar = 'HOST[:PORT] or "/path/to/sendmail -t -i"',
+                       help = 'SMTP server or command to use for sending mail'),
            make_option('-u', '--smtp-user', metavar = 'USER',
                        help = 'username for SMTP authentication'),
            make_option('-p', '--smtp-password', metavar = 'PASSWORD',
@@ -184,8 +188,14 @@ def __parse_addresses(msg):
 
     return (from_addr_list[0], to_addr_list)
 
-def __send_message(smtpserver, from_addr, to_addr_list, msg, sleep,
-                   smtpuser, smtppassword, use_tls):
+def __send_message_sendmail(sendmail, msg):
+    """Send the message using the sendmail command.
+    """
+    cmd = sendmail.split()
+    Run(*cmd).raw_input(msg).discard_output()
+
+def __send_message_smtp(smtpserver, from_addr, to_addr_list, msg,
+                        smtpuser, smtppassword, use_tls):
     """Send the message using the given SMTP server
     """
     try:
@@ -207,13 +217,25 @@ def __send_message(smtpserver, from_addr, to_addr_list, msg, sleep,
         result = s.sendmail(from_addr, to_addr_list, msg)
         if len(result):
             print "mail server refused delivery for the following recipients: %s" % result
-        # give recipients a chance of receiving patches in the correct order
-        time.sleep(sleep)
     except Exception, err:
         raise CmdException, str(err)
 
     s.quit()
 
+def __send_message(smtpserver, from_addr, to_addr_list, msg,
+                   sleep, smtpuser, smtppassword, use_tls):
+    """Message sending dispatcher.
+    """
+    if smtpserver.startswith('/'):
+        # Use the sendmail tool
+        __send_message_sendmail(smtpserver, msg)
+    else:
+        # Use the SMTP server (we have host and port information)
+        __send_message_smtp(smtpserver, from_addr, to_addr_list, msg,
+                            smtpuser, smtppassword, use_tls)
+    # give recipients a chance of receiving patches in the correct order
+    time.sleep(sleep)
+
 def __build_address_headers(msg, options, extra_cc = []):
     """Build the address headers and check existing headers in the
     template.

^ 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