* Re: [PATCH 2/2] fetch/push: readd rsync support
From: Johannes Schindelin @ 2007-09-28 12:53 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Daniel Barkalow, git
In-Reply-To: <7v3awzqgqc.fsf@gitster.siamese.dyndns.org>
Hi,
On Fri, 28 Sep 2007, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > +/*
> > + * path is assumed to point to a buffer of PATH_MAX bytes, and
> > + * path + name_offset is expected to point to "refs/".
> > + */
> > +
> > +static int read_loose_refs(char *path, int name_offset, struct ref **tail)
> > +{
> > + DIR *dir = opendir(path);
> > + struct dirent *de;
> > + struct {
> > + struct dirent *entries;
> > + int nr, alloc;
> > + } list;
> > + int i, pathlen;
> > +
> > + if (!dir)
> > + return -1;
> > +
> > + memset (&list, 0, sizeof(list));
> > +
> > + while ((de = readdir(dir))) {
> > + if (de->d_name[0] == '.' && (de->d_name[1] == '\0' ||
> > + (de->d_name[1] == '.' &&
> > + de->d_name[2] == '\0')))
> > + continue;
> > + if (list.nr >= list.alloc) {
> > + list.alloc = alloc_nr(list.nr);
> > + list.entries = xrealloc(list.entries,
> > + list.alloc * sizeof(*de));
> > + }
>
> ALLOC_GROW() not applicable here?
>
> > + list.entries[list.nr++] = *de;
>
> Are you sure about this?
>
> The last paragraph in Rationale section, in
>
> http://www.opengroup.org/onlinepubs/000095399/basedefs/dirent.h.html
>
> suggests that the d_name[] member in struct dirent could be
> declared at the very end of the structure as length of 1 (the
> traditional trick to implement a flex-array); your assignment
> >from *de into entries[] would not work as expected on such an
> implementation.
>
> On Linux with glibc it appears bits/dirent.h defines dirent with
> "char d_name[256]", so you may not see a breakage there, though.
D'oh! You're completely right.
> You only use a list of strings (char **), don't you?
Originally, I wanted to use the d_type, too, but as I mentioned on IRC, it
is not reliable enough (shows DT_UNKNOWN _all_ the time here).
But yes, I'll redo it, using ALLOC_GROW.
> > ...
> > + if (fd < 0)
> > + continue;
> > + next = alloc_ref(strlen(path + name_offset));
>
> And as we discussed earlier you would need one more byte here ;-).
Well, not after my patch, which I thought of as (1/3), but then decided it
is good enough to be (1/1) until you shot it down...
Will fix.
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH] alloc_ref(): allow for trailing NUL
From: Pierre Habouzit @ 2007-09-28 13:13 UTC (permalink / raw)
To: Johannes Schindelin, Junio C Hamano, Daniel Barkalow, git
In-Reply-To: <20070928124102.GA21309@artemis.corp>
[-- Attachment #1: Type: text/plain, Size: 883 bytes --]
On Fri, Sep 28, 2007 at 12:41:02PM +0000, Pierre Habouzit wrote:
> void *xflexdupz(size_t offset, void *src, size_t len)
> {
> char *p = xmalloc(offset + len + 1);
> memset(p, 0, offset);
> memcpy(p + offset, src, len);
> p[offset + len] = '\0';
> return p;
> }
>
> Then alloc_ref could be a wrapper around:
> xflexdupz(offsetof(struct ref, name), ..., ...).
>
> Of course right now alloc_ref doesn't perform any kind of copy, but a
> grep -A1 will convince you that it's not a problem:
[...]
> remote.c: ret = alloc_ref(strlen(name) + 6);
> remote.c- sprintf(ret->name, "refs/%s", name);
okay forget about me, my proposal doesn't work, too bad :)
--
·O· Pierre Habouzit
··O madcoder@debian.org
OOO http://www.madism.org
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: git push (mis ?)behavior
From: Johannes Schindelin @ 2007-09-28 13:31 UTC (permalink / raw)
To: Steffen Prohaska; +Cc: Junio C Hamano, Pierre Habouzit, git
In-Reply-To: <9019207B-77A5-4595-8499-807DA0460EF0@zib.de>
Hi,
On Fri, 28 Sep 2007, Steffen Prohaska wrote:
> On Sep 28, 2007, at 9:07 AM, Junio C Hamano wrote:
>
> > Steffen Prohaska <prohaska@zib.de> writes:
> >
> > > When "remote.<name>.push" is set I'd expect "git push" to
> > > choose only the 'right' remote.<name>.push lines, that is
> > > the lines that have the current branch as the local ref.
> >
> > That would break the existing setup so it would not fly as a
> > default, although it could be added as an option.
>
> Do you mean 'not now' or never, i.e. not in git 1.6?
If it changes behaviour, and there might be people relying on the old
behaviour, we have to deprecate the old behaviour first. With a nice
warning so that people have a chance to adapt their setups. And then,
after a decent grace period, we can change it.
> What does 'break the existing setup' means? Pushing all branches that
> are configured in "remote.<name>.push" could be done by "git push
> <name>". This would be in the line with the idea that "git push" should
> only operate on the current branch and operations involving other local
> refs should be explicitly stated.
People have scripts and aliases to help them go through the day. If one
of those scripts or aliases stop working, that is called "break the
existing setup". ;-)
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH] quiltimport: Skip non-existent patches
From: Geert Uytterhoeven @ 2007-09-28 14:06 UTC (permalink / raw)
To: Dan Nicholson; +Cc: git
In-Reply-To: <1190925059-5233-1-git-send-email-dbn.lists@gmail.com>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1548 bytes --]
On Thu, 27 Sep 2007, Dan Nicholson wrote:
> When quiltimport encounters a non-existent patch in the series file,
> just skip to the next patch. This matches the behavior of quilt.
>
> Signed-off-by: Dan Nicholson <dbn.lists@gmail.com>
Acked-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
> ---
> git-quiltimport.sh | 4 ++++
> 1 files changed, 4 insertions(+), 0 deletions(-)
>
> diff --git a/git-quiltimport.sh b/git-quiltimport.sh
> index 74a54d5..880c81d 100755
> --- a/git-quiltimport.sh
> +++ b/git-quiltimport.sh
> @@ -71,6 +71,10 @@ commit=$(git rev-parse HEAD)
>
> mkdir $tmp_dir || exit 2
> for patch_name in $(grep -v '^#' < "$QUILT_PATCHES/series" ); do
> + if ! [ -f "$QUILT_PATCHES/$patch_name" ] ; then
> + echo "$patch_name doesn't exist. Skipping."
> + continue
> + fi
> echo $patch_name
> git mailinfo "$tmp_msg" "$tmp_patch" \
> <"$QUILT_PATCHES/$patch_name" >"$tmp_info" || exit 3
> --
> 1.5.3.2
With kind regards,
Geert Uytterhoeven
Software Architect
Sony Network and Software Technology Center Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium
Phone: +32 (0)2 700 8453
Fax: +32 (0)2 700 8622
E-mail: Geert.Uytterhoeven@sonycom.com
Internet: http://www.sony-europe.com/
Sony Network and Software Technology Center Europe
A division of Sony Service Centre (Europe) N.V.
Registered office: Technologielaan 7 · B-1840 Londerzeel · Belgium
VAT BE 0413.825.160 · RPR Brussels
Fortis Bank Zaventem · Swift GEBABEBB08A · IBAN BE39001382358619
^ permalink raw reply
* Re: [PATCH] Add a --dateformat= option to git-for-each-ref
From: Andy Parkins @ 2007-09-28 14:15 UTC (permalink / raw)
To: git; +Cc: Jeff King
In-Reply-To: <20070926125811.GC13739@coredump.intra.peff.net>
On Wednesday 2007 September 26, Jeff King wrote:
> would be more flexible. Although perhaps that is a bit too unlikely to
> be concerned with implementing, giving options to substitutions seems
> like a sane way to implement these sorts of things (e.g.,
> "%(objectsize:human)", "%(parent:1)", etc).
I'd thought about doing it like that, but imagined that there would objections
that it was overcomplicating git-for-each-ref. As you think that's
acceptable, I'll do it.
> Surely this same code exists elsewhere, and could be easily factored out
> into a parse_date_type function.
It was. It was also in revisions.c.
A patch series that implements both your requested changes to follow.
Andy
--
Dr Andy Parkins, M Eng (hons), MIET
andyparkins@gmail.com
^ permalink raw reply
* [PATCH 1/4] Add parse_date_format() convenience function for converting a format string to an enum date_mode
From: Andy Parkins @ 2007-09-28 14:17 UTC (permalink / raw)
To: git
In-Reply-To: <200709281516.05438.andyparkins@gmail.com>
parse_date_format() is passed a string that is compared against a
pre-defined list and converted to an enum date_format. The table is as
follows:
- "relative" => DATE_RELATIVE
- "iso8601" or "iso" => DATE_ISO8601
- "rfc2822" => DATE_RFC2822
- "short" => DATE_SHORT
- "local" => DATE_LOCAL
- "default" => DATE_NORMAL
In the event that none of these strings is found, the function die()s.
Signed-off-by: Andy Parkins <andyparkins@gmail.com>
---
cache.h | 1 +
date.c | 20 ++++++++++++++++++++
2 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/cache.h b/cache.h
index 8246500..5587f7e 100644
--- a/cache.h
+++ b/cache.h
@@ -432,6 +432,7 @@ const char *show_date(unsigned long time, int timezone, enum date_mode mode);
int parse_date(const char *date, char *buf, int bufsize);
void datestamp(char *buf, int bufsize);
unsigned long approxidate(const char *);
+enum date_mode parse_date_format(const char *format);
extern const char *git_author_info(int);
extern const char *git_committer_info(int);
diff --git a/date.c b/date.c
index 93bef6e..8f70500 100644
--- a/date.c
+++ b/date.c
@@ -584,6 +584,26 @@ int parse_date(const char *date, char *result, int maxlen)
return date_string(then, offset, result, maxlen);
}
+enum date_mode parse_date_format(const char *format)
+{
+ if (!strcmp(format, "relative"))
+ return DATE_RELATIVE;
+ else if (!strcmp(format, "iso8601") ||
+ !strcmp(format, "iso"))
+ return DATE_ISO8601;
+ else if (!strcmp(format, "rfc2822") ||
+ !strcmp(format, "rfc"))
+ return DATE_RFC2822;
+ else if (!strcmp(format, "short"))
+ return DATE_SHORT;
+ else if (!strcmp(format, "local"))
+ return DATE_LOCAL;
+ else if (!strcmp(format, "default"))
+ return DATE_NORMAL;
+ else
+ die("unknown date format %s", format);
+}
+
void datestamp(char *buf, int bufsize)
{
time_t now;
--
1.5.3.2.105.gf47f2-dirty
^ permalink raw reply related
* [PATCH 3/4] Make for-each-ref allow atom names like "<name>:<something>"
From: Andy Parkins @ 2007-09-28 14:17 UTC (permalink / raw)
To: git
In-Reply-To: <200709281516.05438.andyparkins@gmail.com>
In anticipation of supplying a per-field date format specifier, this
patch makes parse_atom() in builtin-for-each-ref.c allow atoms that have
a valid atom name (as determined by the valid_atom[] table) followed by
a colon, followed by an arbitrary string.
The arbitrary string is where the format for the atom will be specified.
Note, if different formats are specified for the same atom, multiple
entries will be made in the used_atoms table to allow them to be
distinguished by the grab_XXXX() functions.
Signed-off-by: Andy Parkins <andyparkins@gmail.com>
---
builtin-for-each-ref.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c
index 0afa1c5..3280516 100644
--- a/builtin-for-each-ref.c
+++ b/builtin-for-each-ref.c
@@ -106,7 +106,13 @@ static int parse_atom(const char *atom, const char *ep)
/* Is the atom a valid one? */
for (i = 0; i < ARRAY_SIZE(valid_atom); i++) {
int len = strlen(valid_atom[i].name);
- if (len == ep - sp && !memcmp(valid_atom[i].name, sp, len))
+ /* If the atom name has a colon, strip it and everything after
+ * it off - it specifies the format for this entry, and
+ * shouldn't be used for checking against the valid_atom table */
+ const char *formatp = strrchr(sp, ':' );
+ if (formatp == NULL )
+ formatp = ep;
+ if (len == formatp - sp && !memcmp(valid_atom[i].name, sp, len))
break;
}
--
1.5.3.2.105.gf47f2-dirty
^ permalink raw reply related
* [PATCH 2/4] Use parse_date_format() in revisions.c to parse the --date parameter
From: Andy Parkins @ 2007-09-28 14:17 UTC (permalink / raw)
To: git
In-Reply-To: <200709281516.05438.andyparkins@gmail.com>
The --date parameter was previously handled in revisions.c with a list
of if(strcmp()) calls; now parse_date_format() is called instead.
Signed-off-by: Andy Parkins <andyparkins@gmail.com>
---
revision.c | 17 +----------------
1 files changed, 1 insertions(+), 16 deletions(-)
diff --git a/revision.c b/revision.c
index 33d092c..75cd0c6 100644
--- a/revision.c
+++ b/revision.c
@@ -1134,22 +1134,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
continue;
}
if (!strncmp(arg, "--date=", 7)) {
- if (!strcmp(arg + 7, "relative"))
- revs->date_mode = DATE_RELATIVE;
- else if (!strcmp(arg + 7, "iso8601") ||
- !strcmp(arg + 7, "iso"))
- revs->date_mode = DATE_ISO8601;
- else if (!strcmp(arg + 7, "rfc2822") ||
- !strcmp(arg + 7, "rfc"))
- revs->date_mode = DATE_RFC2822;
- else if (!strcmp(arg + 7, "short"))
- revs->date_mode = DATE_SHORT;
- else if (!strcmp(arg + 7, "local"))
- revs->date_mode = DATE_LOCAL;
- else if (!strcmp(arg + 7, "default"))
- revs->date_mode = DATE_NORMAL;
- else
- die("unknown date format %s", arg);
+ revs->date_mode = parse_date_format(arg + 7);
continue;
}
if (!strcmp(arg, "--log-size")) {
--
1.5.3.2.105.gf47f2-dirty
^ permalink raw reply related
* [PATCH 4/4] Make for-each-ref's grab_date() support per-atom formatting
From: Andy Parkins @ 2007-09-28 14:17 UTC (permalink / raw)
To: git
In-Reply-To: <200709281516.05438.andyparkins@gmail.com>
grab_date() gets an extra parameter - atomname; this extra parameter is
checked to see if it has a ":<format>" extra component in it, and if so
that "<format>" string is passed to parse_date_format() to produce an
enum date_mode value which is then further passed to show_date().
In short it allows the user of git-for-each-ref to do things like this:
$ git-for-each-ref --format='%(taggerdate:default)' refs/tags/v1.5.2
Sun May 20 00:30:42 2007 -0700
$ git-for-each-ref --format='%(taggerdate:relative)' refs/tags/v1.5.2
4 months ago
$ git-for-each-ref --format='%(taggerdate:short)' refs/tags/v1.5.2
2007-05-20
$ git-for-each-ref --format='%(taggerdate:local)' refs/tags/v1.5.2
Sun May 20 08:30:42 2007
$ git-for-each-ref --format='%(taggerdate:iso8601)' refs/tags/v1.5.2
2007-05-20 00:30:42 -0700
$ git-for-each-ref --format='%(taggerdate:rfc2822)' refs/tags/v1.5.2
Sun, 20 May 2007 00:30:42 -0700
The default, when no ":<format>" is specified is ":default", leaving the
existing behaviour unchanged.
Signed-off-by: Andy Parkins <andyparkins@gmail.com>
---
Documentation/git-for-each-ref.txt | 5 +++++
builtin-for-each-ref.c | 26 +++++++++++++++++++-------
2 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index 6df8e85..f1f90cc 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -100,6 +100,11 @@ In any case, a field name that refers to a field inapplicable to
the object referred by the ref does not cause an error. It
returns an empty string instead.
+As a special case for the date-type fields, you may specify a format for
+the date by adding one of `:default`, `:relative`, `:short`, `:local`,
+`:iso8601` or `:rfc2822` to the end of the fieldname; e.g.
+`%(taggerdate:relative)`.
+
EXAMPLES
--------
diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c
index 3280516..2ca4fc6 100644
--- a/builtin-for-each-ref.c
+++ b/builtin-for-each-ref.c
@@ -353,12 +353,24 @@ static const char *copy_email(const char *buf)
return line;
}
-static void grab_date(const char *buf, struct atom_value *v)
+static void grab_date(const char *buf, struct atom_value *v, const char *atomname)
{
const char *eoemail = strstr(buf, "> ");
char *zone;
unsigned long timestamp;
long tz;
+ enum date_mode date_mode = DATE_NORMAL;
+ const char *formatp;
+
+ /* We got here because atomname ends in "date" or "date<something>",
+ * it's not possible that <something> is not ":<format>" because
+ * parse_atom() wouldn't have allowed it, so we can assume that no
+ * ":" means no format is specified, use the default */
+ formatp = strrchr( atomname, ':' );
+ if (formatp != NULL) {
+ formatp++;
+ date_mode = parse_date_format(formatp);
+ }
if (!eoemail)
goto bad;
@@ -368,7 +380,7 @@ static void grab_date(const char *buf, struct atom_value *v)
tz = strtol(zone, NULL, 10);
if ((tz == LONG_MIN || tz == LONG_MAX) && errno == ERANGE)
goto bad;
- v->s = xstrdup(show_date(timestamp, tz, 0));
+ v->s = xstrdup(show_date(timestamp, tz, date_mode));
v->ul = timestamp;
return;
bad:
@@ -395,7 +407,7 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru
if (name[wholen] != 0 &&
strcmp(name + wholen, "name") &&
strcmp(name + wholen, "email") &&
- strcmp(name + wholen, "date"))
+ prefixcmp(name + wholen, "date"))
continue;
if (!wholine)
wholine = find_wholine(who, wholen, buf, sz);
@@ -407,8 +419,8 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru
v->s = copy_name(wholine);
else if (!strcmp(name + wholen, "email"))
v->s = copy_email(wholine);
- else if (!strcmp(name + wholen, "date"))
- grab_date(wholine, v);
+ else if (!prefixcmp(name + wholen, "date"))
+ grab_date(wholine, v, name);
}
/* For a tag or a commit object, if "creator" or "creatordate" is
@@ -428,8 +440,8 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru
if (deref)
name++;
- if (!strcmp(name, "creatordate"))
- grab_date(wholine, v);
+ if (!prefixcmp(name, "creatordate"))
+ grab_date(wholine, v, name);
else if (!strcmp(name, "creator"))
v->s = copy_line(wholine);
}
--
1.5.3.2.105.gf47f2-dirty
^ permalink raw reply related
* [PATCH] post-receive-hook: Remove the From field from the generated email header so that the pusher's name is used
From: Andy Parkins @ 2007-09-28 14:24 UTC (permalink / raw)
To: git
Using the name of the committer of the revision at the tip of the
updated ref is not sensible. That information is available in the email
itself should it be wanted, and by supplying a "From", we were
effectively hiding the person who performed the push - which is useful
information in itself.
Signed-off-by: Andy Parkins <andyparkins@gmail.com>
---
contrib/hooks/post-receive-email | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/contrib/hooks/post-receive-email b/contrib/hooks/post-receive-email
index 1f88099..cbbd02f 100644
--- a/contrib/hooks/post-receive-email
+++ b/contrib/hooks/post-receive-email
@@ -177,7 +177,6 @@ generate_email_header()
# --- Email (all stdout will be the email)
# Generate header
cat <<-EOF
- From: $committer
To: $recipients
Subject: ${EMAILPREFIX}$projectdesc $refname_type, $short_refname, ${change_type}d. $describe
X-Git-Refname: $refname
--
1.5.3.2.105.gf47f2-dirty
^ permalink raw reply related
* Re: [PATCH 2/4] Use parse_date_format() in revisions.c to parse the --date parameter
From: Johannes Schindelin @ 2007-09-28 15:22 UTC (permalink / raw)
To: Andy Parkins; +Cc: git
In-Reply-To: <200709281517.32030.andyparkins@gmail.com>
Hi,
On Fri, 28 Sep 2007, Andy Parkins wrote:
> The --date parameter was previously handled in revisions.c with a list
> of if(strcmp()) calls; now parse_date_format() is called instead.
Since this is really more like a code move, 1/4 and 2/4 should be
squashed.
Ciao,
Dscho
^ permalink raw reply
* [PATCH v2 0/2] rsync support, was Re: [PATCH 0/2] rsync support
From: Johannes Schindelin @ 2007-09-28 15:28 UTC (permalink / raw)
To: gitster, spearce, Daniel Barkalow, git
In-Reply-To: <Pine.LNX.4.64.0709280602580.28395@racer.site>
Okay,
here we go again. The changes are
- do not implement a dummy disconnect
- use strbuf much more (makes the code cleaner and shorter, too)
- do not rely on the rejected alloc_ref() patch
Ciao,
Dscho
^ permalink raw reply
* [PATCH v2 1/2] Introduce remove_dir_recursively()
From: Johannes Schindelin @ 2007-09-28 15:28 UTC (permalink / raw)
To: gitster, Daniel Barkalow, git
In-Reply-To: <Pine.LNX.4.64.0709280602580.28395@racer.site>
There was a function called remove_empty_dir_recursive() buried
in refs.c. Expose a slightly enhanced version in dir.h: it can now
optionally remove a non-empty directory.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
dir.c | 41 +++++++++++++++++++++++++++++++++++++++++
dir.h | 2 ++
refs.c | 57 ++++++++++++---------------------------------------------
3 files changed, 55 insertions(+), 45 deletions(-)
diff --git a/dir.c b/dir.c
index eb6c3ab..b18257e 100644
--- a/dir.c
+++ b/dir.c
@@ -685,3 +685,44 @@ int is_inside_dir(const char *dir)
char buffer[PATH_MAX];
return get_relative_cwd(buffer, sizeof(buffer), dir) != NULL;
}
+
+int remove_dir_recursively(struct strbuf *path, int only_empty)
+{
+ DIR *dir = opendir(path->buf);
+ struct dirent *e;
+ int ret = 0, original_len = path->len, len;
+
+ if (!dir)
+ return -1;
+ if (path->buf[original_len - 1] != '/')
+ strbuf_addch(path, '/');
+
+ len = path->len;
+ while ((e = readdir(dir)) != NULL) {
+ struct stat st;
+ if ((e->d_name[0] == '.') &&
+ ((e->d_name[1] == 0) ||
+ ((e->d_name[1] == '.') && e->d_name[2] == 0)))
+ continue; /* "." and ".." */
+
+ strbuf_setlen(path, len);
+ strbuf_addstr(path, e->d_name);
+ if (lstat(path->buf, &st))
+ ; /* fall thru */
+ else if (S_ISDIR(st.st_mode)) {
+ if (!remove_dir_recursively(path, only_empty))
+ continue; /* happy */
+ } else if (!only_empty && !unlink(path->buf))
+ continue; /* happy, too */
+
+ /* path too long, stat fails, or non-directory still exists */
+ ret = -1;
+ break;
+ }
+ closedir(dir);
+
+ strbuf_setlen(path, original_len);
+ if (!ret)
+ ret = rmdir(path->buf);
+ return ret;
+}
diff --git a/dir.h b/dir.h
index f55a87b..a248a23 100644
--- a/dir.h
+++ b/dir.h
@@ -64,4 +64,6 @@ extern struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathna
extern char *get_relative_cwd(char *buffer, int size, const char *dir);
extern int is_inside_dir(const char *dir);
+extern int remove_dir_recursively(struct strbuf *path, int only_empty);
+
#endif
diff --git a/refs.c b/refs.c
index 07e260c..aff02cd 100644
--- a/refs.c
+++ b/refs.c
@@ -2,6 +2,7 @@
#include "refs.h"
#include "object.h"
#include "tag.h"
+#include "dir.h"
/* ISSYMREF=01 and ISPACKED=02 are public interfaces */
#define REF_KNOWS_PEELED 04
@@ -671,57 +672,23 @@ static struct ref_lock *verify_lock(struct ref_lock *lock,
return lock;
}
-static int remove_empty_dir_recursive(char *path, int len)
-{
- DIR *dir = opendir(path);
- struct dirent *e;
- int ret = 0;
-
- if (!dir)
- return -1;
- if (path[len-1] != '/')
- path[len++] = '/';
- while ((e = readdir(dir)) != NULL) {
- struct stat st;
- int namlen;
- if ((e->d_name[0] == '.') &&
- ((e->d_name[1] == 0) ||
- ((e->d_name[1] == '.') && e->d_name[2] == 0)))
- continue; /* "." and ".." */
-
- namlen = strlen(e->d_name);
- if ((len + namlen < PATH_MAX) &&
- strcpy(path + len, e->d_name) &&
- !lstat(path, &st) &&
- S_ISDIR(st.st_mode) &&
- !remove_empty_dir_recursive(path, len + namlen))
- continue; /* happy */
-
- /* path too long, stat fails, or non-directory still exists */
- ret = -1;
- break;
- }
- closedir(dir);
- if (!ret) {
- path[len] = 0;
- ret = rmdir(path);
- }
- return ret;
-}
-
-static int remove_empty_directories(char *file)
+static int remove_empty_directories(const char *file)
{
/* we want to create a file but there is a directory there;
* if that is an empty directory (or a directory that contains
* only empty directories), remove them.
*/
- char path[PATH_MAX];
- int len = strlen(file);
+ struct strbuf path;
+ int result;
- if (len >= PATH_MAX) /* path too long ;-) */
- return -1;
- strcpy(path, file);
- return remove_empty_dir_recursive(path, len);
+ strbuf_init(&path, 20);
+ strbuf_addstr(&path, file);
+
+ result = remove_dir_recursively(&path, 1);
+
+ strbuf_release(&path);
+
+ return result;
}
static int is_refname_available(const char *ref, const char *oldref,
--
1.5.3.2.1102.g9487
^ permalink raw reply related
* [PATCH 2/2] fetch/push: readd rsync support
From: Johannes Schindelin @ 2007-09-28 15:29 UTC (permalink / raw)
To: gitster, Daniel Barkalow, git
In-Reply-To: <Pine.LNX.4.64.0709280602580.28395@racer.site>
We lost rsync support when transitioning from shell to C. Support it
again (even if the transport is technically deprecated, some people just
do not have any chance to use anything else).
Also, add a test to t5510. Since rsync transport is not configured by
default on most machines, and especially not such that you can
write to rsync://127.0.0.1$(pwd)/, it is disabled by default; you can
enable it by setting the environment variable TEST_RSYNC.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
t/t5510-fetch.sh | 35 ++++++
transport.c | 328 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 362 insertions(+), 1 deletions(-)
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 439430f..73a4e3c 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -153,4 +153,39 @@ test_expect_success 'bundle should be able to create a full history' '
'
+test "$TEST_RSYNC" && {
+test_expect_success 'fetch via rsync' '
+ git pack-refs &&
+ mkdir rsynced &&
+ cd rsynced &&
+ git init &&
+ git fetch rsync://127.0.0.1$(pwd)/../.git master:refs/heads/master &&
+ git gc --prune &&
+ test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
+ git fsck --full
+'
+
+test_expect_success 'push via rsync' '
+ mkdir ../rsynced2 &&
+ (cd ../rsynced2 &&
+ git init) &&
+ git push rsync://127.0.0.1$(pwd)/../rsynced2/.git master &&
+ cd ../rsynced2 &&
+ git gc --prune &&
+ test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
+ git fsck --full
+'
+
+test_expect_success 'push via rsync' '
+ cd .. &&
+ mkdir rsynced3 &&
+ (cd rsynced3 &&
+ git init) &&
+ git push --all rsync://127.0.0.1$(pwd)/rsynced3/.git &&
+ cd rsynced3 &&
+ test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
+ git fsck --full
+'
+}
+
test_done
diff --git a/transport.c b/transport.c
index 4f9cddc..c8eed95 100644
--- a/transport.c
+++ b/transport.c
@@ -6,6 +6,330 @@
#include "fetch-pack.h"
#include "walker.h"
#include "bundle.h"
+#include "dir.h"
+#include "refs.h"
+
+/* rsync support */
+
+/*
+ * We copy packed-refs and refs/ into a temporary file, then read the
+ * loose refs recursively (sorting whenever possible), and then inserting
+ * those packed refs that are not yet in the list (not validating, but
+ * assuming that the file is sorted).
+ *
+ * Appears refactoring this from refs.c is too cumbersome.
+ */
+
+static int direntry_cmp(const void *a, const void *b)
+{
+ const struct dirent *d1 = a;
+ const struct dirent *d2 = b;
+
+ return strcmp(d1->d_name, d2->d_name);
+}
+
+/*
+ * path is assumed to point to a buffer of PATH_MAX bytes, and
+ * path + name_offset is expected to point to "refs/".
+ */
+
+static int read_loose_refs(struct strbuf *path, int name_offset,
+ struct ref **tail)
+{
+ DIR *dir = opendir(path->buf);
+ struct dirent *de;
+ struct {
+ char **entries;
+ int nr, alloc;
+ } list;
+ int i, pathlen;
+
+ if (!dir)
+ return -1;
+
+ memset (&list, 0, sizeof(list));
+
+ while ((de = readdir(dir))) {
+ if (de->d_name[0] == '.' && (de->d_name[1] == '\0' ||
+ (de->d_name[1] == '.' &&
+ de->d_name[2] == '\0')))
+ continue;
+ ALLOC_GROW(list.entries, list.nr + 1, list.alloc);
+ list.entries[list.nr++] = xstrdup(de->d_name);
+ }
+ closedir(dir);
+
+ /* sort the list */
+
+ qsort(list.entries, list.nr, sizeof(*de), direntry_cmp);
+
+ pathlen = path->len;
+ strbuf_addch(path, '/');
+
+ for (i = 0; i < list.nr; i++, strbuf_setlen(path, pathlen + 1)) {
+ strbuf_addstr(path, list.entries[i]);
+ if (read_loose_refs(path, name_offset, tail)) {
+ int fd = open(path->buf, O_RDONLY);
+ char buffer[40];
+ struct ref *next;
+
+ if (fd < 0)
+ continue;
+ next = alloc_ref(path->len - name_offset + 1);
+ if (read_in_full(fd, buffer, 40) != 40 ||
+ get_sha1_hex(buffer, next->old_sha1)) {
+ free(next);
+ continue;
+ }
+ close(fd);
+ strcpy(next->name, path->buf + name_offset);
+ (*tail)->next = next;
+ *tail = next;
+ }
+ }
+
+ for (i = 0; i < list.nr; i++)
+ free(list.entries[i]);
+ free(list.entries);
+
+ return 0;
+}
+
+/* insert the packed refs for which no loose refs were found */
+
+static void insert_packed_refs(const char *packed_refs, struct ref **list)
+{
+ FILE *f = fopen(packed_refs, "r");
+ static char buffer[PATH_MAX];
+
+ if (!f)
+ return;
+
+ for (;;) {
+ int cmp, len;
+
+ if (!fgets(buffer, sizeof(buffer), f)) {
+ fclose(f);
+ return;
+ }
+
+ if (hexval(buffer[0]) & 0x10)
+ continue;
+ len = strlen(buffer);
+ if (buffer[len - 1] == '\n')
+ buffer[--len] = '\0';
+ if (len < 41)
+ continue;
+ while ((*list)->next &&
+ (cmp = strcmp(buffer + 41,
+ (*list)->next->name)) > 0)
+ list = &(*list)->next;
+ if (!(*list)->next || cmp < 0) {
+ struct ref *next = alloc_ref(len - 40);
+ buffer[40] = '\0';
+ if (get_sha1_hex(buffer, next->old_sha1)) {
+ warning ("invalid SHA-1: %s", buffer);
+ free(next);
+ continue;
+ }
+ strcpy(next->name, buffer + 41);
+ next->next = (*list)->next;
+ (*list)->next = next;
+ list = &(*list)->next;
+ }
+ }
+}
+
+static struct ref *get_refs_via_rsync(const struct transport *transport)
+{
+ struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
+ struct ref dummy, *result = &dummy;
+ struct child_process rsync;
+ const char *args[5];
+ int temp_dir_len;
+
+ /* copy the refs to the temporary directory */
+
+ strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
+ if (!mkdtemp(temp_dir.buf))
+ die ("Could not make temporary directory");
+ temp_dir_len = temp_dir.len;
+
+ strbuf_addstr(&buf, transport->url);
+ strbuf_addstr(&buf, "/refs");
+
+ memset(&rsync, 0, sizeof(rsync));
+ rsync.argv = args;
+ rsync.stdout_to_stderr = 1;
+ args[0] = "rsync";
+ args[1] = transport->verbose ? "-rv" : "-r";
+ args[2] = buf.buf;
+ args[3] = temp_dir.buf;
+ args[4] = NULL;
+
+ if (run_command(&rsync))
+ die ("Could not run rsync to get refs");
+
+ strbuf_reset(&buf);
+ strbuf_addstr(&buf, transport->url);
+ strbuf_addstr(&buf, "/packed-refs");
+
+ args[2] = buf.buf;
+
+ if (run_command(&rsync))
+ die ("Could not run rsync to get refs");
+
+ /* read the copied refs */
+
+ strbuf_addstr(&temp_dir, "/refs");
+ read_loose_refs(&temp_dir, temp_dir_len + 1, &result);
+ strbuf_setlen(&temp_dir, temp_dir_len);
+
+ result = &dummy;
+ strbuf_addstr(&temp_dir, "/packed-refs");
+ insert_packed_refs(temp_dir.buf, &result);
+ strbuf_setlen(&temp_dir, temp_dir_len);
+
+ if (remove_dir_recursively(&temp_dir, 0))
+ warning ("Error removing temporary directory %s.",
+ temp_dir.buf);
+
+ strbuf_release(&buf);
+ strbuf_release(&temp_dir);
+
+ return dummy.next;
+}
+
+static int fetch_objs_via_rsync(struct transport *transport,
+ int nr_objs, struct ref **to_fetch)
+{
+ struct strbuf buf = STRBUF_INIT;
+ struct child_process rsync;
+ const char *args[8];
+ int result;
+
+ strbuf_addstr(&buf, transport->url);
+ strbuf_addstr(&buf, "/objects/");
+
+ memset(&rsync, 0, sizeof(rsync));
+ rsync.argv = args;
+ rsync.stdout_to_stderr = 1;
+ args[0] = "rsync";
+ args[1] = transport->verbose ? "-rv" : "-r";
+ args[2] = "--ignore-existing";
+ args[3] = "--exclude";
+ args[4] = "info";
+ args[5] = buf.buf;
+ args[6] = get_object_directory();
+ args[7] = NULL;
+
+ /* NEEDSWORK: handle one level of alternates */
+ result = run_command(&rsync);
+
+ strbuf_release(&buf);
+
+ return result;
+}
+
+static int write_one_ref(const char *name, const unsigned char *sha1,
+ int flags, void *data)
+{
+ struct strbuf *buf = data;
+ int len = buf->len;
+ FILE *f;
+
+ if (flags && prefixcmp(name, "refs/heads/") &&
+ prefixcmp(name, "refs/tags/"))
+ return 0;
+
+ strbuf_addstr(buf, name);
+ if (safe_create_leading_directories(buf->buf) ||
+ !(f = fopen(buf->buf, "w")) ||
+ !fwrite(sha1_to_hex(sha1), 40, 1, f) ||
+ fputc('\n', f) == EOF ||
+ fclose(f))
+ return error("problems writing temporary file %s", buf->buf);
+ strbuf_setlen(buf, len);
+ return 0;
+}
+
+static int write_refs_to_temp_dir(struct strbuf *temp_dir,
+ int refspec_nr, const char **refspec)
+{
+ int i;
+
+ for (i = 0; i < refspec_nr; i++) {
+ unsigned char sha1[20];
+ char *ref;
+
+ if (dwim_ref(refspec[i], strlen(refspec[i]), sha1, &ref) != 1)
+ return error("Could not get ref %s", refspec[i]);
+
+ if (write_one_ref(ref, sha1, 0, temp_dir)) {
+ free(ref);
+ return -1;
+ }
+ free(ref);
+ }
+ return 0;
+}
+
+static int rsync_transport_push(struct transport *transport,
+ int refspec_nr, const char **refspec, int flags) {
+ struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
+ int result = 0, i;
+ struct child_process rsync;
+ const char *args[8];
+
+ /* first push the objects */
+
+ strbuf_addstr(&buf, transport->url);
+ strbuf_addch(&buf, '/');
+
+ memset(&rsync, 0, sizeof(rsync));
+ rsync.argv = args;
+ rsync.stdout_to_stderr = 1;
+ args[0] = "rsync";
+ args[1] = transport->verbose ? "-av" : "-a";
+ args[2] = "--ignore-existing";
+ args[3] = "--exclude";
+ args[4] = "info";
+ args[5] = get_object_directory();;
+ args[6] = buf.buf;
+ args[7] = NULL;
+
+ if (run_command(&rsync))
+ return error("Could not push objects to %s", transport->url);
+
+ /* copy the refs to the temporary directory; they could be packed. */
+
+ strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
+ if (!mkdtemp(temp_dir.buf))
+ die ("Could not make temporary directory");
+ strbuf_addch(&temp_dir, '/');
+
+ if (flags & TRANSPORT_PUSH_ALL) {
+ if (for_each_ref(write_one_ref, &temp_dir))
+ return -1;
+ } else if (write_refs_to_temp_dir(&temp_dir, refspec_nr, refspec))
+ return -1;
+
+ i = (flags & TRANSPORT_PUSH_FORCE) ? 2 : 3;
+ args[i++] = temp_dir.buf;
+ args[i++] = transport->url;
+ args[i++] = NULL;
+ if (run_command(&rsync))
+ result = error("Could not push to %s", transport->url);
+
+ if (remove_dir_recursively(&temp_dir, 0))
+ warning ("Could not remove temporary directory %s.",
+ temp_dir.buf);
+
+ strbuf_release(&buf);
+ strbuf_release(&temp_dir);
+
+ return result;
+}
/* Generic functions for using commit walkers */
@@ -402,7 +726,9 @@ struct transport *transport_get(struct remote *remote, const char *url)
ret->url = url;
if (!prefixcmp(url, "rsync://")) {
- /* not supported; don't populate any ops */
+ ret->get_refs_list = get_refs_via_rsync;
+ ret->fetch = fetch_objs_via_rsync;
+ ret->push = rsync_transport_push;
} else if (!prefixcmp(url, "http://")
|| !prefixcmp(url, "https://")
--
1.5.3.2.1102.g9487
^ permalink raw reply related
* Re: [PATCH 2/2] fetch/push: readd rsync support
From: Johannes Schindelin @ 2007-09-28 15:30 UTC (permalink / raw)
To: gitster, Daniel Barkalow, git
In-Reply-To: <Pine.LNX.4.64.0709281629270.28395@racer.site>
Darn. this should read [PATCH v2 2/2].
^ permalink raw reply
* Re: [PATCH] alloc_ref(): allow for trailing NUL
From: Daniel Barkalow @ 2007-09-28 15:44 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.64.0709281259050.28395@racer.site>
On Fri, 28 Sep 2007, Johannes Schindelin wrote:
> Hi,
>
> On Fri, 28 Sep 2007, Junio C Hamano wrote:
>
> > Daniel Barkalow <barkalow@iabervon.org> writes:
> >
> > > On Fri, 28 Sep 2007, Johannes Schindelin wrote:
> > >
> > >> The parameter name "namelen" suggests that you pass the equivalent of
> > >> strlen() to the function alloc_ref(). However, this function did not
> > >> allocate enough space to put a NUL after the name.
> > >>
> > >> Since struct ref does not have any member to describe the length of the
> > >> string, this just does not make sense.
> > >>
> > >> So make space for the NUL.
> > >
> > > Good point, but shouldn't you then fix call sites that use strlen(name) +
> > > 1?
> >
> > Good point.
> >
> > I audited "git grep -A2 -B4 -e alloc_ref next master" output,
> > and it appears almost everybody knows alloc_ref() wants the
> > caller to count the terminating NUL.
> >
> > There however are a few gotchas.
> >
> > * There is one overallocation in connect.c, which would not
> > hurt but is wasteful;
> >
> > * next:transport.c has alloc_ref(strlen(e->name)) which is a
> > no-no;
> >
> > Discarding Johannes's patch, the following would fix it.
>
> But should the signature of alloc_ref() not be changed, then, to read
>
> struct ref *alloc_ref(unsigned name_alloc);
>
> Hm?
>
> Further, I am quite sure that the same mistake will happen again, until we
> change the function to get the name length, not the number of bytes to
> allocate.
I agree. But leaving the majority of cases using the old convention is
just confusing.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* Re: [PATCH] alloc_ref(): allow for trailing NUL
From: Johannes Schindelin @ 2007-09-28 16:11 UTC (permalink / raw)
To: Daniel Barkalow; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.64.0709281138270.5926@iabervon.org>
Hi,
On Fri, 28 Sep 2007, Daniel Barkalow wrote:
> On Fri, 28 Sep 2007, Johannes Schindelin wrote:
>
> > Hi,
> >
> > On Fri, 28 Sep 2007, Junio C Hamano wrote:
> >
> > > Daniel Barkalow <barkalow@iabervon.org> writes:
> > >
> > > > On Fri, 28 Sep 2007, Johannes Schindelin wrote:
> > > >
> > > >> The parameter name "namelen" suggests that you pass the equivalent of
> > > >> strlen() to the function alloc_ref(). However, this function did not
> > > >> allocate enough space to put a NUL after the name.
> > > >>
> > > >> Since struct ref does not have any member to describe the length of the
> > > >> string, this just does not make sense.
> > > >>
> > > >> So make space for the NUL.
> > > >
> > > > Good point, but shouldn't you then fix call sites that use strlen(name) +
> > > > 1?
> > >
> > > Good point.
> > >
> > > I audited "git grep -A2 -B4 -e alloc_ref next master" output,
> > > and it appears almost everybody knows alloc_ref() wants the
> > > caller to count the terminating NUL.
> > >
> > > There however are a few gotchas.
> > >
> > > * There is one overallocation in connect.c, which would not
> > > hurt but is wasteful;
> > >
> > > * next:transport.c has alloc_ref(strlen(e->name)) which is a
> > > no-no;
> > >
> > > Discarding Johannes's patch, the following would fix it.
> >
> > But should the signature of alloc_ref() not be changed, then, to read
> >
> > struct ref *alloc_ref(unsigned name_alloc);
> >
> > Hm?
> >
> > Further, I am quite sure that the same mistake will happen again, until we
> > change the function to get the name length, not the number of bytes to
> > allocate.
>
> I agree. But leaving the majority of cases using the old convention is
> just confusing.
Yeah, sorry, that patch was only half-cooked.
If people agree with me, I'll redo the patch (fixing all calling sites,
too).
Ciao,
Dscho
^ permalink raw reply
* [PATCH] Adding rebase merge strategy
From: Tom Clarke @ 2007-09-28 16:15 UTC (permalink / raw)
To: gitster; +Cc: git, Tom Clarke
In addition to adding git-merge-rebase.sh, git-merge.sh is modified
to handle the rebase strategy specially and avoids running update-ref
as rebase won't generate a merge commit.
Signed-off-by: Tom Clarke <tom@u2i.com>
---
Re-submitting this patch as we were in a pre-release freeze last time I submitted
.gitignore | 1 +
Documentation/merge-strategies.txt | 6 ++++++
Makefile | 2 +-
git-merge-rebase.sh | 34 ++++++++++++++++++++++++++++++++++
git-merge.sh | 14 +++++++++++---
t/t3031-merge-rebase.sh | 34 ++++++++++++++++++++++++++++++++++
6 files changed, 87 insertions(+), 4 deletions(-)
create mode 100755 git-merge-rebase.sh
create mode 100755 t/t3031-merge-rebase.sh
diff --git a/.gitignore b/.gitignore
index e0b91be..fe5cdc4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -73,6 +73,7 @@ git-merge-tree
git-merge-octopus
git-merge-one-file
git-merge-ours
+git-merge-rebase
git-merge-recursive
git-merge-resolve
git-merge-stupid
diff --git a/Documentation/merge-strategies.txt b/Documentation/merge-strategies.txt
index 7df0266..dff1909 100644
--- a/Documentation/merge-strategies.txt
+++ b/Documentation/merge-strategies.txt
@@ -33,3 +33,9 @@ ours::
merge is always the current branch head. It is meant to
be used to supersede old development history of side
branches.
+
+rebase::
+ This rebases the current branch based on a single head.
+ Commits are rewritten as with git-rebase. This doesn't
+ produce a merge. The procedure for dealing with conflicts
+ is the same as with git-rebase.
diff --git a/Makefile b/Makefile
index 8db4dbe..e6d3812 100644
--- a/Makefile
+++ b/Makefile
@@ -215,7 +215,7 @@ SCRIPT_SH = \
git-sh-setup.sh \
git-am.sh \
git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
- git-merge-resolve.sh git-merge-ours.sh \
+ git-merge-resolve.sh git-merge-ours.sh git-merge-rebase.sh \
git-lost-found.sh git-quiltimport.sh git-submodule.sh \
git-filter-branch.sh \
git-stash.sh
diff --git a/git-merge-rebase.sh b/git-merge-rebase.sh
new file mode 100755
index 0000000..fc07331
--- /dev/null
+++ b/git-merge-rebase.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Linus Torvalds
+# Copyright (c) 2007 Tom Clarke
+#
+# Resolve two trees with rebase
+
+# The first parameters up to -- are merge bases; the rest are heads.
+bases= head= remotes= sep_seen=
+for arg
+do
+ case ",$sep_seen,$head,$arg," in
+ *,--,)
+ sep_seen=yes
+ ;;
+ ,yes,,*)
+ head=$arg
+ ;;
+ ,yes,*)
+ remotes="$remotes$arg "
+ ;;
+ *)
+ bases="$bases$arg "
+ ;;
+ esac
+done
+
+# Give up if we are given two or more remotes -- not handling octopus.
+case "$remotes" in
+?*' '?*)
+ exit 2 ;;
+esac
+
+git rebase $remotes || exit 2
diff --git a/git-merge.sh b/git-merge.sh
index 6c513dc..ea3cc16 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -16,11 +16,12 @@ test -z "$(git ls-files -u)" ||
LF='
'
-all_strategies='recur recursive octopus resolve stupid ours subtree'
+all_strategies='recur recursive octopus resolve stupid ours subtree rebase'
default_twohead_strategies='recursive'
default_octopus_strategies='octopus'
no_fast_forward_strategies='subtree ours'
-no_trivial_strategies='recursive recur subtree ours'
+no_trivial_strategies='recursive recur subtree ours rebase'
+no_update_ref='rebase'
use_strategies=
allow_fast_forward=t
@@ -81,11 +82,18 @@ finish () {
echo "No merge message -- not updating HEAD"
;;
*)
- git update-ref -m "$rlogm" HEAD "$1" "$head" || exit 1
+ case " $wt_strategy " in
+ *" $no_update_ref "*)
+ ;;
+ *)
+ git update-ref -m "$rlogm" HEAD "$1" "$head" || exit 1
+ ;;
+ esac
;;
esac
;;
esac
+
case "$1" in
'')
;;
diff --git a/t/t3031-merge-rebase.sh b/t/t3031-merge-rebase.sh
new file mode 100755
index 0000000..8e3641d
--- /dev/null
+++ b/t/t3031-merge-rebase.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+test_description='merge-rebase backend test'
+
+. ./test-lib.sh
+
+test_expect_success 'merging using rebase does not create merge commit' '
+ echo hello >a &&
+ git add a &&
+ test_tick && git commit -m initial &&
+
+ git checkout -b branch &&
+ echo hello >b &&
+ git add b &&
+ test_tick && git commit -m onbranch &&
+
+ git checkout master &&
+ echo update >a &&
+ git add a &&
+ test_tick && git commit -m update &&
+
+ git checkout branch &&
+ git merge -s rebase master >expect &&
+
+ ( git log --pretty=oneline ) >actual &&
+ (
+ echo "4db7a5a013e67aa623d1fd294e8d46e89b3ace8f onbranch"
+ echo "893371811dbd13e85c098b72d1ab42bcfd24c2db update"
+ echo "0e960b10429bf3f1e168ee2cc7d531ac7c622580 initial"
+ ) >expected &&
+ git diff -w -u expected actual
+'
+
+test_done
--
1.5.3.rc7.3.g850f-dirty
^ permalink raw reply related
* Re: [PATCH] Adding rebase merge strategy
From: Johannes Schindelin @ 2007-09-28 17:03 UTC (permalink / raw)
To: Tom Clarke; +Cc: gitster, git
In-Reply-To: <11909961212172-git-send-email-tom@u2i.com>
Hi,
On Fri, 28 Sep 2007, Tom Clarke wrote:
> diff --git a/git-merge-rebase.sh b/git-merge-rebase.sh
> new file mode 100755
> index 0000000..fc07331
> --- /dev/null
> +++ b/git-merge-rebase.sh
> @@ -0,0 +1,34 @@
> +#!/bin/sh
> +#
> +# Copyright (c) 2005 Linus Torvalds
Really?
> +# Copyright (c) 2007 Tom Clarke
> +#
> +# Resolve two trees with rebase
> +
> +# The first parameters up to -- are merge bases; the rest are heads.
> +bases= head= remotes= sep_seen=
> +for arg
> +do
> + case ",$sep_seen,$head,$arg," in
> + *,--,)
> + sep_seen=yes
> + ;;
> + ,yes,,*)
> + head=$arg
> + ;;
> + ,yes,*)
> + remotes="$remotes$arg "
> + ;;
> + *)
> + bases="$bases$arg "
> + ;;
> + esac
> +done
> +
> +# Give up if we are given two or more remotes -- not handling octopus.
> +case "$remotes" in
> +?*' '?*)
> + exit 2 ;;
> +esac
You can check that much earlier, no? IOW something like
while test $# != 0
do
case "$1" in --) break ;; esac
shift
done
test $# = 3 || die "merge stragey rebase needs exactly one ref"
git rebase "$3"
(It's not like you need the variables...) Hmm?
> +git rebase $remotes || exit 2
> diff --git a/git-merge.sh b/git-merge.sh
> index 6c513dc..ea3cc16 100755
> --- a/git-merge.sh
> +++ b/git-merge.sh
> @@ -81,11 +82,18 @@ finish () {
> echo "No merge message -- not updating HEAD"
> ;;
> *)
> - git update-ref -m "$rlogm" HEAD "$1" "$head" || exit 1
> + case " $wt_strategy " in
> + *" $no_update_ref "*)
> + ;;
> + *)
> + git update-ref -m "$rlogm" HEAD "$1" "$head" || exit 1
> + ;;
> + esac
You may want to warn earlier, if a message was supplied with -s rebase, or
even error out.
> diff --git a/t/t3031-merge-rebase.sh b/t/t3031-merge-rebase.sh
> new file mode 100755
> index 0000000..8e3641d
> --- /dev/null
> +++ b/t/t3031-merge-rebase.sh
> @@ -0,0 +1,34 @@
> +#!/bin/sh
> +
> +test_description='merge-rebase backend test'
> +
> +. ./test-lib.sh
> +
> +test_expect_success 'merging using rebase does not create merge commit' '
> + echo hello >a &&
> + git add a &&
> + test_tick && git commit -m initial &&
> +
> + git checkout -b branch &&
> + echo hello >b &&
> + git add b &&
> + test_tick && git commit -m onbranch &&
> +
> + git checkout master &&
> + echo update >a &&
> + git add a &&
> + test_tick && git commit -m update &&
I like to have something like this in a "test_expect_success setup" part,
and then have the meat of the test in its own test case.
But hey, you're the author, it's for you to decide.
Thanks,
Dscho
^ permalink raw reply
* Re: [PATCH] Adding rebase merge strategy
From: Tom Clarke @ 2007-09-28 17:18 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: gitster, git
In-Reply-To: <Pine.LNX.4.64.0709281751390.28395@racer.site>
On 9/28/07, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> > +# Copyright (c) 2005 Linus Torvalds
>
> Really?
Well 90% of the file was copy and pasted from one of the other merge
strategies which was indeed written by Linus. So it seemed
appropriate. If that's not appropriate attribution I can remove :-).
-Tom
^ permalink raw reply
* Re: git-svn and branches
From: Steven Walter @ 2007-09-28 17:19 UTC (permalink / raw)
To: Eric Wong; +Cc: git, stevenrwalter
In-Reply-To: <20070927072404.GB1782@hand.yhbt.net>
On Thu, Sep 27, 2007 at 12:24:04AM -0700, Eric Wong wrote:
> I believe your case handles where a branch is created directly from a
> trunk copy with no file modifications in the branch, but not when a
> branch is created and files are modified in the trunk (or branch) within
> the same revision. Is this what's happening?
>
> Additionally, I think this breaks when an entire trunk or branch is
> moved around because the original directory has moved or gone away:
>
> /trunk => /project-a/trunk
>
> Anyways, as Sam said, newer SVN (1.4.4+) has a working do_switch()
> function and that code path will never be hit at all.
I think you're right that my code would only handle a verbatim copy. I
made a few changes and I think I have something that is more generally
useful. Using a newer version of subversion isn't practical for me, as
this is a work situation where I don't have control of the workstations.
One criticism of the patch: the trees_match function probably needs to
be re-written. My SVN::Perl-foo is weak.
Patch to follow
--
-Steven Walter <stevenrwalter@gmail.com>
"A human being should be able to change a diaper, plan an invasion,
butcher a hog, conn a ship, design a building, write a sonnet, balance
accounts, build a wall, set a bone, comfort the dying, take orders,
give orders, cooperate, act alone, solve equations, analyze a new
problem, pitch manure, program a computer, cook a tasty meal, fight
efficiently, die gallantly. Specialization is for insects."
-Robert Heinlein
^ permalink raw reply
* [PATCH] Don't checkout the full tree if avoidable
From: Steven Walter @ 2007-09-28 17:24 UTC (permalink / raw)
To: git; +Cc: Steven Walter
In most cases of branching, the tree is copied unmodified from the trunk
to the branch. When that is done, we can simply start with the parent's
index and apply the changes on the branch as usual.
Signed-off-by: Steven Walter <stevenrwalter@gmail.com>
---
git-svn.perl | 18 ++++++++++++++++++
1 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/git-svn.perl b/git-svn.perl
index 484b057..2ca2042 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -1847,6 +1847,13 @@ sub find_parent_branch {
$gs->ra->gs_do_switch($r0, $rev, $gs,
$self->full_url, $ed)
or die "SVN connection failed somewhere...\n";
+ } elsif ($self->trees_match($new_url, $r0,
+ $self->full_url, $rev)) {
+ $self->tmp_index_do(sub {
+ command_noisy('read-tree', $parent);
+ });
+ $self->{last_commit} = $parent;
+ # Assume copy with no changes
} else {
print STDERR "Following parent with do_update\n";
$ed = SVN::Git::Fetcher->new($self);
@@ -1859,6 +1866,17 @@ sub find_parent_branch {
return undef;
}
+sub trees_match {
+ my ($self, $url1, $rev1, $url2, $rev2) = @_;
+
+ my $ret=1;
+ open(my $fh, "svn diff $url1\@$rev1 $url2\@$rev2 |");
+ $ret=0 if (<$fh>);
+ close($fh);
+
+ return $ret;
+}
+
sub do_fetch {
my ($self, $paths, $rev) = @_;
my $ed;
--
1.5.3.1
^ permalink raw reply related
* Re: [PATCH 2/4] Use parse_date_format() in revisions.c to parse the --date parameter
From: Andy Parkins @ 2007-09-28 18:00 UTC (permalink / raw)
To: git; +Cc: Johannes Schindelin, Junio C Hamano
In-Reply-To: <Pine.LNX.4.64.0709281622240.28395@racer.site>
On Friday 2007, September 28, Johannes Schindelin wrote:
> Since this is really more like a code move, 1/4 and 2/4 should be
> squashed.
I have no problem with that.
Junio: would you like a resend?
Andy
--
Dr Andy Parkins, M Eng (hons), MIET
andyparkins@gmail.com
^ permalink raw reply
* Re: [PATCH] alloc_ref(): allow for trailing NUL
From: Junio C Hamano @ 2007-09-28 18:08 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Daniel Barkalow, git
In-Reply-To: <Pine.LNX.4.64.0709281711010.28395@racer.site>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> On Fri, 28 Sep 2007, Daniel Barkalow wrote:
>
>> On Fri, 28 Sep 2007, Johannes Schindelin wrote:
>>
>> > Further, I am quite sure that the same mistake will happen again, until we
>> > change the function to get the name length, not the number of bytes to
>> > allocate.
>>
>> I agree. But leaving the majority of cases using the old convention is
>> just confusing.
>
> Yeah, sorry, that patch was only half-cooked.
>
> If people agree with me, I'll redo the patch (fixing all calling sites,
> too).
I think that is probably a better solution.
^ permalink raw reply
* Re: [PATCH 2/4] Use parse_date_format() in revisions.c to parse the --date parameter
From: Junio C Hamano @ 2007-09-28 18:11 UTC (permalink / raw)
To: Andy Parkins; +Cc: git, Johannes Schindelin
In-Reply-To: <200709281900.25536.andyparkins@gmail.com>
Andy Parkins <andyparkins@gmail.com> writes:
> On Friday 2007, September 28, Johannes Schindelin wrote:
>
>> Since this is really more like a code move, 1/4 and 2/4 should be
>> squashed.
>
> I have no problem with that.
>
> Junio: would you like a resend?
Sounds like a good plan.
^ 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