* 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 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 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 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: 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: 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
* [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, ×tamp, &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
* [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, ×tamp, &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 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 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 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, ×tamp, &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 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 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 v2 5/5] run_hook(): allow more than 9 hook arguments
From: Stephan Beyer @ 2009-01-17 3:02 UTC (permalink / raw)
To: git
Cc: Johannes Schindelin, Paolo Bonzini, Miklos Vajna, Shawn O. Pearce,
Daniel Barkalow, Christian Couder, gitster, Stephan Beyer
In-Reply-To: <1232133002-21725-4-git-send-email-s-beyer@gmx.net>
This is done using the ALLOC_GROW macro.
Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
---
Ok, Dscho :-)
The interdiff based on [PATCH 5/5] is...
--- a/run-command.c
+++ b/run-command.c
@@ -350,14 +350,14 @@ int run_hook(const char *index_file, const char *name, ...)
char index[PATH_MAX];
va_list args;
int ret;
- size_t i = 1, alloc = 5;
+ size_t i = 0, alloc = 0;
if (access(git_path("hooks/%s", name), X_OK) < 0)
return 0;
va_start(args, name);
- argv = xmalloc(alloc * sizeof(const char *));
- argv[0] = git_path("hooks/%s", name);
+ ALLOC_GROW(argv, i + 1, alloc);
+ argv[i++] = git_path("hooks/%s", name);
while (argv[i-1]) {
ALLOC_GROW(argv, i + 1, alloc);
argv[i++] = va_arg(args, const char *);
Documentation/technical/api-run-command.txt | 2 +-
run-command.c | 18 +++++++++---------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/Documentation/technical/api-run-command.txt b/Documentation/technical/api-run-command.txt
index 13e7b63..2efe7a4 100644
--- a/Documentation/technical/api-run-command.txt
+++ b/Documentation/technical/api-run-command.txt
@@ -58,7 +58,7 @@ Functions
The first argument is a pathname to an index file, or NULL
if the hook uses the default index file or no index is needed.
The second argument is the name of the hook.
- The further arguments (up to 9) correspond to the hook arguments.
+ The further arguments correspond to the hook arguments.
The last argument has to be NULL to terminate the arguments list.
If the hook does not exist or is not executable, the return
value will be zero.
diff --git a/run-command.c b/run-command.c
index fc54c07..d2f1262 100644
--- a/run-command.c
+++ b/run-command.c
@@ -346,23 +346,22 @@ int finish_async(struct async *async)
int run_hook(const char *index_file, const char *name, ...)
{
struct child_process hook;
- const char *argv[10], *env[2];
+ const char **argv, *env[2];
char index[PATH_MAX];
va_list args;
int ret;
- int i;
+ size_t i = 0, alloc = 0;
if (access(git_path("hooks/%s", name), X_OK) < 0)
return 0;
va_start(args, name);
- argv[0] = git_path("hooks/%s", name);
- i = 0;
- do {
- if (++i >= ARRAY_SIZE(argv))
- die("run_hook(): too many arguments");
- argv[i] = va_arg(args, const char *);
- } while (argv[i]);
+ ALLOC_GROW(argv, i + 1, alloc);
+ argv[i++] = git_path("hooks/%s", name);
+ while (argv[i-1]) {
+ ALLOC_GROW(argv, i + 1, alloc);
+ argv[i++] = va_arg(args, const char *);
+ }
va_end(args);
memset(&hook, 0, sizeof(hook));
@@ -377,6 +376,7 @@ int run_hook(const char *index_file, const char *name, ...)
}
ret = start_command(&hook);
+ free(argv);
if (ret) {
warning("Could not spawn %s", argv[0]);
return ret;
--
1.6.1.160.gecdb
^ permalink raw reply related
* [PATCH 3/3] http-push: update tests
From: Ray Chuan @ 2009-01-17 2:59 UTC (permalink / raw)
To: git
note: the test needs to chmod the test_repo.git folder so that
apache/mod_dav can create .DAV folders in it for locking.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
---
src/git-1.6.1/t/t5540-http-push.sh | 7 +++----
1 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/src/git-1.6.1/t/t5540-http-push.sh
b/src/git-1.6.1/t/t5540-http-push.sh
index da95886..730b9cb 100755
--- a/src/git-1.6.1/t/t5540-http-push.sh
+++ b/src/git-1.6.1/t/t5540-http-push.sh
@@ -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
'
-test_expect_failure 'create and delete remote branch' '
+test_expect_success 'create and delete remote branch' '
cd "$ROOT_PATH"/test_repo_clone &&
git checkout -b dev &&
: >path3 &&
--
1.6.0.4
^ permalink raw reply related
* [PATCH 2/3] http-push: when sending objects, don't PUT before MOVE
From: Ray Chuan @ 2009-01-17 2:59 UTC (permalink / raw)
To: git
since 753bc911f489748a837ecb5ea4b5216220b24845, the opaquelocktocken
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-....
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.
Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
---
src/git-1.6.1/http-push.c | 45 +--------------------------------------------
1 files changed, 1 insertions(+), 44 deletions(-)
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;
@@ -557,32 +550,6 @@ static void start_put(struct transfer_request *request)
}
}
-static void start_move(struct transfer_request *request)
-{
- struct active_request_slot *slot;
- struct curl_slist *dav_headers = NULL;
-
- slot = get_active_slot();
- slot->callback_func = process_response;
- slot->callback_data = request;
- curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); /* undo PUT setup */
- curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_MOVE);
- dav_headers = curl_slist_append(dav_headers, request->dest);
- dav_headers = curl_slist_append(dav_headers, "Overwrite: T");
- curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
- curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
- curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
-
- if (start_active_slot(slot)) {
- request->slot = slot;
- request->state = RUN_MOVE;
- } else {
- request->state = ABORTED;
- free(request->url);
- request->url = NULL;
- }
-}
-
static int refresh_lock(struct remote_lock *lock)
{
struct active_request_slot *slot;
@@ -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;
- }
- } else if (request->state == RUN_MOVE) {
- if (request->curl_result == CURLE_OK) {
if (push_verbosely)
fprintf(stderr, " sent %s\n",
sha1_to_hex(request->obj->sha1));
request->obj->flags |= REMOTE;
release_request(request);
} else {
- fprintf(stderr, "MOVE %s failed, aborting (%d/%ld)\n",
+ fprintf(stderr, "PUT %s failed, aborting (%d/%ld)\n",
sha1_to_hex(request->obj->sha1),
request->curl_result, request->http_code);
request->state = ABORTED;
--
1.6.0.4
^ permalink raw reply related
* [PATCH 1/3] http-push: append slash if possible for directories
From: Ray Chuan @ 2009-01-17 2:53 UTC (permalink / raw)
To: git
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>
---
src/git-1.6.1/http-push.c | 21 ++++++++++++++++-----
1 files changed, 16 insertions(+), 5 deletions(-)
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;
+ while (1) {
+ ep = strchr(ep + 1, '/');
+ if(ep) {
+ ep++;
+ ep_old=*ep;
+ *ep = 0;
+ has_fs = 1;
+ } else {
+ break;
+ }
slot = get_active_slot();
slot->results = &results;
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
@@ -1222,8 +1232,9 @@ static struct remote_lock *lock_remote(const
char *path, long timeout)
free(url);
return NULL;
}
- *ep = '/';
- ep = strchr(ep + 1, '/');
+ if(has_fs) {
+ *ep = ep_old;
+ }
}
strbuf_addf(&out_buffer.buf, LOCK_REQUEST, git_default_email);
--
1.6.0.4
^ permalink raw reply related
* Re: fatal: git grep: cannot generate relative filenames containing '..'
From: Hannu Koivisto @ 2009-01-17 2:21 UTC (permalink / raw)
To: Junio C Hamano; +Cc: George Spelvin, git
In-Reply-To: <7vr634ow3r.fsf@gitster.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> "George Spelvin" <linux@horizon.com> writes:
>
>> Could someone fix this some day?
>
> As far as I know you are the first to ask for this, so perhaps people never
> considered this was something to "fix"....
I for one have faced that problem and considered it something that
would be nice to have fixed. Then again, I consider the default
behaviour (when you pass no path) a bigger usability problem.
>> While you're at it, an option to search the entire git tree rather than
>> the current subdirectory would also be useful. I was thinking about
>> a flag like -r (for "root"),...
It turns out that this "entire git tree" is practically my only use
case when using normal (find and) grep and when I first tried git
grep, I actually expected it to do just that with no path specified.
Why? Because of the way at least git diff and git log work. I
thought that just like with them, "git grep foo" would search the
entire git tree and I would have to say "git grep foo ." to limit to
the current directory and its subdirectories. git-grep(1)'s "Look
for specified patterns in the working tree files..." at least
didn't seem to disagree with my expectation so I was a bit puzzled.
So I'd rather see git grep behave in a way consistent with git log
and git diff (I realize that would change current behaviour instead
of extending it).
--
Hannu
^ permalink raw reply
* Re: I've added Dulwich to the Git Wiki
From: David Aguilar @ 2009-01-17 2:37 UTC (permalink / raw)
To: Jelmer Vernooij; +Cc: Johannes Schindelin, git
In-Reply-To: <1232146991.24098.13.camel@ganieda.vernstok.nl>
On Fri, Jan 16, 2009 at 3:03 PM, Jelmer Vernooij <jelmer@samba.org> wrote:
>>
>> BTW I find it a bit distressing that more and more projects crop up doing
>> substantial and valuable work around Git, but without even bothering to
>> mention it on this list. There might have been a good chance, too, to
>> avoid having _three_ Python libraries for exactly the same task.
> I wasn't aware of PyGit (and its homepage doesn't seem to work), but
> Python-Git is just a wrapper around the git command line tools, it
> doesn't parse/write the file formats itself.
>
> Cheers,
>
> Jelmer
>
> --
> Jelmer Vernooij <jelmer@samba.org> - http://samba.org/~jelmer/
> Jabber: jelmer@jabber.fsfe.org
>
Hello
This sounds like a great project.
I've talked with the authors of GitPython in the past and I believe
the reason it was never mentioned here was that they were probably too
shy or intimidated (you guys are pretty hardcore ;-) ).
Anyways, as you said, GitPython is purely a wrapper around git
commands. BTW, git is bloody fast so it's actually not that bad and
works pretty well.
GitPython's license is the New BSD license and thus it can't use git
code nor could it use libgit2. I think the best route for a useful
Python module would be to wrap something like libgit2 which aims to be
a true library for git. If that's the goals for Dulwich then all the
better. If not (and it instead aims to be a pure-Python
implementation) then that's cool too, but for performance reasons I
think the community would best be served by pursuing a core git
library with various language bindings built on top of it.
In any case, this sounds like a neat development and it does seem like
the goals are slightly different then the existing GitPython module.
GitPython was basically a port of the Ruby Grit library, which also
just wraps git commands. I'll keep my eye on this and see if there's
anywhere I can help.
--
David
^ permalink raw reply
* Re: git add --patch bug with split+edit?
From: Jeff King @ 2009-01-17 2:33 UTC (permalink / raw)
To: Hannu Koivisto; +Cc: git
In-Reply-To: <833afihfvc.fsf@kalahari.s2.org>
On Sat, Jan 17, 2009 at 03:37:43AM +0200, Hannu Koivisto wrote:
> echo "sur\nbaz\nbaz\njee\njee" > baz
> git add --patch
>
> Now say 's RET y RET e RET' and remove the second "+jee" line using
> your editor. The output for me looks like this:
> [...]
> error: patch failed: baz:1
> error: baz: patch does not apply
> Your edited hunk does not apply. Edit again (saying "no" discards!) [y/n]?
Actually, you do not even need to change the patch at all for this to
fail. The hunk that you edit looks like this:
@@ -1,2 +2,4 @@
baz
baz
+jee
+jee
which doesn't make sense. I think the hunk header should actually be:
@@ -1,2 +1,4 @@
But I don't think that is the problem, since git-apply should be
recounting the hunk information (and in a simple test, it doesn't fix
it).
Hm. OK, I see. The "does this diff apply" check feeds _both_ parts of
the split patch to git-apply. But of course the second part will never
correctly apply, because its context overlaps with the first part, but
doesn't take it into account.
Doing the check with _just_ the edited patch would work. But that
doesn't take into account that your edited patch will potentially fail
to apply in the long run, depending on whether or not you accept the
other half of the split patch. And we can't know that yet, because the
user may not have told us (they could have skipped the first half, and
then come back to it later after the edit step).
So in general, I think splitting and editing the same hunk is inherently
dangerous and is going to lead to these sorts of problems. And because
editing provides a superset of the functionality, I think you should
just edit and either allow the first part of the hunk to be applied or
not depending on your preference.
But maybe there is some better way of resolving the conflict. I don't
see one, but I'm tired and didn't think too hard on it. :)
-Peff
^ permalink raw reply
* Re: [PATCH 3/3] Adds a #!bash to the top of bash completions so that editors can recognize, it as a bash script. Also adds a few simple comments above commands that, take arguments. The comments are meant to remind editors of potential, problems that
From: Jeff King @ 2009-01-17 1:40 UTC (permalink / raw)
To: Baz
Cc: markus.heidelberg, Adeodato Simó, Boyd Stephen Smith Jr.,
Shawn O. Pearce, Ted Pavlic, git, Junio C Hamano
In-Reply-To: <2faad3050901160706y297a98d4r35340e4811ca3d2b@mail.gmail.com>
On Fri, Jan 16, 2009 at 03:06:34PM +0000, Baz wrote:
> > At the beginning I tried to fulfil this limit, but often it's not easy.
> > So should it be adjusted to a slightly higher value in the documentation
> > or even split into a recommended limit (e.g. 50) and a recommended
> > absolute maximum (e.g. 76)? Hmm, the split wouldn't make sense, I think.
>
> The 50 character limit is for the first line, try "git log
> --pretty=oneline" and it should be obvious why.
I'm not sure it makes sense to make a workflow recommendation that the
git project itself does not follow. Of 14590 non-merge commits in
git.git, 6940 (nearly 50%) have subject lines longer than 50
characters.
In practice, is this a problem for people using git.git?
Personally, I find --pretty=oneline unreadable because so much of the
screen real estate is wasted on random characters that I don't care
about. I find --pretty=tformat:'%h %s' much nicer (yes, --abbrev-commit
works, too, but I find the '...' a pointless waste of space).
For reference, here are the percentiles of subject lines in git.git
longer than X:
X | %
50 | 48%
60 | 24%
65 | 14%
70 | 8%
So it seems that quite a large chunk are between 50 and 65 characters.
Which still leaves room for "Subject: " or 8 characters of hash at the
beginning.
> perl -ne '$lim = (50,0,72)[($.>3?3:$.)-1];
Ugh. Would a little whitespace have killed you? ;P
> (I wish I'd had something like this when one of the devs here pushed a
> commit with a 346-line message,
> just listing what files he was changing...doh)
Well, yes. That's just insane.
-Peff
^ permalink raw reply
* git add --patch bug with split+edit?
From: Hannu Koivisto @ 2009-01-17 1:37 UTC (permalink / raw)
To: git
Greetings,
If I have a hunk that adds three lines, I can edit the hunk and
remove the last line but I can't split it in two, stage the first
part, edit the second part and remove the last line. An example:
mkdir gittest
cd gittest
git init
echo "baz\nbaz" > baz
git add baz
git commit -m baz baz
rm baz
echo "sur\nbaz\nbaz\njee\njee" > baz
git add --patch
Now say 's RET y RET e RET' and remove the second "+jee" line using
your editor. The output for me looks like this:
--8<-----------------------------------------------------------------
diff --git a/baz b/baz
index 1f55335..48a5f83 100644
--- a/baz
+++ b/baz
@@ -1,2 +1,5 @@
+sur
baz
baz
+jee
+jee
Stage this hunk [y/n/a/d/s/e/?]? s
Split into 2 hunks.
@@ -1,2 +1,3 @@
+sur
baz
baz
Stage this hunk [y/n/a/d/j/J/e/?]? y
@@ -1,2 +2,4 @@
baz
baz
+jee
+jee
Stage this hunk [y/n/a/d/K/e/?]? e
Waiting for Emacs...
error: patch failed: baz:1
error: baz: patch does not apply
Your edited hunk does not apply. Edit again (saying "no" discards!) [y/n]?
--8<-----------------------------------------------------------------
What I also didn't expect is that if I answer 'n' to that last
question, I get...
@@ -1,2 +1,3 @@
+sur
baz
baz
Stage this hunk [y/n/a/d/j/J/e/?]?
...which is the first part of the splitted hunk that I already
staged. If I answer 'd', git status and git diff indicate that
"+sur" is nevertheless staged.
Now, if instead of splitting the hunk and editing it, I edit the
entire...
@@ -1,2 +1,5 @@
+sur
baz
baz
+jee
+jee
...hunk and remove the last "+jee" line, I get no error.
I'm using git 1.6.1 on Linux.
--
Hannu
^ permalink raw reply related
* [PATCH] git-checkout(1) mention fate of extraneous files
From: jidanni @ 2009-01-17 0:36 UTC (permalink / raw)
To: git
Signed-off-by: jidanni <jidanni@jidanni.org>
---
Documentation/git-checkout.txt | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 9cd5151..bce31c7 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -14,12 +14,13 @@ SYNOPSIS
DESCRIPTION
-----------
-When <paths> are not given, this command switches branches by
-updating the index and working tree to reflect the specified
-branch, <branch>, and updating HEAD to be <branch> or, if
-specified, <new_branch>. Using -b will cause <new_branch> to
-be created; in this case you can use the --track or --no-track
-options, which will be passed to `git branch`.
+When <paths> are not given, this command switches branches by updating
+the index and working tree to reflect the specified branch, <branch>,
+and updating HEAD to be <branch> or, if specified, <new_branch>. (No
+extraneous files present are deleted, use linkgit:git-clean[1] for a
+pristine checkout.) Using -b will cause <new_branch> to be created; in
+this case you can use the --track or --no-track options, which will be
+passed to `git branch`.
As a convenience, --track will default to create a branch whose
name is constructed from the specified branch name by stripping
--
1.6.0.6
^ permalink raw reply related
* Re: I've added Dulwich to the Git Wiki
From: Johannes Schindelin @ 2009-01-16 23:30 UTC (permalink / raw)
To: Jelmer Vernooij; +Cc: git
In-Reply-To: <1232146991.24098.13.camel@ganieda.vernstok.nl>
Hi,
On Sat, 17 Jan 2009, Jelmer Vernooij wrote:
> See:
>
> git://git.samba.org/jelmer/dulwich.git
>
> And gitweb: http://git.samba.org/?p=jelmer/dulwich.git;a=summary
For higher visibility, I also added these to the Wiki.
Ciao,
Dscho
^ permalink raw reply
* Re: I've added Dulwich to the Git Wiki
From: Adeodato Simó @ 2009-01-16 23:04 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: jelmer, git
In-Reply-To: <alpine.DEB.1.00.0901162329340.3586@pacific.mpi-cbg.de>
* Johannes Schindelin [Fri, 16 Jan 2009 23:42:38 +0100]:
> Hi people,
> just got aware of the Dulwich project, which purports to be a pure Python
> Git engine.
Interesting.
> Jelmer, is there a chance you can export the Bazaar repository into a
> public Git repository? The Bazaar web-frontend does not even allow me to
> download a snapshot.
Unfortunately, the Dulwich repository contains Git repositories within,
so the resulting repository is not valid. I guess one could drop those
when converting.
--
Adeodato Simó dato at net.com.org.es
Debian Developer adeodato at debian.org
Listening to: Radiohead - House Of Cards
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox