* [PATCH 5/5] for-each-ref: add split message parts to %(contents:*).
From: Jeff King @ 2011-09-07 17:46 UTC (permalink / raw)
To: Michał Górny; +Cc: git, Junio C Hamano, Michael J Gruber
In-Reply-To: <20110902175323.GA29761@sigill.intra.peff.net>
From: Michał Górny <mgorny@gentoo.org>
The %(body) placeholder returns the whole body of a tag or
commit, including the signature. However, callers may want
to get just the body without signature, or just the
signature.
Rather than change the meaning of %(body), which might break
some scripts, this patch introduces a new set of
placeholders which break down the %(contents) placeholder
into its constituent parts.
[jk: initial patch by mg, rebased on top of my refactoring
and with tests by me]
Signed-off-by: Jeff King <peff@peff.net>
---
Documentation/git-for-each-ref.txt | 7 ++--
builtin/for-each-ref.c | 32 +++++++++++++++---
t/lib-gpg.sh | 8 +++++
t/t6300-for-each-ref.sh | 60 ++++++++++++++++++++++++++++++++++-
4 files changed, 96 insertions(+), 11 deletions(-)
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index 152e695..c872b88 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -101,9 +101,10 @@ Fields that have name-email-date tuple as its value (`author`,
`committer`, and `tagger`) can be suffixed with `name`, `email`,
and `date` to extract the named component.
-The first line of the message in a commit and tag object is
-`subject`, the remaining lines are `body`. The whole message
-is `contents`.
+The complete message in a commit and tag object is `contents`.
+Its first line is `contents:subject`, the remaining lines
+are `contents:body` and the optional GPG signature
+is `contents:signature`.
For sorting purposes, fields with numeric values sort in numeric
order (`objectsize`, `authordate`, `committerdate`, `taggerdate`).
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index ea2112b..50fba65 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -69,6 +69,9 @@ static struct {
{ "subject" },
{ "body" },
{ "contents" },
+ { "contents:subject" },
+ { "contents:body" },
+ { "contents:signature" },
{ "upstream" },
{ "symref" },
{ "flag" },
@@ -472,7 +475,9 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru
static void find_subpos(const char *buf, unsigned long sz,
const char **sub, unsigned long *sublen,
- const char **body, unsigned long *bodylen)
+ const char **body, unsigned long *bodylen,
+ unsigned long *nonsiglen,
+ const char **sig, unsigned long *siglen)
{
const char *eol;
/* skip past header until we hit empty line */
@@ -486,10 +491,14 @@ static void find_subpos(const char *buf, unsigned long sz,
while (*buf == '\n')
buf++;
+ /* parse signature first; we might not even have a subject line */
+ *sig = buf + parse_signature(buf, strlen(buf));
+ *siglen = strlen(*sig);
+
/* subject is first non-empty line */
*sub = buf;
/* subject goes to first empty line */
- while (*buf && *buf != '\n') {
+ while (buf < *sig && *buf && *buf != '\n') {
eol = strchrnul(buf, '\n');
if (*eol)
eol++;
@@ -505,14 +514,15 @@ static void find_subpos(const char *buf, unsigned long sz,
buf++;
*body = buf;
*bodylen = strlen(buf);
+ *nonsiglen = *sig - buf;
}
/* See grab_values */
static void grab_sub_body_contents(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
{
int i;
- const char *subpos = NULL, *bodypos;
- unsigned long sublen, bodylen;
+ const char *subpos = NULL, *bodypos, *sigpos;
+ unsigned long sublen, bodylen, nonsiglen, siglen;
for (i = 0; i < used_atom_cnt; i++) {
const char *name = used_atom[i];
@@ -523,17 +533,27 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct obj
name++;
if (strcmp(name, "subject") &&
strcmp(name, "body") &&
- strcmp(name, "contents"))
+ strcmp(name, "contents") &&
+ strcmp(name, "contents:subject") &&
+ strcmp(name, "contents:body") &&
+ strcmp(name, "contents:signature"))
continue;
if (!subpos)
find_subpos(buf, sz,
&subpos, &sublen,
- &bodypos, &bodylen);
+ &bodypos, &bodylen, &nonsiglen,
+ &sigpos, &siglen);
if (!strcmp(name, "subject"))
v->s = copy_subject(subpos, sublen);
+ else if (!strcmp(name, "contents:subject"))
+ v->s = copy_subject(subpos, sublen);
else if (!strcmp(name, "body"))
v->s = xmemdupz(bodypos, bodylen);
+ else if (!strcmp(name, "contents:body"))
+ v->s = xmemdupz(bodypos, nonsiglen);
+ else if (!strcmp(name, "contents:signature"))
+ v->s = xmemdupz(sigpos, siglen);
else if (!strcmp(name, "contents"))
v->s = xstrdup(subpos);
}
diff --git a/t/lib-gpg.sh b/t/lib-gpg.sh
index 28463fb..05824fa 100755
--- a/t/lib-gpg.sh
+++ b/t/lib-gpg.sh
@@ -24,3 +24,11 @@ else
;;
esac
fi
+
+sanitize_pgp() {
+ perl -ne '
+ /^-----END PGP/ and $in_pgp = 0;
+ print unless $in_pgp;
+ /^-----BEGIN PGP/ and $in_pgp = 1;
+ '
+}
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index 0c9ff96..1721784 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -6,6 +6,7 @@
test_description='for-each-ref test'
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-gpg.sh
# Mon Jul 3 15:18:43 2006 +0000
datestamp=1151939923
@@ -40,9 +41,10 @@ test_atom() {
*) ref=$1 ;;
esac
printf '%s\n' "$3" >expected
- test_expect_${4:-success} "basic atom: $1 $2" "
+ test_expect_${4:-success} $PREREQ "basic atom: $1 $2" "
git for-each-ref --format='%($2)' $ref >actual &&
- test_cmp expected actual
+ sanitize_pgp <actual >actual.clean &&
+ test_cmp expected actual.clean
"
}
@@ -72,7 +74,10 @@ test_atom head taggerdate ''
test_atom head creator 'C O Mitter <committer@example.com> 1151939923 +0200'
test_atom head creatordate 'Mon Jul 3 17:18:43 2006 +0200'
test_atom head subject 'Initial'
+test_atom head contents:subject 'Initial'
test_atom head body ''
+test_atom head contents:body ''
+test_atom head contents:signature ''
test_atom head contents 'Initial
'
@@ -102,7 +107,10 @@ test_atom tag taggerdate 'Mon Jul 3 17:18:45 2006 +0200'
test_atom tag creator 'C O Mitter <committer@example.com> 1151939925 +0200'
test_atom tag creatordate 'Mon Jul 3 17:18:45 2006 +0200'
test_atom tag subject 'Tagging at 1151939927'
+test_atom tag contents:subject 'Tagging at 1151939927'
test_atom tag body ''
+test_atom tag contents:body ''
+test_atom tag contents:signature ''
test_atom tag contents 'Tagging at 1151939927
'
@@ -390,9 +398,14 @@ test_expect_success 'create tag with multiline subject' '
git tag -F msg multiline
'
test_atom refs/tags/multiline subject 'first subject line second subject line'
+test_atom refs/tags/multiline contents:subject 'first subject line second subject line'
test_atom refs/tags/multiline body 'first body line
second body line
'
+test_atom refs/tags/multiline contents:body 'first body line
+second body line
+'
+test_atom refs/tags/multiline contents:signature ''
test_atom refs/tags/multiline contents 'first subject line
second subject line
@@ -400,4 +413,47 @@ first body line
second body line
'
+test_expect_success GPG 'create signed tags' '
+ git tag -s -m "" signed-empty &&
+ git tag -s -m "subject line" signed-short &&
+ cat >msg <<-\EOF &&
+ subject line
+
+ body contents
+ EOF
+ git tag -s -F msg signed-long
+'
+
+sig='-----BEGIN PGP SIGNATURE-----
+-----END PGP SIGNATURE-----
+'
+
+PREREQ=GPG
+test_atom refs/tags/signed-empty subject ''
+test_atom refs/tags/signed-empty contents:subject ''
+test_atom refs/tags/signed-empty body "$sig"
+test_atom refs/tags/signed-empty contents:body ''
+test_atom refs/tags/signed-empty contents:signature "$sig"
+test_atom refs/tags/signed-empty contents "$sig"
+
+test_atom refs/tags/signed-short subject 'subject line'
+test_atom refs/tags/signed-short contents:subject 'subject line'
+test_atom refs/tags/signed-short body "$sig"
+test_atom refs/tags/signed-short contents:body ''
+test_atom refs/tags/signed-short contents:signature "$sig"
+test_atom refs/tags/signed-short contents "subject line
+$sig"
+
+test_atom refs/tags/signed-long subject 'subject line'
+test_atom refs/tags/signed-long contents:subject 'subject line'
+test_atom refs/tags/signed-long body "body contents
+$sig"
+test_atom refs/tags/signed-long contents:body 'body contents
+'
+test_atom refs/tags/signed-long contents:signature "$sig"
+test_atom refs/tags/signed-long contents "subject line
+
+body contents
+$sig"
+
test_done
--
1.7.6.10.g62f04
^ permalink raw reply related
* [PATCH 4/5] for-each-ref: handle multiline subjects like --pretty
From: Jeff King @ 2011-09-07 17:44 UTC (permalink / raw)
To: Michał Górny; +Cc: git, Junio C Hamano, Michael J Gruber
In-Reply-To: <20110902175323.GA29761@sigill.intra.peff.net>
Generally the format of a git tag or commit message is:
subject
body body body
body body body
However, we occasionally see multiline subjects like:
subject
with multiple
lines
body body body
body body body
The rest of git treats these multiline subjects as something
to be concatenated and shown as a single line (e.g., "git
log --pretty=format:%s" will do so since f53bd74). For
consistency, for-each-ref should do the same with its
"%(subject)".
Signed-off-by: Jeff King <peff@peff.net>
---
I split this out from the signature patch to make it more obvious what's
going on.
builtin/for-each-ref.c | 29 ++++++++++++++++++++++++-----
t/t6300-for-each-ref.sh | 21 +++++++++++++++++++++
2 files changed, 45 insertions(+), 5 deletions(-)
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index bcea027..ea2112b 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -361,6 +361,18 @@ static const char *copy_email(const char *buf)
return xmemdupz(email, eoemail + 1 - email);
}
+static char *copy_subject(const char *buf, unsigned long len)
+{
+ char *r = xmemdupz(buf, len);
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (r[i] == '\n')
+ r[i] = ' ';
+
+ return r;
+}
+
static void grab_date(const char *buf, struct atom_value *v, const char *atomname)
{
const char *eoemail = strstr(buf, "> ");
@@ -476,10 +488,17 @@ static void find_subpos(const char *buf, unsigned long sz,
/* subject is first non-empty line */
*sub = buf;
- /* subject goes to end of line */
- eol = strchrnul(buf, '\n');
- *sublen = eol - buf;
- buf = eol;
+ /* subject goes to first empty line */
+ while (*buf && *buf != '\n') {
+ eol = strchrnul(buf, '\n');
+ if (*eol)
+ eol++;
+ buf = eol;
+ }
+ *sublen = buf - *sub;
+ /* drop trailing newline, if present */
+ if (*sublen && (*sub)[*sublen - 1] == '\n')
+ *sublen -= 1;
/* skip any empty lines */
while (*buf == '\n')
@@ -512,7 +531,7 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct obj
&bodypos, &bodylen);
if (!strcmp(name, "subject"))
- v->s = xmemdupz(subpos, sublen);
+ v->s = copy_subject(subpos, sublen);
else if (!strcmp(name, "body"))
v->s = xmemdupz(bodypos, bodylen);
else if (!strcmp(name, "contents"))
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index 6fa4d52..0c9ff96 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -379,4 +379,25 @@ first body line
second body line
'
+test_expect_success 'create tag with multiline subject' '
+ cat >msg <<-\EOF &&
+ first subject line
+ second subject line
+
+ first body line
+ second body line
+ EOF
+ git tag -F msg multiline
+'
+test_atom refs/tags/multiline subject 'first subject line second subject line'
+test_atom refs/tags/multiline body 'first body line
+second body line
+'
+test_atom refs/tags/multiline contents 'first subject line
+second subject line
+
+first body line
+second body line
+'
+
test_done
--
1.7.6.10.g62f04
^ permalink raw reply related
* [PATCH 3/5] for-each-ref: refactor subject and body placeholder parsing
From: Jeff King @ 2011-09-07 17:44 UTC (permalink / raw)
To: Michał Górny; +Cc: git, Junio C Hamano, Michael J Gruber
In-Reply-To: <20110902175323.GA29761@sigill.intra.peff.net>
The find_subpos function was a little hard to use, as well
as to read. It would sometimes write into the subject and
body pointers, and sometimes not. The body pointer sometimes
could be compared to subject, and sometimes not. When
actually duplicating the subject, the caller was forced to
figure out again how long the subject is (which is not too
big a deal when the subject is a single line, but hard to
extend).
The refactoring makes the function more straightforward, both
to read and to use. We will always put something into the
subject and body pointers, and we return explicit lengths
for them, too.
This lays the groundwork both for more complex subject
parsing (e.g., multiline), as well as splitting the body
into subparts (like the text versus the signature).
Signed-off-by: Jeff King <peff@peff.net>
---
Sorry, the patch is a little bit hard to read. It's probably simpler to
just apply and read the resulting function.
builtin/for-each-ref.c | 54 +++++++++++++++++++++++++----------------------
1 files changed, 29 insertions(+), 25 deletions(-)
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 89e75c6..bcea027 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -458,38 +458,42 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru
}
}
-static void find_subpos(const char *buf, unsigned long sz, const char **sub, const char **body)
+static void find_subpos(const char *buf, unsigned long sz,
+ const char **sub, unsigned long *sublen,
+ const char **body, unsigned long *bodylen)
{
- while (*buf) {
- const char *eol = strchr(buf, '\n');
- if (!eol)
- return;
- if (eol[1] == '\n') {
- buf = eol + 1;
- break; /* found end of header */
- }
- buf = eol + 1;
+ const char *eol;
+ /* skip past header until we hit empty line */
+ while (*buf && *buf != '\n') {
+ eol = strchrnul(buf, '\n');
+ if (*eol)
+ eol++;
+ buf = eol;
}
+ /* skip any empty lines */
while (*buf == '\n')
buf++;
- if (!*buf)
- return;
- *sub = buf; /* first non-empty line */
- buf = strchr(buf, '\n');
- if (!buf) {
- *body = "";
- return; /* no body */
- }
+
+ /* subject is first non-empty line */
+ *sub = buf;
+ /* subject goes to end of line */
+ eol = strchrnul(buf, '\n');
+ *sublen = eol - buf;
+ buf = eol;
+
+ /* skip any empty lines */
while (*buf == '\n')
- buf++; /* skip blank between subject and body */
+ buf++;
*body = buf;
+ *bodylen = strlen(buf);
}
/* See grab_values */
static void grab_sub_body_contents(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
{
int i;
- const char *subpos = NULL, *bodypos = NULL;
+ const char *subpos = NULL, *bodypos;
+ unsigned long sublen, bodylen;
for (i = 0; i < used_atom_cnt; i++) {
const char *name = used_atom[i];
@@ -503,14 +507,14 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct obj
strcmp(name, "contents"))
continue;
if (!subpos)
- find_subpos(buf, sz, &subpos, &bodypos);
- if (!subpos)
- return;
+ find_subpos(buf, sz,
+ &subpos, &sublen,
+ &bodypos, &bodylen);
if (!strcmp(name, "subject"))
- v->s = copy_line(subpos);
+ v->s = xmemdupz(subpos, sublen);
else if (!strcmp(name, "body"))
- v->s = xstrdup(bodypos);
+ v->s = xmemdupz(bodypos, bodylen);
else if (!strcmp(name, "contents"))
v->s = xstrdup(subpos);
}
--
1.7.6.10.g62f04
^ permalink raw reply related
* [PATCH 2/5] t6300: add more body-parsing tests
From: Jeff King @ 2011-09-07 17:43 UTC (permalink / raw)
To: Michał Górny; +Cc: git, Junio C Hamano, Michael J Gruber
In-Reply-To: <20110902175323.GA29761@sigill.intra.peff.net>
The current tests don't actually check parsing commit and
tag messages that have both a subject and a body (they just
have single-line messages).
Signed-off-by: Jeff King <peff@peff.net>
---
This is mostly to help make sure the next patch doesn't regress this
case.
t/t6300-for-each-ref.sh | 20 ++++++++++++++++++++
1 files changed, 20 insertions(+), 0 deletions(-)
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index 7dc8a51..6fa4d52 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -37,6 +37,7 @@ test_atom() {
case "$1" in
head) ref=refs/heads/master ;;
tag) ref=refs/tags/testtag ;;
+ *) ref=$1 ;;
esac
printf '%s\n' "$3" >expected
test_expect_${4:-success} "basic atom: $1 $2" "
@@ -359,4 +360,23 @@ test_expect_success 'an unusual tag with an incomplete line' '
'
+test_expect_success 'create tag with subject and body content' '
+ cat >>msg <<-\EOF &&
+ the subject line
+
+ first body line
+ second body line
+ EOF
+ git tag -F msg subject-body
+'
+test_atom refs/tags/subject-body subject 'the subject line'
+test_atom refs/tags/subject-body body 'first body line
+second body line
+'
+test_atom refs/tags/subject-body contents 'the subject line
+
+first body line
+second body line
+'
+
test_done
--
1.7.6.10.g62f04
^ permalink raw reply related
* [PATCH 1/5] t7004: factor out gpg setup
From: Jeff King @ 2011-09-07 17:42 UTC (permalink / raw)
To: Michał Górny; +Cc: git, Junio C Hamano, Michael J Gruber
In-Reply-To: <20110902175323.GA29761@sigill.intra.peff.net>
Other test scripts may want to look at or verify signed
tags, and the setup is non-trivial. Let's factor this out
into lib-gpg.sh for other tests to use.
Signed-off-by: Jeff King <peff@peff.net>
---
Similar to the one I sent out earlier, but in that one I accidentally
did:
. ../lib-gpg.sh
which is not right. If --root is used for the test script, then ".." is
not necessarily the right place to find the lib-gpg script. This fixes
it to use $TEST_DIRECTORY.
t/lib-gpg.sh | 26 ++++++++++++++++++++++++++
t/{t7004 => lib-gpg}/pubring.gpg | Bin 1164 -> 1164 bytes
t/{t7004 => lib-gpg}/random_seed | Bin 600 -> 600 bytes
t/{t7004 => lib-gpg}/secring.gpg | Bin 1237 -> 1237 bytes
t/{t7004 => lib-gpg}/trustdb.gpg | Bin 1280 -> 1280 bytes
t/t7004-tag.sh | 29 +----------------------------
6 files changed, 27 insertions(+), 28 deletions(-)
create mode 100755 t/lib-gpg.sh
rename t/{t7004 => lib-gpg}/pubring.gpg (100%)
rename t/{t7004 => lib-gpg}/random_seed (100%)
rename t/{t7004 => lib-gpg}/secring.gpg (100%)
rename t/{t7004 => lib-gpg}/trustdb.gpg (100%)
diff --git a/t/lib-gpg.sh b/t/lib-gpg.sh
new file mode 100755
index 0000000..28463fb
--- /dev/null
+++ b/t/lib-gpg.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+gpg_version=`gpg --version 2>&1`
+if test $? = 127; then
+ say "You do not seem to have gpg installed"
+else
+ # As said here: http://www.gnupg.org/documentation/faqs.html#q6.19
+ # the gpg version 1.0.6 didn't parse trust packets correctly, so for
+ # that version, creation of signed tags using the generated key fails.
+ case "$gpg_version" in
+ 'gpg (GnuPG) 1.0.6'*)
+ say "Your version of gpg (1.0.6) is too buggy for testing"
+ ;;
+ *)
+ # key generation info: gpg --homedir t/lib-gpg --gen-key
+ # Type DSA and Elgamal, size 2048 bits, no expiration date.
+ # Name and email: C O Mitter <committer@example.com>
+ # No password given, to enable non-interactive operation.
+ cp -R "$TEST_DIRECTORY"/lib-gpg ./gpghome
+ chmod 0700 gpghome
+ GNUPGHOME="$(pwd)/gpghome"
+ export GNUPGHOME
+ test_set_prereq GPG
+ ;;
+ esac
+fi
diff --git a/t/t7004/pubring.gpg b/t/lib-gpg/pubring.gpg
similarity index 100%
rename from t/t7004/pubring.gpg
rename to t/lib-gpg/pubring.gpg
diff --git a/t/t7004/random_seed b/t/lib-gpg/random_seed
similarity index 100%
rename from t/t7004/random_seed
rename to t/lib-gpg/random_seed
diff --git a/t/t7004/secring.gpg b/t/lib-gpg/secring.gpg
similarity index 100%
rename from t/t7004/secring.gpg
rename to t/lib-gpg/secring.gpg
diff --git a/t/t7004/trustdb.gpg b/t/lib-gpg/trustdb.gpg
similarity index 100%
rename from t/t7004/trustdb.gpg
rename to t/lib-gpg/trustdb.gpg
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 097ce2b..e93ac73 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -8,6 +8,7 @@ test_description='git tag
Tests for operations with tags.'
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-gpg.sh
# creating and listing lightweight tags:
@@ -585,24 +586,6 @@ test_expect_success \
test_cmp expect actual
'
-# subsequent tests require gpg; check if it is available
-gpg --version >/dev/null 2>/dev/null
-if [ $? -eq 127 ]; then
- say "# gpg not found - skipping tag signing and verification tests"
-else
- # As said here: http://www.gnupg.org/documentation/faqs.html#q6.19
- # the gpg version 1.0.6 didn't parse trust packets correctly, so for
- # that version, creation of signed tags using the generated key fails.
- case "$(gpg --version)" in
- 'gpg (GnuPG) 1.0.6'*)
- say "Skipping signed tag tests, because a bug in 1.0.6 version"
- ;;
- *)
- test_set_prereq GPG
- ;;
- esac
-fi
-
# trying to verify annotated non-signed tags:
test_expect_success GPG \
@@ -625,16 +608,6 @@ test_expect_success GPG \
# creating and verifying signed tags:
-# key generation info: gpg --homedir t/t7004 --gen-key
-# Type DSA and Elgamal, size 2048 bits, no expiration date.
-# Name and email: C O Mitter <committer@example.com>
-# No password given, to enable non-interactive operation.
-
-cp -R "$TEST_DIRECTORY"/t7004 ./gpghome
-chmod 0700 gpghome
-GNUPGHOME="$(pwd)/gpghome"
-export GNUPGHOME
-
get_tag_header signed-tag $commit commit $time >expect
echo 'A signed tag message' >>expect
echo '-----BEGIN PGP SIGNATURE-----' >>expect
--
1.7.6.10.g62f04
^ permalink raw reply related
* Re: [PATCH] for-each-ref: add split message parts to %(contents:*).
From: Jeff King @ 2011-09-07 17:40 UTC (permalink / raw)
To: Michał Górny; +Cc: git, Junio C Hamano, Michael J Gruber
In-Reply-To: <20110902175323.GA29761@sigill.intra.peff.net>
On Fri, Sep 02, 2011 at 01:53:23PM -0400, Jeff King wrote:
> But there may be other corner cases. I need to read through the code
> more carefully, which I should have time to do later today.
This ended up a little trickier than I expected, but I think the series
below is what we should do. I tried to add extensive tests, but let me
know if you can think of any other corner cases.
[1/5]: t7004: factor out gpg setup
[2/5]: t6300: add more body-parsing tests
[3/5]: for-each-ref: refactor subject and body placeholder parsing
[4/5]: for-each-ref: handle multiline subjects like --pretty
[5/5]: for-each-ref: add split message parts to %(contents:*).
-Peff
^ permalink raw reply
* [PATCH v2] git-svn: teach git-svn to populate svn:mergeinfo
From: Bryan Jacobs @ 2011-09-07 17:36 UTC (permalink / raw)
To: git; +Cc: Eric Wong, Sam Vilain
Allow git-svn to populate the svn:mergeinfo property automatically in
a narrow range of circumstances. Specifically, when dcommitting a
revision with multiple parents, all but (potentially) the first of
which have been committed to SVN in the same repository as the target
of the dcommit.
In this case, the merge info is the union of that given by each of the
parents, plus all changes introduced to the first parent by the other
parents.
In all other cases where a revision to be committed has multiple
parents, cause "git svn dcommit" to raise an error rather than
completing the commit and potentially losing history information in
the upstream SVN repository.
This behavior is disabled by default, and can be enabled by setting
the svn.pushmergeinfo config option.
Signed-off-by: Bryan Jacobs <bjacobs@woti.com>
---
This is the second revision of a patch I posted earlier. I believe this patch is now suitable for inclusion.
Significant changes from the last revision are:
- All revisions in the commit list are checked beforehand to ensure that all non-first-parents of merge commits have suitable SVN metadata attached.
- Cases where a merge commit is at the top of an uncommitted stack are tested and now work correctly.
- Cleanups as suggested by Eric Wong.
This code is still vulnerable to race conditions if the git repository is modified while a dcommit is in progress, but this is a fundamental problem with git-svn's continual-rebasing-series approach, as previously discussed.
I believe I have determined the source of the added+untracked files in the working copy. With this repository:
branch1: A - B
/
branch2: C
If a file is added in C, and you attempt to dcommit B (C must be dcommitted or the problem will be detected and the commit will abort), git-svn runs a reset --mixed. So because the files added in C were present in B, they remain present but are untracked when you reset --mixed to A. So you cannot apply B to the rebased state because it would "create" the file you already have (with, admittedly, identical contents).
I'm not clear on why git will not allow this to proceed - the file in the working copy is identical to the file that would be "created", so there's no loss of data. "file would be overwritten", yes, technically, but never altered, so no problem really... Might be a user-interface consistency issue to allow it, but I'd be inclined to say git's behavior should change.
Regardless, this could be solved by using a reset --hard to A before beginning. Since we already disallow dcommitting with a dirty WC, this should be safe (never thought I'd say that about a reset --hard). I'm not going to write that change, though.
Of course, users could also recover from even the worst disaster via the reflog.
Documentation/git-svn.txt | 8 +
git-svn.perl | 255 +++++++++++++++++++++++++
t/t9160-git-svn-mergeinfo-push.sh | 104 ++++++++++
t/t9160/branches.dump | 374 +++++++++++++++++++++++++++++++++++++
4 files changed, 741 insertions(+), 0 deletions(-)
create mode 100755 t/t9160-git-svn-mergeinfo-push.sh
create mode 100644 t/t9160/branches.dump
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index ed5eca1..89955a2 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -213,6 +213,14 @@ discouraged.
store this information (as a property), and svn clients starting from
version 1.5 can make use of it. 'git svn' currently does not use it
and does not set it automatically.
++
+[verse]
+config key: svn.pushmergeinfo
++
+This option will cause git-svn to attempt to automatically populate the
+svn:mergeinfo property in the SVN repository when possible. Currently, this can
+only be done when dcommitting non-fast-forward merges where all parents but the
+first have already been pushed into SVN.
'branch'::
Create a branch in the SVN repository.
diff --git a/git-svn.perl b/git-svn.perl
index 89f83fd..bf60300 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -497,6 +497,195 @@ sub cmd_set_tree {
unlink $gs->{index};
}
+sub split_merge_info_range {
+ my ($range) = @_;
+ if ($range =~ /(\d+)-(\d+)/) {
+ return (int($1), int($2));
+ } else {
+ return (int($range), int($range));
+ }
+}
+
+sub combine_ranges {
+ my ($in) = @_;
+
+ my @fnums = ();
+ my @arr = split(/,/, $in);
+ for my $element (@arr) {
+ my ($start, $end) = split_merge_info_range($element);
+ push @fnums, $start;
+ }
+
+ my @sorted = @arr [ sort {
+ $fnums[$a] <=> $fnums[$b]
+ } 0..$#arr ];
+
+ my @return = ();
+ my $last = -1;
+ my $first = -1;
+ for my $element (@sorted) {
+ my ($start, $end) = split_merge_info_range($element);
+
+ if ($last == -1) {
+ $first = $start;
+ $last = $end;
+ next;
+ }
+ if ($start <= $last+1) {
+ if ($end > $last) {
+ $last = $end;
+ }
+ next;
+ }
+ if ($first == $last) {
+ push @return, "$first";
+ } else {
+ push @return, "$first-$last";
+ }
+ $first = $start;
+ $last = $end;
+ }
+
+ if ($first != -1) {
+ if ($first == $last) {
+ push @return, "$first";
+ } else {
+ push @return, "$first-$last";
+ }
+ }
+
+ return join(',', @return);
+}
+
+sub merge_revs_into_hash {
+ my ($hash, $minfo) = @_;
+ my @lines = split(' ', $minfo);
+
+ for my $line (@lines) {
+ my ($branchpath, $revs) = split(/:/, $line);
+
+ if (exists($hash->{$branchpath})) {
+ # Merge the two revision sets
+ my $combined = "$hash->{$branchpath},$revs";
+ $hash->{$branchpath} = combine_ranges($combined);
+ } else {
+ # Just do range combining for consolidation
+ $hash->{$branchpath} = combine_ranges($revs);
+ }
+ }
+}
+
+sub merge_merge_info {
+ my ($mergeinfo_one, $mergeinfo_two) = @_;
+ my %result_hash = ();
+
+ merge_revs_into_hash(\%result_hash, $mergeinfo_one);
+ merge_revs_into_hash(\%result_hash, $mergeinfo_two);
+
+ my $result = '';
+ # Sort below is for consistency's sake
+ for my $branchname (sort keys(%result_hash)) {
+ my $revlist = $result_hash{$branchname};
+ $result .= "$branchname:$revlist\n"
+ }
+ return $result;
+}
+
+sub populate_merge_info {
+ my ($d, $gs, $uuid, $linear_refs, $rewritten_parent) = @_;
+
+ my %parentshash;
+ read_commit_parents(\%parentshash, $d);
+ my @parents = @{$parentshash{$d}};
+ if ($#parents > 0) {
+ # Merge commit
+ my $all_parents_ok = 1;
+ my $aggregate_mergeinfo = '';
+ my $rooturl = $gs->repos_root;
+
+ if (defined($rewritten_parent)) {
+ # Replace first parent with newly-rewritten version
+ shift @parents;
+ unshift @parents, $rewritten_parent;
+ }
+
+ foreach my $parent (@parents) {
+ my ($branchurl, $svnrev, $paruuid) =
+ cmt_metadata($parent);
+
+ unless (defined($svnrev)) {
+ # Should have been caught be preflight check
+ fatal "merge commit $d has ancestor $parent, but that change "
+ ."does not have git-svn metadata!";
+ }
+ unless ($branchurl =~ /^$rooturl(.*)/) {
+ fatal "commit $parent git-svn metadata changed mid-run!";
+ }
+ my $branchpath = $1;
+
+ my $ra = Git::SVN::Ra->new($branchurl);
+ my (undef, undef, $props) =
+ $ra->get_dir(canonicalize_path("."), $svnrev);
+ my $par_mergeinfo = $props->{'svn:mergeinfo'};
+ unless (defined $par_mergeinfo) {
+ $par_mergeinfo = '';
+ }
+ # Merge previous mergeinfo values
+ $aggregate_mergeinfo =
+ merge_merge_info($aggregate_mergeinfo,
+ $par_mergeinfo, 0);
+
+ next if $parent eq $parents[0]; # Skip first parent
+ # Add new changes being placed in tree by merge
+ my @cmd = (qw/rev-list --reverse/,
+ $parent, qw/--not/);
+ foreach my $par (@parents) {
+ unless ($par eq $parent) {
+ push @cmd, $par;
+ }
+ }
+ my @revsin = ();
+ my ($revlist, $ctx) = command_output_pipe(@cmd);
+ while (<$revlist>) {
+ my $irev = $_;
+ chomp $irev;
+ my (undef, $csvnrev, undef) =
+ cmt_metadata($irev);
+ unless (defined $csvnrev) {
+ # A child is missing SVN annotations...
+ # this might be OK, or might not be.
+ warn "W:child $irev is merged into revision "
+ ."$d but does not have git-svn metadata. "
+ ."This means git-svn cannot determine the "
+ ."svn revision numbers to place into the "
+ ."svn:mergeinfo property. You must ensure "
+ ."a branch is entirely committed to "
+ ."SVN before merging it in order for "
+ ."svn:mergeinfo population to function "
+ ."properly";
+ }
+ push @revsin, $csvnrev;
+ }
+ command_close_pipe($revlist, $ctx);
+
+ last unless $all_parents_ok;
+
+ # We now have a list of all SVN revnos which are
+ # merged by this particular parent. Integrate them.
+ next if $#revsin == -1;
+ my $newmergeinfo = "$branchpath:" . join(',', @revsin);
+ $aggregate_mergeinfo =
+ merge_merge_info($aggregate_mergeinfo,
+ $newmergeinfo, 1);
+ }
+ if ($all_parents_ok and $aggregate_mergeinfo) {
+ return $aggregate_mergeinfo;
+ }
+ }
+
+ return undef;
+}
+
sub cmd_dcommit {
my $head = shift;
command_noisy(qw/update-index --refresh/);
@@ -547,6 +736,62 @@ sub cmd_dcommit {
"without --no-rebase may be required."
}
my $expect_url = $url;
+
+ my $push_merge_info = eval {
+ command_oneline(qw/config --get svn.pushmergeinfo/)
+ };
+ if (not defined($push_merge_info)
+ or $push_merge_info eq "false"
+ or $push_merge_info eq "no"
+ or $push_merge_info eq "never") {
+ $push_merge_info = 0;
+ }
+
+ unless (defined $_merge_info or not $push_merge_info) {
+ # Preflight check of changes to ensure no issues with mergeinfo
+ # This includes check for uncommitted-to-SVN parents
+ # (other than the first parent, which we will handle),
+ # information from different SVN repos, and paths
+ # which are not underneath this repository root.
+ my $rooturl = $gs->repos_root;
+ foreach my $d (@$linear_refs) {
+ my %parentshash;
+ read_commit_parents(\%parentshash, $d);
+ my @realparents = @{$parentshash{$d}};
+ if ($#realparents > 0) {
+ # Merge commit
+ shift @realparents; # Remove/ignore first parent
+ foreach my $parent (@realparents) {
+ my ($branchurl, $svnrev, $paruuid) = cmt_metadata($parent);
+ unless (defined $paruuid) {
+ # A parent is missing SVN annotations...
+ # abort the whole operation.
+ fatal "$parent is merged into revision $d, "
+ ."but does not have git-svn metadata. "
+ ."Either dcommit the branch or use a "
+ ."local cherry-pick, FF merge, or rebase "
+ ."instead of an explicit merge commit.";
+ }
+
+ unless ($paruuid eq $uuid) {
+ # Parent has SVN metadata from different repository
+ fatal "merge parent $parent for change $d has "
+ ."git-svn uuid $paruuid, while current change "
+ ."has uuid $uuid!";
+ }
+
+ unless ($branchurl =~ /^$rooturl(.*)/) {
+ # This branch is very strange indeed.
+ fatal "merge parent $parent for $d is on branch "
+ ."$branchurl, which is not under the "
+ ."git-svn root $rooturl!";
+ }
+ }
+ }
+ }
+ }
+
+ my $rewritten_parent;
Git::SVN::remove_username($expect_url);
while (1) {
my $d = shift @$linear_refs or last;
@@ -561,6 +806,13 @@ sub cmd_dcommit {
print "diff-tree $d~1 $d\n";
} else {
my $cmt_rev;
+
+ unless (defined $_merge_info or not $push_merge_info) {
+ $_merge_info = populate_merge_info($d, $gs, $uuid,
+ $linear_refs,
+ $rewritten_parent);
+ }
+
my %ed_opts = ( r => $last_rev,
log => get_commit_entry($d)->{log},
ra => Git::SVN::Ra->new($url),
@@ -603,6 +855,9 @@ sub cmd_dcommit {
@finish = qw/reset --mixed/;
}
command_noisy(@finish, $gs->refname);
+
+ $rewritten_parent = command_oneline(qw/rev-parse HEAD/);
+
if (@diff) {
@refs = ();
my ($url_, $rev_, $uuid_, $gs_) =
diff --git a/t/t9160-git-svn-mergeinfo-push.sh b/t/t9160-git-svn-mergeinfo-push.sh
new file mode 100755
index 0000000..216f3d7
--- /dev/null
+++ b/t/t9160-git-svn-mergeinfo-push.sh
@@ -0,0 +1,104 @@
+#!/bin/sh
+#
+# Portions copyright (c) 2007, 2009 Sam Vilain
+# Portions copyright (c) 2011 Bryan Jacobs
+#
+
+test_description='git-svn svn mergeinfo propagation'
+
+. ./lib-git-svn.sh
+
+test_expect_success 'load svn dump' "
+ svnadmin load -q '$rawsvnrepo' \
+ < '$TEST_DIRECTORY/t9160/branches.dump' &&
+ git svn init --minimize-url -R svnmerge \
+ -T trunk -b branches '$svnrepo' &&
+ git svn fetch --all
+ "
+
+test_expect_success 'propagate merge information' '
+ git config svn.pushmergeinfo yes &&
+ git checkout svnb1 &&
+ git merge --no-ff svnb2 &&
+ git svn dcommit
+ '
+
+test_expect_success 'check svn:mergeinfo' '
+ mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb1)
+ test "$mergeinfo" = "/branches/svnb2:3,8"
+ '
+
+test_expect_success 'merge another branch' '
+ git merge --no-ff svnb3 &&
+ git svn dcommit
+ '
+
+test_expect_success 'check primary parent mergeinfo respected' '
+ mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb1)
+ test "$mergeinfo" = "/branches/svnb2:3,8
+/branches/svnb3:4,9"
+ '
+
+test_expect_success 'merge existing merge' '
+ git merge --no-ff svnb4 &&
+ git svn dcommit
+ '
+
+test_expect_success "check both parents' mergeinfo respected" '
+ mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb1)
+ test "$mergeinfo" = "/branches/svnb2:3,8
+/branches/svnb3:4,9
+/branches/svnb4:5-6,10-12
+/branches/svnb5:6,11"
+ '
+
+test_expect_success 'make further commits to branch' '
+ git checkout svnb2 &&
+ touch newb2file &&
+ git add newb2file &&
+ git commit -m "later b2 commit" &&
+ touch newb2file-2 &&
+ git add newb2file-2 &&
+ git commit -m "later b2 commit 2" &&
+ git svn dcommit
+ '
+
+test_expect_success 'second forward merge' '
+ git checkout svnb1 &&
+ git merge --no-ff svnb2 &&
+ git svn dcommit
+ '
+
+test_expect_success 'check new mergeinfo added' '
+ mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb1)
+ test "$mergeinfo" = "/branches/svnb2:3,8,16-17
+/branches/svnb3:4,9
+/branches/svnb4:5-6,10-12
+/branches/svnb5:6,11"
+ '
+
+test_expect_success 'reintegration merge' '
+ git checkout svnb4 &&
+ git merge --no-ff svnb1 &&
+ git svn dcommit
+ '
+
+test_expect_success 'check reintegration mergeinfo' '
+ mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb4)
+ test "$mergeinfo" = "/branches/svnb1:2-4,7-9,13-18
+/branches/svnb2:3,8,16-17
+/branches/svnb3:4,9
+/branches/svnb4:5-6,10-12
+/branches/svnb5:6,11"
+ '
+
+test_expect_success 'dcommit a merge at the top of a stack' '
+ git checkout svnb1 &&
+ touch anotherfile &&
+ git add anotherfile &&
+ git commit -m "a commit" &&
+ git merge svnb4 &&
+ git svn dcommit
+ '
+
+test_done
diff --git a/t/t9160/branches.dump b/t/t9160/branches.dump
new file mode 100644
index 0000000..e61c3e7
--- /dev/null
+++ b/t/t9160/branches.dump
@@ -0,0 +1,374 @@
+SVN-fs-dump-format-version: 2
+
+UUID: 1ef08553-f2d1-45df-b38c-19af6b7c926d
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2011-09-02T16:08:02.941384Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 114
+Content-length: 114
+
+K 7
+svn:log
+V 12
+Base commit
+
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:08:27.205062Z
+PROPS-END
+
+Node-path: branches
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 2
+Prop-content-length: 121
+Content-length: 121
+
+K 7
+svn:log
+V 19
+Create branch svnb1
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:09:43.628137Z
+PROPS-END
+
+Node-path: branches/svnb1
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Revision-number: 3
+Prop-content-length: 121
+Content-length: 121
+
+K 7
+svn:log
+V 19
+Create branch svnb2
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:09:46.339930Z
+PROPS-END
+
+Node-path: branches/svnb2
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Revision-number: 4
+Prop-content-length: 121
+Content-length: 121
+
+K 7
+svn:log
+V 19
+Create branch svnb3
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:09:49.394515Z
+PROPS-END
+
+Node-path: branches/svnb3
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Revision-number: 5
+Prop-content-length: 121
+Content-length: 121
+
+K 7
+svn:log
+V 19
+Create branch svnb4
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:09:54.114607Z
+PROPS-END
+
+Node-path: branches/svnb4
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Revision-number: 6
+Prop-content-length: 121
+Content-length: 121
+
+K 7
+svn:log
+V 19
+Create branch svnb5
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:09:58.602623Z
+PROPS-END
+
+Node-path: branches/svnb5
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Revision-number: 7
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 9
+b1 commit
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:10:20.292369Z
+PROPS-END
+
+Node-path: branches/svnb1/b1file
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 8
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 9
+b2 commit
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:10:38.429199Z
+PROPS-END
+
+Node-path: branches/svnb2/b2file
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 9
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 9
+b3 commit
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:10:52.843023Z
+PROPS-END
+
+Node-path: branches/svnb3/b3file
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 10
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 9
+b4 commit
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:11:17.489870Z
+PROPS-END
+
+Node-path: branches/svnb4/b4file
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 11
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 9
+b5 commit
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:11:32.277404Z
+PROPS-END
+
+Node-path: branches/svnb5/b5file
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 12
+Prop-content-length: 192
+Content-length: 192
+
+K 7
+svn:log
+V 90
+Merge remote-tracking branch 'svnb5' into HEAD
+
+* svnb5:
+ b5 commit
+ Create branch svnb5
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:11:54.274722Z
+PROPS-END
+
+Node-path: branches/svnb4
+Node-kind: dir
+Node-action: change
+Prop-content-length: 56
+Content-length: 56
+
+K 13
+svn:mergeinfo
+V 21
+/branches/svnb5:6,11
+
+PROPS-END
+
+
+Node-path: branches/svnb4/b5file
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
+Content-length: 10
+
+PROPS-END
+
+
--
1.7.6.1.5.g8ba83.dirty
^ permalink raw reply related
* Re: Git without morning coffee
From: Junio C Hamano @ 2011-09-07 17:35 UTC (permalink / raw)
To: Michael J Gruber; +Cc: Git Mailing List
In-Reply-To: <7vehzs47we.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> Michael J Gruber <git@drmicha.warpmail.net> writes:
>
>> git merge ":/Merge branch 'jk/generation-numbers' into pu"
>> fatal: ':/Merge branch 'jk/generation-numbers' into pu' does not point
>> to a commit
>> # Huh?
>
> Interesting.
This is because 1c7b76b (Build in merge, 2008-07-07) grabs the name of the
commit to be merged using peel_to_type(), which was defined in 8177631
(expose a helper function peel_to_type()., 2007-12-24) in terms of
get_sha1_1(). It understands $commit~$n, $commit^$n and $ref@{$nth}, but
does not understand :/$str, $treeish:$path, and :$stage:$path.
^ permalink raw reply
* Re: [PATCH v2 2/5] sha1_file: remove a buggy value setting
From: wanghui @ 2011-09-07 9:55 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, tali
In-Reply-To: <7vpqjdab76.fsf@alter.siamese.dyndns.org>
Junio C Hamano wrote:
> Wang Hui <Hui.Wang@windriver.com> writes:
>
>
>> From: Hui Wang <Hui.Wang@windriver.com>
>>
>> The ent->base[] is a character array, it has pfxlen characters from
>> position 0 to (pfxlen-1) to contain an alt object dir name, the
>> position pfxlen should be the string terminating character '\0' and
>> is deliberately set to '\0' at the previous code line. The position
>> (pfxlen+1) is given to ent->name.
>>
>
> Correct. Do you understand why?
>
> We temporarily NUL terminate the ent->base[] so that we can give it to
> is_directory() to see if that is a directory, but the invariants for a
> alternate_object_database instance after it is properly initialized by
> this function are to have:
>
> - the directory name followed by a slash in the base[] array;
> - the name pointer pointing at one byte beyond the slash;
> - name[2] filled with a slash; and
> - name[41] terminated with NUL.
>
> Later, has_loose_object_nonlocal() calls fill_sha1_path() with the name
> pointer to fill name[0..1, 3..40] with the hexadecimal representation of
> the object name, which would result in base[] array to have the pathname
> for a loose object found in that alternate. The same thing happens in
> open_sha1_file() to read from a loose object in an alternate.
>
> And you are breaking one of the above invariants by removing that slash
> after the directory name. These callers of fill_sha1_path() will see the
> directory name, your NUL, two hex, slash, and 38 hex in base[].
>
>
Understand now, thanks for your explanation.
> How would the code even work with your patch?
>
>
>
^ permalink raw reply
* Re: Git without morning coffee
From: Michael Witten @ 2011-09-07 17:23 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Michael J Gruber, Git Mailing List
In-Reply-To: <7vehzs47we.fsf@alter.siamese.dyndns.org>
[Sorry for the repeat, Junio]
On Wed, Sep 7, 2011 at 16:46, Junio C Hamano <gitster@pobox.com> wrote:
> Michael J Gruber <git@drmicha.warpmail.net> writes:
>
>> git merge ":/Merge branch 'jk/generation-numbers' into pu"
>> fatal: ':/Merge branch 'jk/generation-numbers' into pu' does not point
>> to a commit
>> # Huh?
>
> Interesting.
>
>> git merge $(git rev-parse ":/Merge branch 'jk/generation-numbers' into pu")
>> error: addinfo_cache failed for path 't/t7810-grep.sh'
>> Performing inexact rename detection: 100% (91476/91476), done.
>> error: addinfo_cache failed for path 't/t7810-grep.sh'
>
> Smells like another case where merge-recursive is looking at the work tree
> when it shouldn't inside an inner merge or something.
>
>> I mean, I'm merging a commit from origin/pu to origin/next when the
>> latter is basically contained in the former (except for some merge
>> commits).
>
> This falls into the "side note" category, but these days 'next' and 'pu'
> do not share any history beyond the tip of 'master'. Every time I update
> the 'pu' branch, it is rebuilt directly on top of 'master' from scratch by
> merging the topics in 'next' (and at this point I make sure its tree
> matches that of 'next') and then merging remaining topics on top of the
> result. A topic often goes through multiple iterations of fix-ups while in
> 'next', and these fix-ups result in multiple incremental merges of the
> same topic into 'next'; I do not want to see an incorrect merge when such
> a topic is merged in a single-step into 'master', and it is one way to
> ensure the health of the merge fixup machinery (including the rerere
> database) to attempt from-scratch-the-whole-topic-at-once merges and
> verify the result.
>
> The merge you attempted will have a lot of "the history leading to the
> current commit added/modified in a certain way and the history being
> merged did the same modification independently" kind of conflicts that
> should resolve to no-op.
> --
> 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
>
I think it would be great if at some point you could write a detailed
tutorial of how you maintain git (using example topics, example patch
series and pull requests, and follow-along command sequences, etc.).
Most importantly, it would be nice to see an explicit description of
the maintenance properties you are trying to achieve with your
workflow.
^ permalink raw reply
* [PATCH v3 1/1] sha1_file: normalize alt_odb path before comparing and storing
From: Wang Hui @ 2011-09-07 10:37 UTC (permalink / raw)
To: gitster, git, tali
In-Reply-To: <1315391867-31277-1-git-send-email-Hui.Wang@windriver.com>
From: Hui Wang <Hui.Wang@windriver.com>
When it needs to compare and add an alt object path to the
alt_odb_list, we normalize this path first since comparing normalized
path is easy to get correct result.
Use strbuf to replace some string operations, since it is cleaner and
safer.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Hui Wang <Hui.Wang@windriver.com>
---
sha1_file.c | 34 +++++++++++++++++-----------------
1 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/sha1_file.c b/sha1_file.c
index f7c3408..fa2484b 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -248,27 +248,27 @@ static int link_alt_odb_entry(const char * entry, int len, const char * relative
const char *objdir = get_object_directory();
struct alternate_object_database *ent;
struct alternate_object_database *alt;
- /* 43 = 40-byte + 2 '/' + terminating NUL */
- int pfxlen = len;
- int entlen = pfxlen + 43;
- int base_len = -1;
+ int pfxlen, entlen;
+ struct strbuf pathbuf = STRBUF_INIT;
if (!is_absolute_path(entry) && relative_base) {
- /* Relative alt-odb */
- if (base_len < 0)
- base_len = strlen(relative_base) + 1;
- entlen += base_len;
- pfxlen += base_len;
+ strbuf_addstr(&pathbuf, real_path(relative_base));
+ strbuf_addch(&pathbuf, '/');
}
- ent = xmalloc(sizeof(*ent) + entlen);
+ strbuf_add(&pathbuf, entry, len);
- if (!is_absolute_path(entry) && relative_base) {
- memcpy(ent->base, relative_base, base_len - 1);
- ent->base[base_len - 1] = '/';
- memcpy(ent->base + base_len, entry, len);
- }
- else
- memcpy(ent->base, entry, pfxlen);
+ normalize_path_copy(pathbuf.buf, pathbuf.buf);
+
+ pfxlen = strlen(pathbuf.buf);
+
+ /* Drop the last '/' from path can make memcmp more accurate */
+ if (pathbuf.buf[pfxlen-1] == '/')
+ pfxlen -= 1;
+
+ entlen = pfxlen + 43; /* '/' + 2 hex + '/' + 38 hex + NUL */
+ ent = xmalloc(sizeof(*ent) + entlen);
+ memcpy(ent->base, pathbuf.buf, pfxlen);
+ strbuf_release(&pathbuf);
ent->name = ent->base + pfxlen + 1;
ent->base[pfxlen + 3] = '/';
--
1.6.3.1
^ permalink raw reply related
* Re: [PATCH v2 1/5] sha1_file cleanup: remove redundant variable check
From: wanghui @ 2011-09-07 10:24 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, tali
In-Reply-To: <7vaaaha9p2.fsf@alter.siamese.dyndns.org>
Junio C Hamano wrote:
> Wang Hui <Hui.Wang@windriver.com> writes:
>
>
>> From: Hui Wang <Hui.Wang@windriver.com>
>>
>> This variable check is always true, so it is redundant and need to be
>> removed.
>>
>> We can't remove the init value for this variable, since removing
>> it will introduce building warning:
>> 'base_len' may be used uninitialized in this function.
>>
>
> If we are into cleaning things up, we should instead notice and say "yuck"
> to the repeated "is entry is absolute and relative base is given" check.
>
> Wouldn't something like this makes things easier to follow and also avoids
> the "when does the path normalized and made absolute" issue?
>
> Completely untested and I may have off-by-one errors and such, but I think
> you would get the idea...
>
>
Yes, i got the idea, and some errors are pointed out below. I will
prepare a V3 patch basing on it.
> sha1_file.c | 29 ++++++++++++-----------------
> 1 files changed, 12 insertions(+), 17 deletions(-)
>
> diff --git a/sha1_file.c b/sha1_file.c
> index e002056..26aa3be 100644
> --- a/sha1_file.c
> +++ b/sha1_file.c
> @@ -248,27 +248,22 @@ static int link_alt_odb_entry(const char * entry, int len, const char * relative
> const char *objdir = get_object_directory();
> struct alternate_object_database *ent;
> struct alternate_object_database *alt;
> - /* 43 = 40-byte + 2 '/' + terminating NUL */
> - int pfxlen = len;
> - int entlen = pfxlen + 43;
> - int base_len = -1;
> + int pfxlen, entlen;
> + struct strbuf pathbuf = STRBUF_INIT;
>
> if (!is_absolute_path(entry) && relative_base) {
> - /* Relative alt-odb */
> - if (base_len < 0)
> - base_len = strlen(relative_base) + 1;
> - entlen += base_len;
> - pfxlen += base_len;
> + strbuf_addstr(&pathbuf, relative_base);
>
s/relative_base/real_path(relative_base)/ is better, since
normalize_path_copy is not good at handle relative path. e.g. ".
./objects/../../test2/objects" will be normalized to "objects"
> + strbuf_addch(&pathbuf, '/');
> }
> - ent = xmalloc(sizeof(*ent) + entlen);
> + strbuf_add(&pathbuf, entry, len);
> + normalize_path_copy(pathbuf.buf, pathbuf.buf);
>
if pathbuf.buf[strlen(pathbuf.buf)] is '/', remove it. this can avoid to
get a wrong result when comparing "/a/b" with "/a/b/".
> + strbuf_setlen(&pathbuf, strlen(pathbuf.buf));
>
above line can be removed, since we will release pathbuf soon.
>
> - if (!is_absolute_path(entry) && relative_base) {
> - memcpy(ent->base, relative_base, base_len - 1);
> - ent->base[base_len - 1] = '/';
> - memcpy(ent->base + base_len, entry, len);
> - }
> - else
> - memcpy(ent->base, entry, pfxlen);
> + pfxlen = pathbuf.len;
> + entlen = pfxlen + 43; /* '/' + 2 hex + '/' + 38 hex + NUL */
> + ent = xmalloc(sizeof(*ent) + entlen);
> + memcpy(ent->base, pathbuf.buf, pfxlen);
> + strbuf_release(&pathbuf);
>
> ent->name = ent->base + pfxlen + 1;
> ent->base[pfxlen + 3] = '/';
>
>
^ permalink raw reply
* [PATCH v3 0/1] sha1_file: normalize alt_odb path before comparing and storing
From: Wang Hui @ 2011-09-07 10:37 UTC (permalink / raw)
To: gitster, git, tali
Hi Junio & Martin,
In the V3, i prepared a patch basing on Junio's suggestion. If this patch can
pass review and be merged to upstream. What about the last two patches in the
V2 (remove relative alternates only possible at current repos limitation), do
you think it is safe to pick up these two patches?
Hui Wang (1):
sha1_file: normalize alt_odb path before comparing and storing
sha1_file.c | 34 +++++++++++++++++-----------------
1 files changed, 17 insertions(+), 17 deletions(-)
^ permalink raw reply
* Re: The imporantance of including http credential caching in 1.7.7
From: Kyle Neath @ 2011-09-07 8:11 UTC (permalink / raw)
To: Sverre Rabbelier; +Cc: Junio C Hamano, git
In-Reply-To: <CAGdFq_h3KNuGuhhY2Zv-dHWqAY4Wq3HHBGh2f53rWzDT9PzSgQ@mail.gmail.com>
On Wed, Sep 7, 2011 at 12:46 AM, Sverre Rabbelier <srabbelier@gmail.com> wrote:
> Junio mentioned in WC that he wants to see some feedback on it's
> usage, perhaps that you can help provide this by providing a git
> patched with this functionality to some of your users and see how they
> respond?
Perhaps this is where things get complicated. Due to the nature of the people
I'm discussing (people afraid of SSH keys), getting them to run a custom
version of git is pretty far out of the question. Peff alluded to this in his
reply.
I think the best evidence I can provide is in context of GitHub for Mac.
GitHub for Mac defaults to Smart HTTP, with the credentials cached in OSX's
Keychain. Effectively, it functions as a patched git with credential caching.
Two months after shipping, we have around 20,000 people that use the
application regularly. In that time, we've gotten a ton of positive feedback.
So there is a great number of people interested in a git client that uses
Smart HTTP. One of the bigger complaints we get is that people constantly have
to enter their username & password if they choose to drop to the command line.
Of course, this is all fuzzy data since it's not really comparable with git
core. But it's the only data I have.
Then again, perhaps the fact that we spent development time hacking around
git's limitation is a data point in itself. Git GUI developers are spending
development time to fill a hole in git core.
Kyle
^ permalink raw reply
* Add interactive patch menu help scrolled away if hunk is long
From: Sergio Callegari @ 2011-09-07 12:43 UTC (permalink / raw)
To: git
Hi,
when using git add -i, selecting the patch functionality, git shows the
Stage this hunk [y,n,q,a,d,/,K,j,J,g,s,e,?]?
question for each hunk.
Apparently the '?' entry meant to show help is not very useful when the hunk is
long since the help is scrolled away as the hunk is reprinted.
Probably it would be better not to reprint the hunk when '?' is selected.
Sergio
^ permalink raw reply
* Re: [ANNOUNCE] GitTogether 2011 - Oct 24th/25th
From: Scott Chacon @ 2011-09-07 17:11 UTC (permalink / raw)
To: Shawn Pearce; +Cc: git
In-Reply-To: <CAJo=hJu48DiVUDexuWJpVgq__zVTfO1Xz=AgfOz6wws00b2EaQ@mail.gmail.com>
Hey,
On Mon, Sep 5, 2011 at 12:56 PM, Shawn Pearce <spearce@spearce.org> wrote:
> Google is once again hosting a 2 day user/developer conference for Git
> users and developers to get together, share experiences, and hack on
> interesting features. This event will be held October 24th and 25th at
> Google's headquarters in Mountain View, CA.
>
> More details along with sign-up (as space is limited) can be found on the wiki:
>
> https://git.wiki.kernel.org/index.php/GitTogether11
It's been like 2 days and we're already overflowing. I've also
already heard people say they didn't sign up because it was full.
This is unacceptable. I want to drink with all of you guys.
Shawn, if you can't get a bigger venue at Google, we'll rent a meeting
space either at the hotel that most of the mentors are staying at or a
nearby one. I'm looking into spaces that will accomodate closer to 50
people and will serve us beer. :)
So, everybody that wants to come just sign up and we'll make sure
there is room for everyone. Also, if any regular Git contributors
need help with flights or lodging, please let me know and we'll see
what we can do to help.
Thanks,
Scott
^ permalink raw reply
* Re: The imporantance of including http credential caching in 1.7.7
From: Sverre Rabbelier @ 2011-09-07 7:46 UTC (permalink / raw)
To: Kyle Neath, Junio C Hamano; +Cc: git
In-Reply-To: <CAFcyEthzW1AY4uXgpsVxjyWCDXAJ6=GdWGqLFO6Acm1ovJJVaw@mail.gmail.com>
Heya,
On Wed, Sep 7, 2011 at 07:33, Kyle Neath <kneath@gmail.com> wrote:
> I'll summarize with a graph of my opinion of where git's potential for
> adoption lies:
>
> ------------------------------------------------------------------------------
> OPPORTUNITY FOR GIT ADOPTION ACCORDING TO KYLE NEATH
>
> Caching of http credentials
> |
> [=====================================================================||=====]
> |
> Everything else in the universe
>
> ------------------------------------------------------------------------------
I, personally, find the graph very convincing :).
Junio mentioned in WC that he wants to see some feedback on it's
usage, perhaps that you can help provide this by providing a git
patched with this functionality to some of your users and see how they
respond?
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* Re: [PATCH v2] date.c: Support iso8601 timezone formats
From: Junio C Hamano @ 2011-09-07 17:00 UTC (permalink / raw)
To: Haitao Li; +Cc: git, Jeff King
In-Reply-To: <1315374407-30828-1-git-send-email-lihaitao@gmail.com>
Haitao Li <lihaitao@gmail.com> writes:
> diff --git a/date.c b/date.c
> index 896fbb4..f970ea8 100644
> --- a/date.c
> +++ b/date.c
> @@ -556,15 +556,35 @@ static int match_tz(const char *date, int *offp)
> int min, hour;
> int n = end - date - 1;
>
> - min = offset % 100;
> - hour = offset / 100;
> + /*
> + * ISO8601:2004(E) allows time zone designator been separated
> + * by a clone in the extended format
> + */
> + if (*end == ':') {
> + if (isdigit(end[1])) {
> + hour = offset;
> + min = strtoul(end+1, &end, 10);
> + } else {
> + /* Mark as invalid */
> + n = -1;
> + }
> + } else {
> + /* Only hours specified */
That comment belongs to inside the following if() {...}.
> + if (n == 1 || n == 2) {
... i.e. here.
> + hour = offset;
> + min = 0;
> + } else {
> + hour = offset / 100;
> + min = offset % 100;
> + }
> + }
>
> /*
> + * Don't accept any random crap.. We might want to check that
> + * the minutes are divisible by 15 or something too. (Offset of
> + * Kathmandu, Nepal is UTC+5:45)
> */
> - if (min < 60 && n > 2) {
> + if (n > 0 && min < 60 && hour < 25) {
What is this "hour < 25" about? Aren't we talking about the UTC offset
value that come after the [-+] sign?
I do not mind adding a new check, but I do mind if it adds a check with
not much value. Even at Pacific/Kiritimati, the offset is 14; the new
check seems a bit too lenient.
> offset = hour*60+min;
> if (*date == '-')
> offset = -offset;
> diff --git a/t/t0006-date.sh b/t/t0006-date.sh
> index f87abb5..5235b7a 100755
> --- a/t/t0006-date.sh
> +++ b/t/t0006-date.sh
> @@ -40,6 +40,11 @@ check_parse 2008-02 bad
> check_parse 2008-02-14 bad
> check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 +0000'
> check_parse '2008-02-14 20:30:45 -0500' '2008-02-14 20:30:45 -0500'
> +check_parse '2008-02-14 20:30:45 -0015' '2008-02-14 20:30:45 -0015'
> +check_parse '2008-02-14 20:30:45 -5' '2008-02-14 20:30:45 -0500'
> +check_parse '2008-02-14 20:30:45 -05' '2008-02-14 20:30:45 -0500'
> +check_parse '2008-02-14 20:30:45 -:30' '2008-02-14 20:30:45 +0000'
> +check_parse '2008-02-14 20:30:45 -05:00' '2008-02-14 20:30:45 -0500'
> check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 -0500' EST5
>
> check_approxidate() {
^ permalink raw reply
* Re: [ANNOUNCE] Git 1.7.6.2
From: Sverre Rabbelier @ 2011-09-07 11:24 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git List
In-Reply-To: <7vsjo84mx3.fsf@alter.siamese.dyndns.org>
Heya,
On Wed, Sep 7, 2011 at 13:22, Junio C Hamano <gitster@pobox.com> wrote:
>> That's interesting, how did revert a merge commit?
>
> Does "git revert --help" lack the description?
It warns that "As a result, later merges will only bring in tree
changes introduced by commits that are not ancestors of the previously
reverted merge." How would you later re-merge the series when the
problems it has are fixed though?
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* Re: git-rebase skips automatically no more needed commits
From: Michael J Gruber @ 2011-09-07 13:19 UTC (permalink / raw)
To: Francis Moreau; +Cc: Junio C Hamano, git
In-Reply-To: <CAC9WiBjrfJeJ854dkJMPwRSwuujRsYLnAd7QX7C_oU8_FdOvQA@mail.gmail.com>
Francis Moreau venit, vidit, dixit 06.09.2011 21:28:
> Hello Junio,
>
> On Tue, Sep 6, 2011 at 7:09 PM, Junio C Hamano <gitster@pobox.com> wrote:
>>
>> Our assumption has always been that it is a notable event that a patch
>> that does not get filtered with internal "git cherry" (which culls patches
>> that are textually identical to those that are already merged to the
>> history you are rebasing onto) becomes totally unneeded and is safe to ask
>> for human confirmation in the form of "rebase --skip" than to ignore it
>> and give potentially incorrect result silently.
>
> Ok then I think this "git cherry" filtering is not working in my case
> since it seems to me that commit that I cherry-picked are not
> filtered, please see below.
>
>>
>> Obviously you do not find it a notable event for some reason. We would
>> need to understand why, and if the reason is sensible, it _might_ make
>> sense to allow a user to say "git rebase --ignore-merged" or something
>> when starting the rebase.
>
> My use case is the following: I'm maintaining a branch from an
> upstream project (the kernel one). While the upstream project follows
> its development cycle (including some fixes), my branch is stuck. I
> sometime want to includes (or rather backport) some commits that
> happened later in the development cycle. To do that I use "git
> cherry-pick".
>
> After some period, I'm allowed to rebase to a more recent commit from
> the upstream project and this rebase 'cancel' the previous 'git
> cherry-pick' I did. But for some reasons, git telling me "nothing
> added to commit ...", which is expected in my case, well I think,
> hence my question.
>
> Thanks.
Unless you had to resolve a conflict when cherry-picking, the picked
commit should be patch-equivalent to the original one, and thus dropped
by rebase automatically.
How do the two patches compare:
git show $picked >a
git show $original >b
git patch-id <a
git patch-id <b
git diff --no-index a b
Michael
^ permalink raw reply
* [PATCH] git-update-ref documentation: --no-deref can be used together with -d
From: Bernhard R. Link @ 2011-09-07 16:06 UTC (permalink / raw)
To: git
---
Documentation/git-update-ref.txt | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt
index d377a35..5da3691 100644
--- a/Documentation/git-update-ref.txt
+++ b/Documentation/git-update-ref.txt
@@ -8,7 +8,7 @@ git-update-ref - Update the object name stored in a ref safely
SYNOPSIS
--------
[verse]
-'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] <ref> <newvalue> [<oldvalue>])
+'git update-ref' [-m <reason>] [--no-deref] (-d <ref> [<oldvalue>] | <ref> <newvalue> [<oldvalue>])
DESCRIPTION
-----------
--
1.7.2.5
^ permalink raw reply related
* Re: Git without morning coffee
From: Junio C Hamano @ 2011-09-07 16:46 UTC (permalink / raw)
To: Michael J Gruber; +Cc: Git Mailing List
In-Reply-To: <4E6721E3.7000207@drmicha.warpmail.net>
Michael J Gruber <git@drmicha.warpmail.net> writes:
> git merge ":/Merge branch 'jk/generation-numbers' into pu"
> fatal: ':/Merge branch 'jk/generation-numbers' into pu' does not point
> to a commit
> # Huh?
Interesting.
> git merge $(git rev-parse ":/Merge branch 'jk/generation-numbers' into pu")
> error: addinfo_cache failed for path 't/t7810-grep.sh'
> Performing inexact rename detection: 100% (91476/91476), done.
> error: addinfo_cache failed for path 't/t7810-grep.sh'
Smells like another case where merge-recursive is looking at the work tree
when it shouldn't inside an inner merge or something.
> I mean, I'm merging a commit from origin/pu to origin/next when the
> latter is basically contained in the former (except for some merge
> commits).
This falls into the "side note" category, but these days 'next' and 'pu'
do not share any history beyond the tip of 'master'. Every time I update
the 'pu' branch, it is rebuilt directly on top of 'master' from scratch by
merging the topics in 'next' (and at this point I make sure its tree
matches that of 'next') and then merging remaining topics on top of the
result. A topic often goes through multiple iterations of fix-ups while in
'next', and these fix-ups result in multiple incremental merges of the
same topic into 'next'; I do not want to see an incorrect merge when such
a topic is merged in a single-step into 'master', and it is one way to
ensure the health of the merge fixup machinery (including the rerere
database) to attempt from-scratch-the-whole-topic-at-once merges and
verify the result.
The merge you attempted will have a lot of "the history leading to the
current commit added/modified in a certain way and the history being
merged did the same modification independently" kind of conflicts that
should resolve to no-op.
^ permalink raw reply
* Re: [PATCH] git-svn: teach git-svn to populate svn:mergeinfo
From: Bryan Jacobs @ 2011-09-07 14:14 UTC (permalink / raw)
To: Eric Wong; +Cc: git, Sam Vilain
In-Reply-To: <20110906205750.GB12574@dcvr.yhbt.net>
On Tue, 6 Sep 2011 13:57:50 -0700
Eric Wong <normalperson@yhbt.net> wrote:
> Bryan Jacobs <bjacobs@woti.com> wrote:
> > +sub split_merge_info_range {
> > + my ($range) = @_;
> > + if ($range =~ /(\d+)-(\d+)/o) {
>
> No need for "/o" in regexps unless you have a (constant) variable
> expansion in there.
Okay, I'll take that out. I got into the habit of putting "optimize" on
all regexes without an explicitly dynamic variable on some earlier Perl
version.
> > +sub merge_commit_fail {
> > + my ($gs, $linear_refs, $d) = @_;
> > + #while (1) {
> > + # my $cs = shift @$linear_refs or last;
> > + # command_noisy(qw/cherry-pick/, $cs);
> > + #}
> > + #command_noisy(qw/cherry-pick -m/, '1', $d);
>
> Huh? If there's commented-out code, it must be explained or removed.
I think I did explain that in my earlier comments. I'm still not happy
with the recovery-from-aborted-commit-series handling. That commented
bit was my attempt.
The best suggestion so far is to prescan the commits to fail-fast. I
will do that in the next revision of the patch, just give me some time
to put it together.
> > + fatal "Aborted after failed dcommit of merge revision";
> > +}
>
> > +++ b/t/t9160-git-svn-mergeinfo-push.sh
> > @@ -0,0 +1,97 @@
> > +#!/bin/sh
> > +#
> > +# Copyright (c) 2007, 2009 Sam Vilain
>
> That should be: "Copyright (c) 2011 Brian Jacobs", correct?
Well, the file was copied from one bearing the Vilain copyright bit.
I'm not sure I entirely understand why it matters who holds the
individual copyrights if you have a collective license which is going to
be changed, but I can't just stick my own name on derived work - as the
setup code for that unit is.
> > +test_expect_success 'check svn:mergeinfo' '
> > + mergeinfo=$(svn_cmd propget svn:mergeinfo
> > "$svnrepo"/branches/svnb1)
> > + echo "$mergeinfo"
>
> No need to echo unless you're debugging a test, right?
>
Correct, leftover test-debugging cruft, will remove.
I will submit another revision shortly.
Bryan Jacobs
^ permalink raw reply
* [PATCH] RelNotes/1.7.7: minor fixes
From: Michael J Gruber @ 2011-09-07 11:54 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
---
Documentation/RelNotes/1.7.7.txt | 52 +++++++++++++++++++-------------------
1 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/Documentation/RelNotes/1.7.7.txt b/Documentation/RelNotes/1.7.7.txt
index d819956..6e83082 100644
--- a/Documentation/RelNotes/1.7.7.txt
+++ b/Documentation/RelNotes/1.7.7.txt
@@ -8,7 +8,7 @@ Updates since v1.7.6
* Interix, Cygwin and Minix ports got updated.
- * Various updates git-p4 (in contrib/), fast-import, and git-svn.
+ * Various updates to git-p4 (in contrib/), fast-import, and git-svn.
* Gitweb learned to read from /etc/gitweb-common.conf when it exists,
before reading from gitweb_config.perl or from /etc/gitweb.conf
@@ -20,7 +20,7 @@ Updates since v1.7.6
platforms with 64-bit long, which has been corrected.
* Git now recognizes loose objects written by other implementations that
- uses non-standard window size for zlib deflation (e.g. Agit running on
+ use a non-standard window size for zlib deflation (e.g. Agit running on
Android with 4kb window). We used to reject anything that was not
deflated with 32kb window.
@@ -28,59 +28,59 @@ Updates since v1.7.6
been improved, especially when a command that is not built-in was
involved.
- * "git am" learned to pass "--exclude=<path>" option through to underlying
+ * "git am" learned to pass the "--exclude=<path>" option through to underlying
"git apply".
- * You can now feed many empty lines before feeding a mbox file to
+ * You can now feed many empty lines before feeding an mbox file to
"git am".
* "git archive" can be told to pass the output to gzip compression and
produce "archive.tar.gz".
- * "git bisect" can be used in a bare repository (provided if the test
+ * "git bisect" can be used in a bare repository (provided that the test
you perform per each iteration does not need a working tree, of
course).
* The length of abbreviated object names in "git branch -v" output
- now honors core.abbrev configuration variable.
+ now honors the core.abbrev configuration variable.
* "git check-attr" can take relative paths from the command line.
- * "git check-attr" learned "--all" option to list the attributes for a
+ * "git check-attr" learned an "--all" option to list the attributes for a
given path.
* "git checkout" (both the code to update the files upon checking out a
- different branch, the code to checkout specific set of files) learned
+ different branch and the code to checkout a specific set of files) learned
to stream the data from object store when possible, without having to
- read the entire contents of a file in memory first. An earlier round
+ read the entire contents of a file into memory first. An earlier round
of this code that is not in any released version had a large leak but
now it has been plugged.
- * "git clone" can now take "--config key=value" option to set the
+ * "git clone" can now take a "--config key=value" option to set the
repository configuration options that affect the initial checkout.
* "git commit <paths>..." now lets you feed relative pathspecs that
- refer outside your current subdirectory.
+ refer to outside your current subdirectory.
- * "git diff --stat" learned --stat-count option to limit the output of
- diffstat report.
+ * "git diff --stat" learned a --stat-count option to limit the output of
+ a diffstat report.
- * "git diff" learned "--histogram" option, to use a different diff
+ * "git diff" learned a "--histogram" option to use a different diff
generation machinery stolen from jgit, which might give better
performance.
- * "git diff" had a wierd worst case behaviour that can be triggered
+ * "git diff" had a weird worst case behaviour that can be triggered
when comparing files with potentially many places that could match.
* "git fetch", "git push" and friends no longer show connection
- errors for addresses that couldn't be connected when at least one
+ errors for addresses that couldn't be connected to when at least one
address succeeds (this is arguably a regression but a deliberate
one).
- * "git grep" learned --break and --heading options, to let users mimic
- output format of "ack".
+ * "git grep" learned "--break" and "--heading" options, to let users mimic
+ the output format of "ack".
- * "git grep" learned "-W" option that shows wider context using the same
+ * "git grep" learned a "-W" option that shows wider context using the same
logic used by "git diff" to determine the hunk header.
* Invoking the low-level "git http-fetch" without "-a" option (which
@@ -91,25 +91,25 @@ Updates since v1.7.6
highlight grafted and replaced commits.
* "git rebase master topci" no longer spews usage hints after giving
- "fatal: no such branch: topci" error message.
+ the "fatal: no such branch: topci" error message.
* The recursive merge strategy implementation got a fairly large
- fixes for many corner cases that may rarely happen in real world
+ fix for many corner cases that may rarely happen in real world
projects (it has been verified that none of the 16000+ merges in
the Linux kernel history back to v2.6.12 is affected with the
corner case bugs this update fixes).
- * "git stash" learned --include-untracked option.
+ * "git stash" learned an "--include-untracked option".
* "git submodule update" used to stop at the first error updating a
submodule; it now goes on to update other submodules that can be
updated, and reports the ones with errors at the end.
- * "git push" can be told with --recurse-submodules=check option to
+ * "git push" can be told with the "--recurse-submodules=check" option to
refuse pushing of the supermodule, if any of its submodules'
commits hasn't been pushed out to their remotes.
- * "git upload-pack" and "git receive-pack" learned to pretend only a
+ * "git upload-pack" and "git receive-pack" learned to pretend that only a
subset of the refs exist in a repository. This may help a site to
put many tiny repositories into one repository (this would not be
useful for larger repositories as repacking would be problematic).
@@ -118,7 +118,7 @@ Updates since v1.7.6
that is more efficient in reading objects in packfiles.
* test scripts for gitweb tried to run even when CGI-related perl modules
- are not installed; it now exits early when they are unavailable.
+ are not installed; they now exit early when the latter are unavailable.
Also contains various documentation updates and minor miscellaneous
changes.
@@ -127,7 +127,7 @@ changes.
Fixes since v1.7.6
------------------
-Unless otherwise noted, all the fixes in 1.7.6.X maintenance track are
+Unless otherwise noted, all fixes in the 1.7.6.X maintenance track are
included in this release.
* The error reporting logic of "git am" when the command is fed a file
--
1.7.7.rc0.438.gcfb82
^ permalink raw reply related
* Re: git-rebase skips automatically no more needed commits
From: Junio C Hamano @ 2011-09-07 16:29 UTC (permalink / raw)
To: Francis Moreau; +Cc: Michael J Gruber, git
In-Reply-To: <CAC9WiBi_bkLNJZckq2fr3eb6ie+KVfauE_PyA3GcaW5Ga-isFw@mail.gmail.com>
Francis Moreau <francis.moro@gmail.com> writes:
> If I start the rebase process with : "git rebase -i -p master foo"
> then the filtering is happening. Here 'foo' has been created with
> v2.6.39 tag as start point and contains some patches cherry-picked
> from the upstream.
>
> However if I call git-rebase this way: "git rebase -i -p --onto master
> v2.6.39 foo", then it seems that no filtering is done.
>
> Is that expected ?
Because "rebase --onto A B C" has to be usable when commit A does not have
any ancestry relationship with the history between B and C, I wouldn't be
surprised if the command does not look at commits on the history that lead
to A that _might_ be related to the ones between B and C. It does not know
how far to dig from A and stop, and obviously you do not want to dig down
to the beginning of the history. "rebase A B" on the other hand can safely
stop digging the history back from A down to where the history leading to
B forked (i.e. merge base between A and B).
I do not know if "expected" is the right adjective; understandable---yes,
unsurprised---yes, justifiable--- I dunno.
^ 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