Git development
 help / color / mirror / Atom feed
* [PATCH/RFC v3 0/6] N-th last checked out branch
From: Thomas Rast @ 2009-01-17  3:30 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Johannes Schindelin, Johannes Sixt, Johan Herland
In-Reply-To: <7v8wpcs38c.fsf@gitster.siamese.dyndns.org>

Junio C Hamano <gitster@pobox.com> writes:
> "cd -" is a very good analogy why your "-" shortcut is a short-sighted
> convenience feature that is too narrow and not well designed.  "cd -" can
> go back, but you cannot say "ls -" to list the contents of the previous
> directory.

True.

> Another reason is the one level limitation.

It shares that limitation with my mind ;-)

But well, since you all seem to want a more general solution, here's a
draft.

I started poking around in refs.c for the backwards search, but the
two reflog functions had a lot of functionality implemented very
differently.  So 1-4 are just cleanup and adding that backwards
iterator.  Note that 3/6 changes for_each_reflog_ent() to die() when
it finds a format error, unlike the previous behaviour.  No tests
seemed to care, but maybe someone out there relies on having broken
reflogs? ;-)

>  * The code read the reflog twice, first to count how many branch
>    switching there are and then to locate the N-th entry we are interested
>    in, because I was lazy.  We may want an API to enumerate reflog entries
>    in reverse.

So this might be settled.

>  * The reflog parser only parses "checkout" and not rebase action.  It
>    also does not notice "git checkout HEAD^" is not switching to a real
>    branch.

I don't handle this, but I'm not sure how much of a problem it is.  It
can correctly detach and re-attach even in cases such as HEAD^.

Ok, now that you mention it, it will probably put you on the parent of
whatever you happened to be on, instead of the earlier value of HEAD^.

>      $ git checkout @{-1}

One problem with the syntax is that the assumption that there can only
be a single @{} construct is quite entrenched in sha1_name.c.  So if
we want to support @{-1}@{1}, that'll need some extra work.

@{-1}~2 and similar work fine though.


Other things of note:

I changed the semantics to really only look at checkouts that "did
something".  If you keep saying 'git checkout master' over and over,
those will not count towards the N.

I changed the parser to read the 'checkout: moving from $old' instead
of the 'to $new'.  The above semantics introduced too many extra
conditions for my taste if we wanted to support the pre-1.5.3 reflog
comment format.  (You'd have to check if the $to was changed from the
last [newer] entry, but then there's another border case when you do
'git init; git checkout -b side; git checkout -' because you never
moved to master.)

The @{date} syntax will be marginally slower after the refactoring
because the old parser carefully avoided parsing numbers where it
could.  (I guess it could actually be done as a bisection for an extra
order of magnitude.)

It's far too early here to be sending mail.

Interactive rebase needs a "move hunk" feature.


Thomas Rast (6):
  reflog: refactor parsing and checking
  reflog: refactor log open+mmap
  reflog: make for_each_reflog_ent use mmap
  reflog: add backwards iterator
  sha1_name: implement @{-N} syntax for N-th last checked out
  checkout: implement '@{-N}' and '-' special abbreviations

 Documentation/git-checkout.txt  |    4 +
 Documentation/git-rev-parse.txt |    3 +
 builtin-checkout.c              |   15 ++-
 cache.h                         |    1 +
 refs.c                          |  285 +++++++++++++++++++++++----------------
 refs.h                          |    1 +
 sha1_name.c                     |   79 +++++++++++-
 t/t1505-rev-parse-last.sh       |   71 ++++++++++
 t/t2012-checkout-last.sh        |   50 +++++++
 9 files changed, 387 insertions(+), 122 deletions(-)
 create mode 100755 t/t1505-rev-parse-last.sh
 create mode 100755 t/t2012-checkout-last.sh

^ permalink raw reply

* [PATCH/RFC v3 5/6] sha1_name: implement @{-N} syntax for N-th last checked out
From: Thomas Rast @ 2009-01-17  3:30 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Johannes Schindelin, Johannes Sixt, Johan Herland
In-Reply-To: <7v8wpcs38c.fsf@gitster.siamese.dyndns.org>

Implements a new syntax @{-N} that parses the reflog for the N-th last
interesting 'checkout: moving from $branch to $new' entry and
substitutes $branch.  Here, "interesting" is defined as $branch !=
$new.  We then substitute the real branch name for the parse.

For example:

  git checkout foo
  git checkout bar
  git checkout master
  git checkout master   # did not move, so doesn't count
  git rev-parse @{-1}   # same as bar
  git rev-parse @{-2}   # same as foo
  git rev-parse @{-2}~3 # same as foo~3

Thanks to Junio for much of the code.

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---
 Documentation/git-rev-parse.txt |    3 +
 cache.h                         |    1 +
 sha1_name.c                     |   79 +++++++++++++++++++++++++++++++++++++-
 t/t1505-rev-parse-last.sh       |   71 +++++++++++++++++++++++++++++++++++
 4 files changed, 151 insertions(+), 3 deletions(-)
 create mode 100755 t/t1505-rev-parse-last.sh

diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 2921da3..3ccef2f 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -212,6 +212,9 @@ when you run 'git-merge'.
   reflog of the current branch. For example, if you are on the
   branch 'blabla', then '@\{1\}' means the same as 'blabla@\{1\}'.
 
+* The special construct '@\{-<n>\}' means the <n>th branch checked out
+  before the current one.
+
 * A suffix '{caret}' to a revision parameter means the first parent of
   that commit object.  '{caret}<n>' means the <n>th parent (i.e.
   'rev{caret}'
diff --git a/cache.h b/cache.h
index 8e1af26..0dd9168 100644
--- a/cache.h
+++ b/cache.h
@@ -663,6 +663,7 @@ static inline unsigned int hexval(unsigned char c)
 extern const char *resolve_ref(const char *path, unsigned char *sha1, int, int *);
 extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref);
 extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);
+extern int interpret_nth_last_branch(const char *str, struct strbuf *);
 
 extern int refname_match(const char *abbrev_name, const char *full_name, const char **rules);
 extern const char *ref_rev_parse_rules[];
diff --git a/sha1_name.c b/sha1_name.c
index 159c2ab..b2dd302 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -297,6 +297,8 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
 	return logs_found;
 }
 
+static int get_sha1_1(const char *name, int len, unsigned char *sha1);
+
 static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 {
 	static const char *warning = "warning: refname '%.*s' is ambiguous.\n";
@@ -307,7 +309,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 	if (len == 40 && !get_sha1_hex(str, sha1))
 		return 0;
 
-	/* basic@{time or number} format to query ref-log */
+	/* basic@{time or number or -number} format to query ref-log */
 	reflog_len = at = 0;
 	if (str[len-1] == '}') {
 		for (at = 0; at < len - 1; at++) {
@@ -324,6 +326,14 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 		return -1;
 
 	if (!len && reflog_len) {
+		struct strbuf buf = STRBUF_INIT;
+		int ret;
+		/* try the @{-N} syntax for n-th checkout */
+		ret = interpret_nth_last_branch(str+at, &buf);
+		if (ret > 0) {
+			/* substitute this branch name and restart */
+			return get_sha1_1(buf.buf, buf.len, sha1);
+		}
 		/* allow "@{...}" to mean the current branch reflog */
 		refs_found = dwim_ref("HEAD", 4, sha1, &real_ref);
 	} else if (reflog_len)
@@ -379,8 +389,6 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 	return 0;
 }
 
-static int get_sha1_1(const char *name, int len, unsigned char *sha1);
-
 static int get_parent(const char *name, int len,
 		      unsigned char *result, int idx)
 {
@@ -674,6 +682,71 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1)
 	return retval;
 }
 
+struct grab_nth_branch_switch_cbdata {
+	int nth;
+	struct strbuf *buf;
+};
+
+static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
+				  const char *email, unsigned long timestamp, int tz,
+				  const char *message, void *cb_data)
+{
+	struct grab_nth_branch_switch_cbdata *cb = cb_data;
+	const char *match = NULL, *target = NULL;
+	size_t len;
+
+	if (!prefixcmp(message, "checkout: moving from ")) {
+		match = message + strlen("checkout: moving from ");
+		if ((target = strstr(match, " to ")) != NULL)
+			target += 4;
+	}
+
+	if (!match)
+		return 0;
+
+	len = target - match - 4;
+	if (target[len] == '\n' && !strncmp(match, target, len))
+		return 0;
+
+	if (--cb->nth <= 0) {
+		strbuf_reset(cb->buf);
+		strbuf_add(cb->buf, match, len);
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * This reads "@{-N}" syntax, finds the name of the Nth previous
+ * branch we were on, and places the name of the branch in the given
+ * buf and returns 0 if successful.
+ *
+ * If the input is not of the accepted format, it returns a negative
+ * number to signal an error.
+ */
+int interpret_nth_last_branch(const char *name, struct strbuf *buf)
+{
+	int nth;
+	struct grab_nth_branch_switch_cbdata cb;
+	const char *brace;
+	char *num_end;
+
+	if (name[0] != '@' || name[1] != '{' || name[2] != '-')
+		return -1;
+	brace = strchr(name, '}');
+	if (!brace)
+		return -1;
+	nth = strtol(name+3, &num_end, 10);
+	if (num_end != brace)
+		return -1;
+
+	cb.nth = nth;
+	cb.buf = buf;
+	for_each_reflog_ent_backward("HEAD", grab_nth_branch_switch, &cb);
+
+	return brace-name+1;
+}
+
 /*
  * This is like "get_sha1_basic()", except it allows "sha1 expressions",
  * notably "xyz^" for "parent of xyz"
diff --git a/t/t1505-rev-parse-last.sh b/t/t1505-rev-parse-last.sh
new file mode 100755
index 0000000..1e49dd2
--- /dev/null
+++ b/t/t1505-rev-parse-last.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+
+test_description='test @{-N} syntax'
+
+. ./test-lib.sh
+
+
+make_commit () {
+	echo "$1" > "$1" &&
+	git add "$1" &&
+	git commit -m "$1"
+}
+
+
+test_expect_success 'setup' '
+
+	make_commit 1 &&
+	git branch side &&
+	make_commit 2 &&
+	make_commit 3 &&
+	git checkout side &&
+	make_commit 4 &&
+	git merge master &&
+	git checkout master
+
+'
+
+# 1 -- 2 -- 3 master
+#  \         \
+#   \         \
+#    --- 4 --- 5 side
+#
+# and 'side' should be the last branch
+
+git log --graph --all --pretty=oneline --decorate
+
+test_rev_equivalent () {
+
+	git rev-parse "$1" > expect &&
+	git rev-parse "$2" > output &&
+	test_cmp expect output
+
+}
+
+test_expect_success '@{-1} works' '
+	test_rev_equivalent side @{-1}
+'
+
+test_expect_success '@{-1}~2 works' '
+	test_rev_equivalent side~2 @{-1}~2
+'
+
+test_expect_success '@{-1}^2 works' '
+	test_rev_equivalent side^2 @{-1}^2
+'
+
+test_expect_failure '@{-1}@{1} works' '
+	test_rev_equivalent side@{1} @{-1}@{1}
+'
+
+test_expect_success '@{-2} works' '
+	test_rev_equivalent master @{-2}
+'
+
+test_expect_success '@{-3} fails' '
+	test_must_fail git rev-parse @{-3}
+'
+
+test_done
+
+
-- 
1.6.1.315.g92577

^ permalink raw reply related

* [PATCH/RFC v3 1/6] reflog: refactor parsing and checking
From: Thomas Rast @ 2009-01-17  3:30 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Johannes Schindelin, Johannes Sixt, Johan Herland
In-Reply-To: <7v8wpcs38c.fsf@gitster.siamese.dyndns.org>

read_ref_at() and for_each_reflog_ent() both had parsing and error
checking routines.  Refactor into a separate function that fully
parses a single entry.  Note that this switches for_each_reflog_ent()
from silently ignoring errors to die().

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---
 refs.c |  197 ++++++++++++++++++++++++++++++++--------------------------------
 1 files changed, 98 insertions(+), 99 deletions(-)

diff --git a/refs.c b/refs.c
index 33ced65..4571fac 100644
--- a/refs.c
+++ b/refs.c
@@ -1337,24 +1337,68 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
 	return 0;
 }
 
-static char *ref_msg(const char *line, const char *endp)
+/*
+ * Check and parse a single reflog line.  Assumes that there is only
+ * one newline in the range buf[0]..buf[len-1] (but does check that it
+ * is at buf[len-1]).
+ */
+static void parse_reflog_line(const char *buf, int len,
+			      unsigned char *osha1, unsigned char *nsha1,
+			      char **email,
+			      unsigned long *timestamp, int *tz,
+			      char **message,
+			      const char *logname)
 {
-	const char *ep;
-	line += 82;
-	ep = memchr(line, '\n', endp - line);
-	if (!ep)
-		ep = endp;
-	return xmemdupz(line, ep - line);
+	static char *retbuf = NULL;
+	static int retbufsz = 0;
+	char *tzstr, *email_end;
+
+	if (len < 83 || buf[len-1] != '\n')
+		die("Log %s is corrupt (entry too short or unterminated).", logname);
+
+	if (get_sha1_hex(buf, osha1) || buf[40] != ' ')
+		die("Log %s is corrupt (malformed old sha1).", logname);
+
+	if (get_sha1_hex(buf + 41, nsha1) || buf[81] != ' ')
+		die("Log %s is corrupt (malformed new sha1).", logname);
+
+	ALLOC_GROW(retbuf, len-82+1, retbufsz);
+	memcpy(retbuf, buf+82, len-82);
+	retbuf[len-82] = '\0';
+
+	email_end = strchr(retbuf, '>');
+	if (!email_end || email_end[1] != ' ')
+		die("Log %s is corrupt (malformed email field).", logname);
+
+	*email = retbuf;
+	email_end[1] = '\0';
+
+	*timestamp = strtoul(email_end + 2, &tzstr, 10);
+	if (!(*timestamp) || !tzstr || tzstr[0] != ' ' ||
+	    (tzstr[1] != '+' && tzstr[1] != '-') ||
+	    !isdigit(tzstr[2]) || !isdigit(tzstr[3]) ||
+	    !isdigit(tzstr[4]) || !isdigit(tzstr[5]))
+		die("Log %s is corrupt (malformed timezone).", logname);
+	if (!(tzstr[6] == '\t' || tzstr[6] == '\n'))
+		die("Log %s is corrupt (bad message field separator).", logname);
+	*tz = strtoul(tzstr, NULL, 10);
+
+	if (tzstr[6] == '\t')
+		*message = tzstr+7;
+	else
+		*message = tzstr+6;
 }
 
 int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1, char **msg, unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
 {
-	const char *logfile, *logdata, *logend, *rec, *lastgt, *lastrec;
-	char *tz_c;
+	const char *logfile, *logdata, *logend, *rec, *start;
+	char *email, *message;
 	int logfd, tz, reccnt = 0;
 	struct stat st;
 	unsigned long date;
-	unsigned char logged_sha1[20];
+	unsigned char new_sha1[20];
+	unsigned char old_sha1[20];
+	unsigned char next_sha1[20];
 	void *log_mapped;
 	size_t mapsz;
 
@@ -1370,86 +1414,55 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
 	logdata = log_mapped;
 	close(logfd);
 
-	lastrec = NULL;
 	rec = logend = logdata + st.st_size;
+	if (logdata < rec && *(rec-1) == '\n')
+		rec--;
 	while (logdata < rec) {
-		reccnt++;
-		if (logdata < rec && *(rec-1) == '\n')
-			rec--;
-		lastgt = NULL;
-		while (logdata < rec && *(rec-1) != '\n') {
-			rec--;
-			if (*rec == '>')
-				lastgt = rec;
-		}
-		if (!lastgt)
-			die("Log %s is corrupt.", logfile);
-		date = strtoul(lastgt + 1, &tz_c, 10);
+		start = memrchr(logdata, '\n', rec-logdata);
+		if (start)
+			start++;
+		else
+			start = logdata;
+		parse_reflog_line(start, rec-start+1,
+				  old_sha1, new_sha1,
+				  &email, &date, &tz, &message,
+				  logfile);
+
+		if (cutoff_time)
+			*cutoff_time = date;
+		if (cutoff_tz)
+			*cutoff_tz = tz;
+		if (cutoff_cnt)
+			*cutoff_cnt = reccnt;
+		if (msg)
+			*msg = message;
+
 		if (date <= at_time || cnt == 0) {
-			tz = strtoul(tz_c, NULL, 10);
-			if (msg)
-				*msg = ref_msg(rec, logend);
-			if (cutoff_time)
-				*cutoff_time = date;
-			if (cutoff_tz)
-				*cutoff_tz = tz;
-			if (cutoff_cnt)
-				*cutoff_cnt = reccnt - 1;
-			if (lastrec) {
-				if (get_sha1_hex(lastrec, logged_sha1))
-					die("Log %s is corrupt.", logfile);
-				if (get_sha1_hex(rec + 41, sha1))
-					die("Log %s is corrupt.", logfile);
-				if (hashcmp(logged_sha1, sha1)) {
-					fprintf(stderr,
-						"warning: Log %s has gap after %s.\n",
-						logfile, show_date(date, tz, DATE_RFC2822));
-				}
-			}
-			else if (date == at_time) {
-				if (get_sha1_hex(rec + 41, sha1))
-					die("Log %s is corrupt.", logfile);
-			}
-			else {
-				if (get_sha1_hex(rec + 41, logged_sha1))
-					die("Log %s is corrupt.", logfile);
-				if (hashcmp(logged_sha1, sha1)) {
-					fprintf(stderr,
-						"warning: Log %s unexpectedly ended on %s.\n",
-						logfile, show_date(date, tz, DATE_RFC2822));
-				}
-			}
+			if (reccnt && hashcmp(new_sha1, next_sha1))
+				fprintf(stderr,
+					"warning: Log %s has gap after %s.\n",
+					logfile, show_date(date, tz, DATE_RFC2822));
+			if (!reccnt && date < at_time && hashcmp(new_sha1, next_sha1))
+				fprintf(stderr,
+					"warning: Log %s unexpectedly ended on %s.\n",
+					logfile, show_date(date, tz, DATE_RFC2822));
+				/* leave caller's sha1 untouched */
+			else
+				hashcpy(sha1, new_sha1);
 			munmap(log_mapped, mapsz);
 			return 0;
 		}
-		lastrec = rec;
+
+		hashcpy(next_sha1, old_sha1);
+		rec = start-1;
 		if (cnt > 0)
 			cnt--;
+		reccnt++;
 	}
 
-	rec = logdata;
-	while (rec < logend && *rec != '>' && *rec != '\n')
-		rec++;
-	if (rec == logend || *rec == '\n')
-		die("Log %s is corrupt.", logfile);
-	date = strtoul(rec + 1, &tz_c, 10);
-	tz = strtoul(tz_c, NULL, 10);
-	if (get_sha1_hex(logdata, sha1))
-		die("Log %s is corrupt.", logfile);
-	if (is_null_sha1(sha1)) {
-		if (get_sha1_hex(logdata + 41, sha1))
-			die("Log %s is corrupt.", logfile);
-	}
-	if (msg)
-		*msg = ref_msg(logdata, logend);
-	munmap(log_mapped, mapsz);
+	hashcpy(sha1, new_sha1);
 
-	if (cutoff_time)
-		*cutoff_time = date;
-	if (cutoff_tz)
-		*cutoff_tz = tz;
-	if (cutoff_cnt)
-		*cutoff_cnt = reccnt;
+	munmap(log_mapped, mapsz);
 	return 1;
 }
 
@@ -1466,30 +1479,16 @@ int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
 		return -1;
 	while (fgets(buf, sizeof(buf), logfp)) {
 		unsigned char osha1[20], nsha1[20];
-		char *email_end, *message;
+		char *email, *message;
 		unsigned long timestamp;
 		int len, tz;
 
-		/* old SP new SP name <email> SP time TAB msg LF */
 		len = strlen(buf);
-		if (len < 83 || buf[len-1] != '\n' ||
-		    get_sha1_hex(buf, osha1) || buf[40] != ' ' ||
-		    get_sha1_hex(buf + 41, nsha1) || buf[81] != ' ' ||
-		    !(email_end = strchr(buf + 82, '>')) ||
-		    email_end[1] != ' ' ||
-		    !(timestamp = strtoul(email_end + 2, &message, 10)) ||
-		    !message || message[0] != ' ' ||
-		    (message[1] != '+' && message[1] != '-') ||
-		    !isdigit(message[2]) || !isdigit(message[3]) ||
-		    !isdigit(message[4]) || !isdigit(message[5]))
-			continue; /* corrupt? */
-		email_end[1] = '\0';
-		tz = strtol(message + 1, NULL, 10);
-		if (message[6] != '\t')
-			message += 6;
-		else
-			message += 7;
-		ret = fn(osha1, nsha1, buf+82, timestamp, tz, message, cb_data);
+		parse_reflog_line(buf, len,
+				  osha1, nsha1,
+				  &email, &timestamp, &tz, &message,
+				  logfile);
+		ret = fn(osha1, nsha1, email, timestamp, tz, message, cb_data);
 		if (ret)
 			break;
 	}
-- 
1.6.1.315.g92577

^ permalink raw reply related

* [PATCH/RFC v3 6/6] checkout: implement '@{-N}' and '-' special abbreviations
From: Thomas Rast @ 2009-01-17  3:30 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Johannes Schindelin, Johannes Sixt, Johan Herland
In-Reply-To: <7v8wpcs38c.fsf@gitster.siamese.dyndns.org>

Checks if the branch to be checked out is either '@{-N}' or the
special shorthand '-' for '@{-1}' (i.e. the last checked out branch).
If so, we take it to mean the branch name, not the corresponding SHA,
so that we check out an attached HEAD on that branch.

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---
 Documentation/git-checkout.txt |    4 +++
 builtin-checkout.c             |   15 ++++++++++-
 t/t2012-checkout-last.sh       |   50 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+), 2 deletions(-)
 create mode 100755 t/t2012-checkout-last.sh

diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 9cd5151..3bccffa 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -133,6 +133,10 @@ the conflicted merge in the specified paths.
 +
 When this parameter names a non-branch (but still a valid commit object),
 your HEAD becomes 'detached'.
++
+As a special case, the "`@\{-N\}`" syntax for the N-th last branch
+checks out the branch (instead of detaching).  You may also specify
+"`-`" which is synonymous with "`@\{-1\}`".
 
 
 Detached HEAD
diff --git a/builtin-checkout.c b/builtin-checkout.c
index b5dd9c0..b0a101b 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -361,8 +361,16 @@ struct branch_info {
 static void setup_branch_path(struct branch_info *branch)
 {
 	struct strbuf buf = STRBUF_INIT;
-	strbuf_addstr(&buf, "refs/heads/");
-	strbuf_addstr(&buf, branch->name);
+	int ret;
+
+	if ((ret = interpret_nth_last_branch(branch->name, &buf))
+	    && ret == strlen(branch->name)) {
+		branch->name = xstrdup(buf.buf);
+		strbuf_splice(&buf, 0, 0, "refs/heads/", 11);
+	} else {
+		strbuf_addstr(&buf, "refs/heads/");
+		strbuf_addstr(&buf, branch->name);
+	}
 	branch->path = strbuf_detach(&buf, NULL);
 }
 
@@ -671,6 +679,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 		arg = argv[0];
 		has_dash_dash = (argc > 1) && !strcmp(argv[1], "--");
 
+		if (!strcmp(arg, "-"))
+			arg = "@{-1}";
+
 		if (get_sha1(arg, rev)) {
 			if (has_dash_dash)          /* case (1) */
 				die("invalid reference: %s", arg);
diff --git a/t/t2012-checkout-last.sh b/t/t2012-checkout-last.sh
new file mode 100755
index 0000000..320f6eb
--- /dev/null
+++ b/t/t2012-checkout-last.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+test_description='checkout can switch to last branch'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	echo hello >world &&
+	git add world &&
+	git commit -m initial &&
+	git branch other &&
+	echo "hello again" >>world &&
+	git add world &&
+	git commit -m second
+'
+
+test_expect_success '"checkout -" does not work initially' '
+	test_must_fail git checkout -
+'
+
+test_expect_success 'first branch switch' '
+	git checkout other
+'
+
+test_expect_success '"checkout -" switches back' '
+	git checkout - &&
+	test "z$(git symbolic-ref HEAD)" = "zrefs/heads/master"
+'
+
+test_expect_success '"checkout -" switches forth' '
+	git checkout - &&
+	test "z$(git symbolic-ref HEAD)" = "zrefs/heads/other"
+'
+
+test_expect_success 'detach HEAD' '
+	git checkout $(git rev-parse HEAD)
+'
+
+test_expect_success '"checkout -" attaches again' '
+	git checkout - &&
+	test "z$(git symbolic-ref HEAD)" = "zrefs/heads/other"
+'
+
+test_expect_success '"checkout -" detaches again' '
+	git checkout - &&
+	test "z$(git rev-parse HEAD)" = "z$(git rev-parse other)" &&
+	test_must_fail git symbolic-ref HEAD
+'
+
+test_done
-- 
1.6.1.315.g92577

^ permalink raw reply related

* [PATCH/RFC v3 2/6] reflog: refactor log open+mmap
From: Thomas Rast @ 2009-01-17  3:30 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Johannes Schindelin, Johannes Sixt, Johan Herland
In-Reply-To: <7v8wpcs38c.fsf@gitster.siamese.dyndns.org>

Move the open+mmap code from read_ref_at() to a separate function for
the next patch.

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---
 refs.c |   54 ++++++++++++++++++++++++++++++++----------------------
 1 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/refs.c b/refs.c
index 4571fac..0a57896 100644
--- a/refs.c
+++ b/refs.c
@@ -1389,12 +1389,31 @@ static void parse_reflog_line(const char *buf, int len,
 		*message = tzstr+6;
 }
 
+static char *open_reflog(const char *ref, size_t *mapsz, const char **logfile)
+{
+	struct stat st;
+	int logfd;
+	char *map;
+
+	*logfile = git_path("logs/%s", ref);
+	logfd = open(*logfile, O_RDONLY, 0);
+	if (logfd < 0)
+		return NULL;
+	if (fstat(logfd, &st))
+		return NULL;
+
+	*mapsz = xsize_t(st.st_size);
+	map = xmmap(NULL, *mapsz, PROT_READ, MAP_PRIVATE, logfd, 0);
+	close(logfd);
+	return map;
+}
+
+
 int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1, char **msg, unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
 {
-	const char *logfile, *logdata, *logend, *rec, *start;
+	const char *logfile, *logdata, *logend, *rec, *end;
 	char *email, *message;
-	int logfd, tz, reccnt = 0;
-	struct stat st;
+	int tz, reccnt = 0;
 	unsigned long date;
 	unsigned char new_sha1[20];
 	unsigned char old_sha1[20];
@@ -1402,28 +1421,20 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
 	void *log_mapped;
 	size_t mapsz;
 
-	logfile = git_path("logs/%s", ref);
-	logfd = open(logfile, O_RDONLY, 0);
-	if (logfd < 0)
+	logdata = log_mapped = open_reflog(ref, &mapsz, &logfile);
+	if (!logdata)
 		die("Unable to read log %s: %s", logfile, strerror(errno));
-	fstat(logfd, &st);
-	if (!st.st_size)
+	if (!mapsz)
 		die("Log %s is empty.", logfile);
-	mapsz = xsize_t(st.st_size);
-	log_mapped = xmmap(NULL, mapsz, PROT_READ, MAP_PRIVATE, logfd, 0);
-	logdata = log_mapped;
-	close(logfd);
 
-	rec = logend = logdata + st.st_size;
-	if (logdata < rec && *(rec-1) == '\n')
-		rec--;
+	rec = logend = logdata + mapsz;
 	while (logdata < rec) {
-		start = memrchr(logdata, '\n', rec-logdata);
-		if (start)
-			start++;
-		else
-			start = logdata;
-		parse_reflog_line(start, rec-start+1,
+		if (logdata < rec && rec[-1] == '\n')
+			rec--;
+		end = rec;
+		while (logdata < rec && rec[-1] != '\n')
+			rec--;
+		parse_reflog_line(rec, end-rec+1,
 				  old_sha1, new_sha1,
 				  &email, &date, &tz, &message,
 				  logfile);
@@ -1454,7 +1465,6 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
 		}
 
 		hashcpy(next_sha1, old_sha1);
-		rec = start-1;
 		if (cnt > 0)
 			cnt--;
 		reccnt++;
-- 
1.6.1.315.g92577

^ permalink raw reply related

* [PATCH/RFC v3 4/6] reflog: add backwards iterator
From: Thomas Rast @ 2009-01-17  3:30 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Johannes Schindelin, Johannes Sixt, Johan Herland
In-Reply-To: <7v8wpcs38c.fsf@gitster.siamese.dyndns.org>

Add for_each_reflog_ent_backward() which does the same as
for_each_reflog_ent(), except it traverses the reflog in backwards
(newest to oldest) order.

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---
 refs.c |   35 +++++++++++++++++++++++++++++++++++
 refs.h |    1 +
 2 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/refs.c b/refs.c
index 3848aa0..cc78f63 100644
--- a/refs.c
+++ b/refs.c
@@ -1476,6 +1476,41 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
 	return 1;
 }
 
+int for_each_reflog_ent_backward(const char *ref, each_reflog_ent_fn fn, void *cb_data)
+{
+	const char *log_mapped, *buf, *log_end, *logfile;
+	size_t mapsz;
+	int ret = 0;
+
+	log_mapped = open_reflog(ref, &mapsz, &logfile);
+	if (!log_mapped)
+		return -1;
+	buf = log_end = log_mapped + mapsz;
+
+	while (buf > log_mapped) {
+		unsigned char osha1[20], nsha1[20];
+		char *email, *message;
+		const char *end;
+		unsigned long timestamp;
+		int tz;
+
+		while (buf > log_mapped && buf[-1] == '\n')
+			buf--;
+		end = buf;
+		while (buf > log_mapped && buf[-1] != '\n')
+			buf--;
+		parse_reflog_line(buf, end-buf+1,
+				  osha1, nsha1,
+				  &email, &timestamp, &tz, &message,
+				  logfile);
+		ret = fn(osha1, nsha1, email, timestamp, tz, message, cb_data);
+		if (ret)
+			break;
+	}
+	munmap((void*) log_mapped, mapsz);
+	return ret;
+}
+
 int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
 {
 	const char *log_mapped, *buf, *log_end, *logfile;
diff --git a/refs.h b/refs.h
index 06ad260..723bddc 100644
--- a/refs.h
+++ b/refs.h
@@ -60,6 +60,7 @@ struct ref_lock {
 /* iterate over reflog entries */
 typedef int each_reflog_ent_fn(unsigned char *osha1, unsigned char *nsha1, const char *, unsigned long, int, const char *, void *);
 int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data);
+int for_each_reflog_ent_backward(const char *ref, each_reflog_ent_fn fn, void *cb_data);
 
 /*
  * Calls the specified function for each reflog file until it returns nonzero,
-- 
1.6.1.315.g92577

^ permalink raw reply related

* [PATCH/RFC v3 3/6] reflog: make for_each_reflog_ent use mmap
From: Thomas Rast @ 2009-01-17  3:30 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Johannes Schindelin, Johannes Sixt, Johan Herland
In-Reply-To: <7v8wpcs38c.fsf@gitster.siamese.dyndns.org>

Now that all building blocks have been refactored, we can implement
for_each_reflog_ent in terms of them, so that it uses mmap.

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---
 refs.c |   25 ++++++++++++++++---------
 1 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/refs.c b/refs.c
index 0a57896..3848aa0 100644
--- a/refs.c
+++ b/refs.c
@@ -1478,22 +1478,28 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
 
 int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
 {
-	const char *logfile;
-	FILE *logfp;
-	char buf[1024];
+	const char *log_mapped, *buf, *log_end, *logfile;
+	size_t mapsz;
 	int ret = 0;
 
-	logfile = git_path("logs/%s", ref);
-	logfp = fopen(logfile, "r");
-	if (!logfp)
+	buf = log_mapped = open_reflog(ref, &mapsz, &logfile);
+	if (!log_mapped)
 		return -1;
-	while (fgets(buf, sizeof(buf), logfp)) {
+	log_end = buf + mapsz;
+
+	while (buf < log_end) {
 		unsigned char osha1[20], nsha1[20];
 		char *email, *message;
+		const char *next;
 		unsigned long timestamp;
 		int len, tz;
 
-		len = strlen(buf);
+		next = memchr(buf, '\n', log_end - buf);
+		if (next)
+			next++;
+		else
+			next = log_end;
+		len = next - buf;
 		parse_reflog_line(buf, len,
 				  osha1, nsha1,
 				  &email, &timestamp, &tz, &message,
@@ -1501,8 +1507,9 @@ int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
 		ret = fn(osha1, nsha1, email, timestamp, tz, message, cb_data);
 		if (ret)
 			break;
+		buf = next;
 	}
-	fclose(logfp);
+	munmap((void*) log_mapped, mapsz);
 	return ret;
 }
 
-- 
1.6.1.315.g92577

^ permalink raw reply related

* Re: git-difftool
From: enso @ 2009-01-17  3:47 UTC (permalink / raw)
  To: git
In-Reply-To: <46dff0320901011759ke7026d9hafe4fdde099e370b@mail.gmail.com>




Ping Yin wrote:
> 
> Thanks. With GIT_PAGER="" it works now.
> 

Personally, I didn't like having to screw around with environment variables
directly to get vimdiff to work. So I did the following:

1) Made a simple diff script gitvimdiff.sh:

#!/bin/env sh
vimdiff "$2" "$5"

2) git config --global diff.external ~/path/to/gitvimdiff.sh
3) git config --global pager.diff ""

Now when I run git-diff it uses vimdiff (hooray) and automatically turns the
pager off for me! Now only if I could get meld to work under cygwin.
-- 
View this message in context: http://n2.nabble.com/git-difftool-tp1814817p2171934.html
Sent from the git mailing list archive at Nabble.com.

^ permalink raw reply

* Re: git-difftool
From: David Aguilar @ 2009-01-17  4:41 UTC (permalink / raw)
  To: enso; +Cc: git
In-Reply-To: <1232164040173-2171934.post@n2.nabble.com>

On Fri, Jan 16, 2009 at 7:47 PM, enso <a.calhoon@gmail.com> wrote:
> Ping Yin wrote:
>>
>> Thanks. With GIT_PAGER="" it works now.
>>
>
> Personally, I didn't like having to screw around with environment variables
> directly to get vimdiff to work. So I did the following:
>
> 1) Made a simple diff script gitvimdiff.sh:
>
> #!/bin/env sh
> vimdiff "$2" "$5"
>
> 2) git config --global diff.external ~/path/to/gitvimdiff.sh
> 3) git config --global pager.diff ""
>
> Now when I run git-diff it uses vimdiff (hooray) and automatically turns the
> pager off for me! Now only if I could get meld to work under cygwin.
> --

Hello sir
It sounds like you were looking for exactly the patch I sent last night =)

http://article.gmane.org/gmane.comp.version-control.git/105925


With 'git difftool' you just do it once:

git config --global merge.tool vimdiff
git difftool [diff options]

The nice thing is that it supports the same configuration variables as
'git mergetool', so if you've already set things up to work correctly
with mergetool then you're already setup for difftool.

Meld.. I can't say I've used it on windows.
I have successfully used kdiff3 with msysgit, though.  I just
downloaded it and copied it to /bin.

difftool supports meld, though, so if you get a build of meld that
works then you should in theory be able to use it just by setting
merge.tool to meld.

-- 
    David

^ permalink raw reply

* Re: [PATCH 1/3] http-push: append slash if possible for directories
From: Johannes Schindelin @ 2009-01-17  5:19 UTC (permalink / raw)
  To: Ray Chuan; +Cc: git
In-Reply-To: <be6fef0d0901161853y6784310dgf94dadb2218001a1@mail.gmail.com>

Hi,

On Sat, 17 Jan 2009, Ray Chuan wrote:

>  src/git-1.6.1/http-push.c |   21 ++++++++++++++++-----

That is a, uhm, creative way of using Git...

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH 3/3] http-push: update tests
From: Johannes Schindelin @ 2009-01-17  5:23 UTC (permalink / raw)
  To: Ray Chuan; +Cc: git
In-Reply-To: <be6fef0d0901161859qbea135bwe89e48caaa69a77c@mail.gmail.com>

Hi,

On Sat, 17 Jan 2009, Ray Chuan wrote:

> note: the test needs to chmod the test_repo.git folder so that
> apache/mod_dav can create .DAV folders in it for locking.

Is this supposed to explain ...

> @@ -51,17 +51,16 @@ test_expect_success 'clone remote repository' '
>  	git clone $HTTPD_URL/test_repo.git test_repo_clone
>  '
> 
> -test_expect_failure 'push to remote repository' '
> +test_expect_success 'push to remote repository' '
>  	cd "$ROOT_PATH"/test_repo_clone &&
>  	: >path2 &&
>  	git add path2 &&
>  	test_tick &&
>  	git commit -m path2 &&
> -	git push &&
> -	[ -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/refs/heads/master" ]
> +	git push origin master
>  '

... this removal?  I do not think this is a good change, as it removes 
a test that is actually pretty important.

BTW I do not understand at all what you mean by "we need to chmod".  Does 
the Apache instance not run with the current user's permissions?

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH/RFC v3 1/6] reflog: refactor parsing and checking
From: Johannes Schindelin @ 2009-01-17  5:35 UTC (permalink / raw)
  To: Thomas Rast; +Cc: git, Junio C Hamano, Johannes Sixt, Johan Herland
In-Reply-To: <1232163011-20088-2-git-send-email-trast@student.ethz.ch>

Hi,

On Sat, 17 Jan 2009, Thomas Rast wrote:

> Note that this switches for_each_reflog_ent() from silently ignoring 
> errors to die().

I am not convinced this is necessary, and neither that it is good.

You could return int from parse_reflog_line() just like the other 
non-dying functions.

And keep in mind that reflogs could be corrupted for all kinds of reasons; 
with your patch, reflog handling would fail gracelessly, even if a 
lot could still be salvaged (by ignoring the error with a warning).

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH/RFC v3 2/6] reflog: refactor log open+mmap
From: Johannes Schindelin @ 2009-01-17  5:40 UTC (permalink / raw)
  To: Thomas Rast; +Cc: git, Junio C Hamano, Johannes Sixt, Johan Herland
In-Reply-To: <1232163011-20088-3-git-send-email-trast@student.ethz.ch>

Hi,

On Sat, 17 Jan 2009, Thomas Rast wrote:

> +static char *open_reflog(const char *ref, size_t *mapsz, const char **logfile)
> +{
> +	struct stat st;
> +	int logfd;
> +	char *map;
> +
> +	*logfile = git_path("logs/%s", ref);

That is dangerous.  git_path() returns a pointer to a static buffer.  
Before your patch, logfile was a local variable, and one could be 
relatively sure that git_path() was not called during the lifetime.  Now 
the lifetime of logfile is no longer as clear-cut, and it is much easier 
to overlook that git_path() must not be called while logfile holds a 
reference to its static buffer.

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH/RFC v3 0/6] N-th last checked out branch
From: Johannes Schindelin @ 2009-01-17  5:52 UTC (permalink / raw)
  To: Thomas Rast; +Cc: git, Junio C Hamano, Johannes Sixt, Johan Herland
In-Reply-To: <1232163011-20088-1-git-send-email-trast@student.ethz.ch>

Hi,

On Sat, 17 Jan 2009, Thomas Rast wrote:

>  Documentation/git-checkout.txt  |    4 +
>  Documentation/git-rev-parse.txt |    3 +
>  builtin-checkout.c              |   15 ++-
>  cache.h                         |    1 +
>  refs.c                          |  285 +++++++++++++++++++++++----------------
>  refs.h                          |    1 +
>  sha1_name.c                     |   79 +++++++++++-
>  t/t1505-rev-parse-last.sh       |   71 ++++++++++
>  t/t2012-checkout-last.sh        |   50 +++++++
>  9 files changed, 387 insertions(+), 122 deletions(-)
>  create mode 100755 t/t1505-rev-parse-last.sh
>  create mode 100755 t/t2012-checkout-last.sh

Let's quickly compare that to what Junio sent:

 builtin-checkout.c |   10 +++++-
 cache.h            |    1 +
 sha1_name.c        |   78 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 87 insertions(+), 2 deletions(-)

Granted, the documentation and tests are nice, but why that big change in 
refs.c?  After all, the more you change in one go, the more you can break.

Let's take one step back.  The two things that Junio's patch left to be 
desired (in addition to documentation and tests) are

- reflogs are traversed twice.  While this is not a showstopper, it is 
  easily improved by building a string_list and then picking the one entry 
  we're interested in, and

- the '-' handling you seem to want.

I really have to ask: why did you not work on top of Junio's patch, just 
adding docs, tests, and checkout -?  And then -- maybe -- the 
string_list...

Although I have to admit that I am not _that_ convinced the string_list is 
worth it: reflogs are not evaluated all the time, so it is definitely not 
performance critical.

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH 1/3] http-push: append slash if possible for directories
From: Johannes Schindelin @ 2009-01-17  6:02 UTC (permalink / raw)
  To: Ray Chuan; +Cc: git
In-Reply-To: <be6fef0d0901161853y6784310dgf94dadb2218001a1@mail.gmail.com>

Hi,

more comments:

On Sat, 17 Jan 2009, Ray Chuan wrote:

> diff --git a/src/git-1.6.1/http-push.c b/src/git-1.6.1/http-push.c
> index 7c64609..25b655d 100644
> --- a/src/git-1.6.1/http-push.c
> +++ b/src/git-1.6.1/http-push.c
> @@ -1189,6 +1189,7 @@ static struct remote_lock *lock_remote(const
> char *path, long timeout)
>  	struct strbuf in_buffer = STRBUF_INIT;
>  	char *url;
>  	char *ep;
> +	char ep_old;
>  	char timeout_header[25];
>  	struct remote_lock *lock = NULL;
>  	struct curl_slist *dav_headers = NULL;
> @@ -1198,9 +1199,18 @@ static struct remote_lock *lock_remote(const
> char *path, long timeout)
>  	sprintf(url, "%s%s", remote->url, path);
> 
>  	/* Make sure leading directories exist for the remote ref */
> -	ep = strchr(url + strlen(remote->url) + 1, '/');
> -	while (ep) {
> -		*ep = 0;
> +	ep = url + strlen(remote->url) + 1;
> +	int has_fs = 0;

decl-after-statement.

And name-not-meaningful.  What does "has_fs" stand for?

> +	while (1) {
> +		ep = strchr(ep + 1, '/');
> +		if(ep) {
> +			ep++;
> +			ep_old=*ep;

Okay, you succeeded in fooling me.  It took fully five minutes until I 
realized that ep_old is not the old value of ep, but of *ep.

And now I know what has_fs does, but the name is an even bigger puzzle.

Almost as big as the puzzle why you did not do a much less intrusive 
change:

- after the "while (ep) {" you could say "char saved_character = ep[1];

- then you replace the "*ep = 0" by "ep[1] = '\0';"

- at the end of the loop, you replace the "*ep = '/'" with "ep[1] = 
  saved_character;"

That way, not only would the patch be much smaller, it would also not have 
been as difficult to review as it was.

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH 2/3] http-push: when sending objects, don't PUT before MOVE
From: Johannes Schindelin @ 2009-01-17  6:13 UTC (permalink / raw)
  To: Ray Chuan; +Cc: git
In-Reply-To: <be6fef0d0901161859g4e5d749et78b6b0231eb915ee@mail.gmail.com>

Hi,

On Sat, 17 Jan 2009, Ray Chuan wrote:

> since 753bc911f489748a837ecb5ea4b5216220b24845, the opaquelocktocken

It would be nice to use the form <abbrev-sha1>(<oneline>) instead of a 
non-abbreviated SHA-1 that everybody who is interested has to look up, 
wasting time.

> URI isn't used, so it doesn't make sense to PUT then MOVE.
> 
> currently, git PUTs to
> 
> /repo.git/objects/1a/1a2b..._opaquelocktoken:1234-....

First you say that the opaquelocktoken URI is not used, but here it looks 
like one?

> on some platforms, ':' isn't allowed in filenames so this fails
> (assuming the server doesn't recognize it as opaquelocktoken scheme).
> in fact, i don't think this is the correct implementation of the
> scheme; 'opaquelocktoken: ' should come in front of the path.

It would be nice to make that a fact-backed commit message.  IOW there has 
to be some documentation about the subject which you can quote, and which 
would give you a definitive answer to the question if it should be a 
prefix or not.

> diff --git a/src/git-1.6.1/http-push.c b/src/git-1.6.1/http-push.c
> index a646a49..838ff6f 100644
> --- a/src/git-1.6.1/http-push.c
> +++ b/src/git-1.6.1/http-push.c
> @@ -31,7 +31,6 @@ enum XML_Status {
>  /* DAV methods */
>  #define DAV_LOCK "LOCK"
>  #define DAV_MKCOL "MKCOL"
> -#define DAV_MOVE "MOVE"
>  #define DAV_PROPFIND "PROPFIND"
>  #define DAV_PUT "PUT"
>  #define DAV_UNLOCK "UNLOCK"
> @@ -104,7 +103,6 @@ enum transfer_state {
>  	NEED_PUSH,
>  	RUN_MKCOL,
>  	RUN_PUT,
> -	RUN_MOVE,
>  	ABORTED,
>  	COMPLETE,
>  };
> @@ -528,11 +526,6 @@ static void start_put(struct transfer_request *request)
>  	posn += 2;
>  	*(posn++) = '/';
>  	strcpy(posn, hex + 2);
> -	request->dest = xmalloc(strlen(request->url) + 14);
> -	sprintf(request->dest, "Destination: %s", request->url);
> -	posn += 38;
> -	*(posn++) = '_';
> -	strcpy(posn, request->lock->token);
> 
>  	slot = get_active_slot();
>  	slot->callback_func = process_response;

Color me puzzled again.  Why is this code no longer needed?  Is this the 
lock you were talking about?

> @@ -705,23 +672,13 @@ static void finish_request(struct
> transfer_request *request)
>  		}
>  	} else if (request->state == RUN_PUT) {
>  		if (request->curl_result == CURLE_OK) {
> -			start_move(request);
> -		} else {
> -			fprintf(stderr,	"PUT %s failed, aborting (%d/%ld)\n",
> -				sha1_to_hex(request->obj->sha1),
> -				request->curl_result, request->http_code);
> -			request->state = ABORTED;
> -			aborted = 1;
> -		}

... and here comes my first doubt that it would be a good idea to avoid 
"put && move"; what if "put" fails?  Then you end up with a corrupt 
repository.

Ciao,
Dscho

^ permalink raw reply

* [Announce] teamgit v0.0.9 - visual interactive rebase
From: Abhijit Bhopatkar @ 2009-01-17  7:38 UTC (permalink / raw)
  To: git

Hi people,

teamGit is a functional git gui written in qt, its ultimate aim is to
add functionality on top of git targeted at small closely knit teams.

I have tagged the repo with v0.0.9!!!
You can now get the .deb from ubuntu intrepid ppa
deb http://ppa.launchpad.net/bain-devslashzero/ubuntu intrepid main
package name is teamgit.
The main project website is http://www.devslashzero.com/teamgit

The major changes from v0.0.8 include
1. Added preliminary interactive rebase support, now edit reabse queue
visually
2. Advanced menu is now disabled, since its still long way from being
stable
3. You can now drag and drop emailed patches straight from evoluion (may
be others as well) or drop patch files/mboxes from nautilus.

Shortlog since v0.0.8 appended
Abhijit
---

Abhijit Bhopatkar (23):
      guifydialogui: Fixed a groupbox title
      Added a rebase ui binary
      gitprocess: make rebase editor a variable and unset it after
rebase
      mainwindowui: Added interactive rebase action to tools
      gitprocess: make rebase take an argument for rebase point
      mainwindowimpl: don't crash if git binary is not found
      Added rebase interactive functionality
      rabse-interactive: Added rebase control file reading
      Made teamgit a global project for main and rebase projects
      Added install target for rebase-interactive
      Added teamgit-rebase and editor for teamgit control file
      Removed stray merge conflict file
      Added suporject for main teamgit app
      Added basic merge command support
      mainwindowimpl.cpp: Use save/restoreGeometry function for window
state.
      White space cleanup
      Drag and drop patch support
      mainwindowsimpl.cpp: fix stupid commenting
      Build advanced menu only if settings is true
Abhijit Bhopatkar (23):
      guifydialogui: Fixed a groupbox title
      Added a rebase ui binary
      gitprocess: make rebase editor a variable and unset it after
rebase
      mainwindowui: Added interactive rebase action to tools
      gitprocess: make rebase take an argument for rebase point
      mainwindowimpl: don't crash if git binary is not found
      Added rebase interactive functionality
      rabse-interactive: Added rebase control file reading
      Made teamgit a global project for main and rebase projects
      Added install target for rebase-interactive
      Added teamgit-rebase and editor for teamgit control file
      Removed stray merge conflict file
      Added suporject for main teamgit app
      Added basic merge command support
      mainwindowimpl.cpp: Use save/restoreGeometry function for window
state.
      White space cleanup
      Drag and drop patch support
      mainwindowsimpl.cpp: fix stupid commenting
      Build advanced menu only if settings is true
      settings.ui:Add showAdvanced checkbox
      Enable advanced menu only on selecting it from options
      settings.ui: Add a warning label in advanced about unstability
      v0.0.9 hurra!!!

Markus Bröker (13):
      src/gitprocess.cpp: unicode aware encoding
      src/gitprocess.cpp: White space corrections
      utf8 aware encoding - part 2
      Check, whether valid data is parseable or not
      Unicode aware diffing
      Remove trailing spaces during package build
      Interactive Rebase
      Rebase: Sorting Order
      QtextEdit replaces the moving puzzle
      Rebase: UTF-8 Writer
      Rebase: edit and drop buttons added
      Rebase: Write Access when writing
      c++ std header

Rajesh Sola (1):
      gitporcess:Added git rebase interactive

^ permalink raw reply

* Re: [PATCH resend] bash completion: add 'rename' subcommand to git-remote
From: Junio C Hamano @ 2009-01-17  8:03 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Markus Heidelberg, git
In-Reply-To: <20090116221203.GP10179@spearce.org>

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

> Markus Heidelberg <markus.heidelberg@web.de> wrote:
>> 
>> Signed-off-by: Markus Heidelberg <markus.heidelberg@web.de>
>
> Acked-by: Shawn O. Pearce <spearce@spearce.org>
>
>> 	I've just accidently read in the completion file itself, that
>> 	Shawn is the maintainer, so I give it a third try. The first two
>> 	haven't been sent to him.
>
> Sorry, I must have missed the other two attempts.  :-)

And I seem to have missed all three.

>
>  
>>  contrib/completion/git-completion.bash |    4 ++--
>>  1 files changed, 2 insertions(+), 2 deletions(-)
>> 
>> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
>> index 049ded0..6623344 100755
>> --- a/contrib/completion/git-completion.bash
>> +++ b/contrib/completion/git-completion.bash
>> @@ -1384,7 +1384,7 @@ _git_config ()
>>  
>>  _git_remote ()
>>  {
>> -	local subcommands="add rm show prune update"
>> +	local subcommands="add rename rm show prune update"
>>  	local subcommand="$(__git_find_subcommand "$subcommands")"
>>  	if [ -z "$subcommand" ]; then
>>  		__gitcomp "$subcommands"
>> @@ -1392,7 +1392,7 @@ _git_remote ()
>>  	fi
>>  
>>  	case "$subcommand" in
>> -	rm|show|prune)
>> +	rename|rm|show|prune)
>>  		__gitcomp "$(__git_remotes)"
>>  		;;
>>  	update)
>> -- 
>> 1.6.1.35.g0c23
>> 
>
> -- 
> Shawn.
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 1/3] http-push: append slash if possible for directories
From: Ray Chuan @ 2009-01-17  8:28 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <alpine.DEB.1.00.0901170654540.3586@pacific.mpi-cbg.de>

let me rewrite the patch:
----------------------------------------------------
the lock_remote currently sends MKCOL requests to leading directories
to make sure they exist; however, it doesn't put a forward slash '/'
behind the path, so if the path is a directory, the server sends a 301
redirect.

by appending a '/' we can save the server this additional step.

in addition, it seems that curl doesn't re-send the authentication
credentials when it follows a 301 redirect, so skipping (unnecessary)
redirects can also be seen as a workaround for this issue. (i'm using
7.16.3)

Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
---
 http-push.c |   20 +++++++++++++++-----
 1 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/http-push.c b/http-push.c
index 7c64609..9218c7a 100644
--- a/http-push.c
+++ b/http-push.c
@@ -1187,8 +1187,10 @@ static struct remote_lock *lock_remote(const
char *path, long timeout)
 	struct slot_results results;
 	struct buffer out_buffer = { STRBUF_INIT, 0 };
 	struct strbuf in_buffer = STRBUF_INIT;
+	int has_forwardslash = 0;
 	char *url;
 	char *ep;
+	char saved_character;
 	char timeout_header[25];
 	struct remote_lock *lock = NULL;
 	struct curl_slist *dav_headers = NULL;
@@ -1198,9 +1200,16 @@ static struct remote_lock *lock_remote(const
char *path, long timeout)
 	sprintf(url, "%s%s", remote->url, path);

 	/* Make sure leading directories exist for the remote ref */
-	ep = strchr(url + strlen(remote->url) + 1, '/');
-	while (ep) {
-		*ep = 0;
+	ep = url + strlen(remote->url) + 1;
+	while (1) {
+		ep = strchr(ep + 1, '/');
+		if(ep) {
+			saved_character=ep[1];
+			ep[1]=0;
+			has_forwardslash = 1;
+		} else {
+			break;
+		}
 		slot = get_active_slot();
 		slot->results = &results;
 		curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
@@ -1222,8 +1231,9 @@ static struct remote_lock *lock_remote(const
char *path, long timeout)
 			free(url);
 			return NULL;
 		}
-		*ep = '/';
-		ep = strchr(ep + 1, '/');
+		if(has_forwardslash) {
+			ep[1] = saved_character;
+		}
 	}

 	strbuf_addf(&out_buffer.buf, LOCK_REQUEST, git_default_email);
-- 
1.6.0.4

^ permalink raw reply related

* Re: [PATCH 3/3] http-push: update tests
From: Ray Chuan @ 2009-01-17  8:40 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <alpine.DEB.1.00.0901170621440.3586@pacific.mpi-cbg.de>

Hi,

On Sat, Jan 17, 2009 at 1:23 PM, Johannes Schindelin
<Johannes.Schindelin@gmx.de> wrote:
> Hi,
>
> On Sat, 17 Jan 2009, Ray Chuan wrote:
>
>> note: the test needs to chmod the test_repo.git folder so that
>> apache/mod_dav can create .DAV folders in it for locking.
>
> Is this supposed to explain ...
>
>> @@ -51,17 +51,16 @@ test_expect_success 'clone remote repository' '
>>       git clone $HTTPD_URL/test_repo.git test_repo_clone
>>  '
>>
>> -test_expect_failure 'push to remote repository' '
>> +test_expect_success 'push to remote repository' '
>>       cd "$ROOT_PATH"/test_repo_clone &&
>>       : >path2 &&
>>       git add path2 &&
>>       test_tick &&
>>       git commit -m path2 &&
>> -     git push &&
>> -     [ -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/refs/heads/master" ]
>> +     git push origin master
>>  '
>
> ... this removal?  I do not think this is a good change, as it removes
> a test that is actually pretty important.

i'm sorry for the poor commit message, what i wanted to do was to
change the tests to expect success rather than failure. no tests were
removed; only their expected outcomes were modified. currently, the
pushes fail, so the test 'fails as expected'; now the pushes succeed,
so they shouldn't be expecting failed pushes (or anything else).

> BTW I do not understand at all what you mean by "we need to chmod".  Does
> the Apache instance not run with the current user's permissions?

i wrote 'we need to chmod', cos i'm not sure what the permissions are
required. sorry, i didn't notice that apache was running with the
current user's permissions. but i added the note just in case, for
users who don't run apache with the current user, so they modify the
test appropriately (ie adding a chmod).

> Ciao,
> Dscho
>



-- 
Cheers,
Ray Chuan

^ permalink raw reply

* Re: git-svn fails to fetch repository
From: Eric Wong @ 2009-01-17  9:51 UTC (permalink / raw)
  To: Vladimir Pouzanov; +Cc: git, Jay Soffian
In-Reply-To: <76718490901141006n6c70eb2cw67ad814b3739786e@mail.gmail.com>

Jay Soffian <jaysoffian@gmail.com> wrote:
> On Wed, Jan 14, 2009 at 3:32 AM, Vladimir Pouzanov <farcaller@gmail.com> wrote:
> > Jay Soffian <jaysoffian <at> gmail.com> writes:
> >> So you're adding the "use Carp..." and "warn..." lines.
> >>
> >> Then try the import again. That should at least show why the svn_delta
> >> temp file is being acquired twice.
> >
> > Output is pretty long so I've put in on pastebin:
> > http://pastebin.com/m210be905
> 
> Okay, this is beyond me. git-svn (among other things) implements a
> so-called delta editor (part of the subversion API). The driver for
> that editor is apparently calling the editor's apply_textdelta()
> method twice in a row w/o an intervening call to the editor's
> close_file() method.
> 
> I don't understand when and/or why it would do this. This part of the
> Subversion API seems not that well documented, and I got lost trying
> to follow all the indirections in the Subversion source code (esp
> w/the swig'ified Perl bindings). AFAICT, this should not be happening.

Thank you Jay for your help and patch so far.  I'm sorry you had to go
through the craziness that is the Subversion library (and associated
craziness that leaked into git-svn) to try an debug this problem.

> I could ask you to insert some more debugging statements to try to
> track it to a specific file (or files), but I think at this point I'll
> going to wait to see if the git-svn author has any ideas.

Putting "print" and "print Dumper(\@_)" everywhere is pretty much
how I figured out how to use the delta interface the first time around.

Vladimir:

I can't reproduce this problem at all, either.  git-svn dups the file
handle in question, maybe your combination of (SVN/Perl/OSX) somehow
handles dup'd file descriptors differently?

Does the following patch (a shot in the dark) work for you?
(it generates a lot of warnings for me)

diff --git a/git-svn.perl b/git-svn.perl
index ad01e18..23e6925 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -3361,6 +3361,7 @@ sub apply_textdelta {
 	seek $base, 0, 0 or croak $!;
 	$fb->{fh} = $fh;
 	$fb->{base} = $base;
+	$fb->{dup} = $dup;
 	[ SVN::TxDelta::apply($base, $dup, undef, $fb->{path}, $fb->{pool}) ];
 }
 
@@ -3408,6 +3409,7 @@ sub close_file {
 
 		Git::temp_release($fb->{base}, 1);
 		Git::temp_release($fh, 1);
+		eval { Git::temp_release($fb->{dup}, 1) };
 	} else {
 		$hash = $fb->{blob} or die "no blob information\n";
 	}

> BTW, it doesn't help any that the order that files are checked out
> seems not to be consistent. Not only is my git-svn clone working, the
> order my files are checked out in is different from yours.
> 
> Oh, one other thing I don't understand is why the debugging output is
> now showing that some files are being added for you (the lines
> beginning with \tA). Before you weren't getting that. I had thought
> these lines might be getting lost in stdout buffering, but git-svn
> disables buffering on stdout, so color me confused.

With that comment and my attempted fix above, I'm almost under the
impression that something on Vladimir's system (or Perl) is
configured to handle I/O in some weird/broken way...

-- 
Eric Wong

^ permalink raw reply related

* Re: git-svn fails to fetch repository
From: Vladimir Pouzanov @ 2009-01-17 10:06 UTC (permalink / raw)
  To: Eric Wong; +Cc: git, Jay Soffian
In-Reply-To: <20090117095147.GA29598@dcvr.yhbt.net>


On 17 янв. 2009, at 11:51, Eric Wong wrote:
> Does the following patch (a shot in the dark) work for you?
> (it generates a lot of warnings for me)

$ git svn clone http://qsb-mac.googlecode.com/svn/trunk qsbmac
Initialized empty Git repository in /Users/farcaller/temp/qsbmac/.git/
r1 = 810fe584c48b884460b5403a28bc61d872452b93 (git-svn)
Attempt to release temp file 'GLOB(0x82b290)' that has not been locked  
at /opt/local/libexec/git-core/git-svn line 3413
	A	externals/BSJSONAdditions/NSArray+BSJSONAdditions.m
Attempt to release temp file 'GLOB(0xa0de34)' that has not been locked  
at /opt/local/libexec/git-core/git-svn line 3413
	A	externals/BSJSONAdditions/BSJSON.h
Attempt to release temp file 'GLOB(0x80ed84)' that has not been locked  
at /opt/local/libexec/git-core/git-svn line 3413
	A	externals/BSJSONAdditions/NSDictionary+BSJSONAdditions.m
Attempt to release temp file 'GLOB(0x9d3018)' that has not been locked  
at /opt/local/libexec/git-core/git-svn line 3413
	A	externals/BSJSONAdditions/Example/Unit Tests/ 
BSJSONScanner_UnitTests.h
Attempt to release temp file 'GLOB(0xa0df48)' that has not been locked  
at /opt/local/libexec/git-core/git-svn line 3413
	A	externals/BSJSONAdditions/Example/version.plist
Attempt to release temp file 'GLOB(0x9d8114)' that has not been locked  
at /opt/local/libexec/git-core/git-svn line 3413
	A	externals/BSJSONAdditions/NSDictionary+BSJSONAdditions.h
Temp file with moniker 'svn_delta' already in use at /opt/local/lib/ 
perl5/site_perl/5.8.8/Git.pm line 1011.

I've built git 1.6.1 based on OSX original perl an subversion, and it  
handles the give repo without any problems, so the problem is kind of  
solved. Strange thing is that macports git (the one that fails)  
handles other svn repositories without any problems, I had cloned  
whole transmissionbt repo (>7000 revs) with all the tags and branches  
and several other simpler repositories.

-- 
Sincerely,
Vladimir "Farcaller" Pouzanov

^ permalink raw reply

* Re: [PATCH/RFC] git-svn: Add --convert-timezone option
From: Eric Wong @ 2009-01-17 10:37 UTC (permalink / raw)
  To: Pete Harlan; +Cc: Git mailing list
In-Reply-To: <496D35B8.70203@pcharlan.com>

Pete Harlan <pgit@pcharlan.com> wrote:
> By default git svn stores timestamps of fetched commits in
> Subversion's UTC format, to facilitate interoperating with a
> Subversion repository.
> 
> If you're using git svn to convert a repository to Git and aren't
> interested in pushing Git commits back to Subversion, you can use this
> option to store timestamps of fetched commits as though they were made
> in the local timezone of the host on which git svn is run.  This makes
> the times and timezones of a resulting "git log" agree with what "svn
> log" shows for the same repository.
> 
> Signed-off-by: Pete Harlan <pgit@pcharlan.com>
> ---
> 
> This is a patch I've had floating around for a while.  I haven't
> submitted it before because I find the solution ungainly.  There has
> to be a better way to convert from one timezone to the other, but I
> didn't run across it and now that I've converted away from Subversion
> I'm sort of done thinking about it.  I'm submitting it now because
> even in its current state it would have saved me some headache.
> 
> Also, I'm not sure I'm correct when asserting that converting
> timezones like this will break Subversion interoperability.  Eric, if
> that isn't true then I can remove that claim and resubmit.  If
> converting timezones breaks nothing, then maybe it could even be the
> default.

Hi,

It'll break interoperability between multiple users of git-svn
tracking the same repo.  But several options already allow for
this (authors file, noMetdata, ...), so I'm fine with it as long
as it's optional.

> One improvement that I didn't bother to make would be to convert to
> different local timezones based on author.  This change uses the
> timezone of the machine running git-svn, which in my case was fine.
> Using per-author timezones would be nice, but since parse_svn_date()
> doesn't already know which author the date is associated with it would
> be a more intrusive change.

Could be an interesting idea, but on the other hand I doubt many people
would bother configuring the authors-file for it.

On a side note, for the total conversions I've done, I've found it
easier/faster/more bandwidth efficient to just forgo authors-file
entirely and use git-filter-branch after-the-fact.

> My primary motivation in this was to reduce transition shock among our
> development team.  The fewer ways "git log" looks unhelpfully
> different than the old "svn log" the better; converting all commit
> times into GMT wasn't going to look friendly.
> 
> Comments welcome.

My usual coding style nits apply (pretty much git (and Linux kernel)
standard coding style things, too).

No space between "function(arguments)".

lower_snake_case, especially for local variables.  mixedCase requires
more effort to read IMO.

More comments inline...

> --Pete
> 
>  Documentation/git-svn.txt              |    8 ++++
>  contrib/completion/git-completion.bash |    2 +-
>  git-svn.perl                           |   56 ++++++++++++++++++++++++++++++-
>  3 files changed, 63 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
> index 8d0c421..8811bf0 100644
> --- a/Documentation/git-svn.txt
> +++ b/Documentation/git-svn.txt
> @@ -92,6 +92,14 @@ COMMANDS
>  	.git/config file may be specified as an optional command-line
>  	argument.
> 
> +--convert-timezones;;

Is it "timezone" or "timezones" here?  I think "convert-timezone" is
more correct since we only use the local timezone, not different
ones for each author.  On the other hand, maybe "--localtime" is
an even better name for this option...

Any other opinions out there?

> +	Store Git commit times in the local timezone instead of UTC.  This
> +	makes 'git-log' (even without --date=local) show the same times
> +	that `svn log` would in the local timezone.
> +
> +This breaks interoperability with SVN, but may be cosmetically
> +desirable when converting a repository from SVN to Git.

Again, this only breaks interoperability with other users of git-svn
using the default configuration on the same repo.

>  'clone'::
>  	Runs 'init' and 'fetch'.  It will automatically create a
>  	directory based on the basename of the URL passed to it;
> diff --git a/git-svn.perl b/git-svn.perl
> index ad01e18..c2f600d 100755
> --- a/git-svn.perl
> +++ b/git-svn.perl
> @@ -66,7 +66,7 @@ my ($_stdin, $_help, $_edit,
>  	$_version, $_fetch_all, $_no_rebase,
>  	$_merge, $_strategy, $_dry_run, $_local,
>  	$_prefix, $_no_checkout, $_url, $_verbose,
> -	$_git_format, $_commit_url, $_tag);
> +	$_git_format, $_commit_url, $_tag, $_convert_timezones);

Not easy to tell (and apologies for that) but this new variable probably
belongs in the Git::SVN namespace.  I really need to find some time to
reorganize and split out the source to git-svn.

>  $Git::SVN::_follow_parent = 1;
>  my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
>                      'config-dir=s' => \$Git::SVN::Ra::config_dir,
> @@ -84,6 +84,7 @@ my %fc_opts = ( 'follow-parent|follow!' => \$Git::SVN::_follow_parent,
>  		   \$Git::SVN::_repack_flags,
>  		'use-log-author' => \$Git::SVN::_use_log_author,
>  		'add-author-from' => \$Git::SVN::_add_author_from,
> +		'convert-timezones' => \$_convert_timezones,
>  		%remote_opts );
> 
>  my ($_trunk, $_tags, $_branches, $_stdlayout);
> @@ -2526,12 +2527,63 @@ sub get_untracked {
>  	\@out;
>  }
> 
> +# parse_svn_date(DATE)
> +# --------------------
> +# Given a date (in UTC) from Subversion, return a string in the format
> +# "<TZ Offset> <local date/time>" that Git will use.
> +#
> +# By default the parsed date will be in UTC for interoperating with
> +# Subversion, but if $_convert_timezones is true we'll convert it to
> +# the local timezone instead.
>  sub parse_svn_date {
>  	my $date = shift || return '+0000 1970-01-01 00:00:00';
>  	my ($Y,$m,$d,$H,$M,$S) = ($date =~ /^(\d{4})\-(\d\d)\-(\d\d)T
>  	                                    (\d\d)\:(\d\d)\:(\d\d).\d+Z$/x) or
>  	                                 croak "Unable to parse date: $date\n";
> -	"+0000 $Y-$m-$d $H:$M:$S";
> +	my $parsed_date;    # Set next.
> +
> +	if ($_convert_timezones) {
> +		# Translate the Subversion datetime to an epoch time.
> +		# We need to switch ourselves to $date's timezone,
> +		# UTC, for this.
> +		my $oldEnvTZ = $ENV{TZ};
> +		$ENV{TZ} = 'UTC';
> +
> +		my $epochUTC =
> +		    POSIX::strftime ('%s', $S, $M, $H, $d, $m - 1, $Y - 1900);
> +
> +		# Determine our local timezone (including DST) at the
> +		# time of $epochUTC.  $Git::SVN::Log::TZ stored the
> +		# value of TZ, if any, at the time we were run.
> +		if (defined $Git::SVN::Log::TZ) {
> +			$ENV{TZ} = $Git::SVN::Log::TZ;
> +		} else {
> +			delete $ENV{TZ};
> +		}
> +
> +		my $ourTZ =
> +		    POSIX::strftime ('%Z', $S, $M, $H, $d, $m - 1, $Y - 1900);
> +
> +		# This converts $epochUTC into our local timezone.
> +		my ($sec, $min, $hour, $mday, $mon, $year,
> +		    $wday, $yday, $isdst) = localtime ($epochUTC);
> +
> +		$parsed_date = sprintf ('%s %04d-%02d-%02d %02d:%02d:%02d',
> +					$ourTZ, $year + 1900, $mon + 1,
> +					$mday, $hour, $min, $sec);

There's probably a reason you didn't use strftime here, or is there?
The stock Perl time/date handling functions have always frightened me,
so I'll just trust the (+|-) (1|1900) things are correct :)

-- 
Eric Wong

^ permalink raw reply

* Re: git-svn fails to fetch repository
From: Eric Wong @ 2009-01-17 10:45 UTC (permalink / raw)
  To: Vladimir Pouzanov; +Cc: git, Jay Soffian
In-Reply-To: <E3BA9CAD-B3CD-4050-8493-7C4024AD4529@gmail.com>

Vladimir Pouzanov <farcaller@gmail.com> wrote:
> On 17 янв. 2009, at 11:51, Eric Wong wrote:
>> Does the following patch (a shot in the dark) work for you?
>> (it generates a lot of warnings for me)
>
> $ git svn clone http://qsb-mac.googlecode.com/svn/trunk qsbmac
> Initialized empty Git repository in /Users/farcaller/temp/qsbmac/.git/
> r1 = 810fe584c48b884460b5403a28bc61d872452b93 (git-svn)
> Attempt to release temp file 'GLOB(0x82b290)' that has not been locked  
> at /opt/local/libexec/git-core/git-svn line 3413
> 	A	externals/BSJSONAdditions/NSArray+BSJSONAdditions.m
> Attempt to release temp file 'GLOB(0xa0de34)' that has not been locked  
> at /opt/local/libexec/git-core/git-svn line 3413
> 	A	externals/BSJSONAdditions/BSJSON.h
> Attempt to release temp file 'GLOB(0x80ed84)' that has not been locked  
> at /opt/local/libexec/git-core/git-svn line 3413
> 	A	externals/BSJSONAdditions/NSDictionary+BSJSONAdditions.m
> Attempt to release temp file 'GLOB(0x9d3018)' that has not been locked  
> at /opt/local/libexec/git-core/git-svn line 3413
> 	A	externals/BSJSONAdditions/Example/Unit Tests/ 
> BSJSONScanner_UnitTests.h
> Attempt to release temp file 'GLOB(0xa0df48)' that has not been locked  
> at /opt/local/libexec/git-core/git-svn line 3413
> 	A	externals/BSJSONAdditions/Example/version.plist
> Attempt to release temp file 'GLOB(0x9d8114)' that has not been locked  
> at /opt/local/libexec/git-core/git-svn line 3413
> 	A	externals/BSJSONAdditions/NSDictionary+BSJSONAdditions.h
> Temp file with moniker 'svn_delta' already in use at /opt/local/lib/ 
> perl5/site_perl/5.8.8/Git.pm line 1011.

OK, and there are no symlinks in the repository which could trigger a
rare code path, either.  Very strange, does abort_edit() ever get called
in there?

> I've built git 1.6.1 based on OSX original perl an subversion, and it  
> handles the give repo without any problems, so the problem is kind of  
> solved. Strange thing is that macports git (the one that fails) handles 
> other svn repositories without any problems, I had cloned whole 
> transmissionbt repo (>7000 revs) with all the tags and branches and 
> several other simpler repositories.

At least you got a working combination working.  Does anybody know if
macports git have any patches/changes to it that could cause this?

-- 
Eric Wong

^ permalink raw reply

* Re: [PATCH] git svn clone -s was not prefixing 'branches/'
From: Eric Wong @ 2009-01-17 10:54 UTC (permalink / raw)
  To: Jonathan Lim; +Cc: git
In-Reply-To: <1232050647-2870-1-git-send-email-snowblink@gmail.com>

Jonathan Lim <snowblink@gmail.com> wrote:
> All branches in the subversion repository would appear at the same
> level as trunk.  The should now appear with a 'branches/' prefix.
> 
> Signed-off-by: Jonathan Lim <snowblink@gmail.com>

This is too ugly for the common existing cases.  For the rare case where
this could lead to a namespace conflict[1], it's possible to work around
it by editing .git/config.

I would accept a --tags-prefix= and --branches-prefix= patch to make
this possible w/o having to edit .git/config, but I don't want the
default prefixes changed.

Thanks,

[1] - "/branches/trunk" vs "/trunk", which I've yet to see evidence of...

> ---
>  git-svn.perl |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/git-svn.perl b/git-svn.perl
> index ad01e18..17d65cb 100755
> --- a/git-svn.perl
> +++ b/git-svn.perl
> @@ -789,7 +789,7 @@ sub cmd_multi_init {
>  	}
>  	return unless defined $_branches || defined $_tags;
>  	my $ra = $url ? Git::SVN::Ra->new($url) : undef;
> -	complete_url_ls_init($ra, $_branches, '--branches/-b', $_prefix);
> +	complete_url_ls_init($ra, $_branches, '--branches/-b', $_prefix . 'branches/');
>  	complete_url_ls_init($ra, $_tags, '--tags/-t', $_prefix . 'tags/');
>  }

^ permalink raw reply


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