Skip to content

Commit

Permalink
Allow helper to map private ref names into normal names
Browse files Browse the repository at this point in the history
This allows a helper to say that, when it handles "import
refs/heads/topic", the script it outputs will actually write to
refs/svn/origin/branches/topic; therefore, transport-helper should
read it from the latter location after git-fast-import completes.

Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Daniel Barkalow authored and Junio C Hamano committed Nov 18, 2009
1 parent e65e91e commit 72ff894
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 2 deletions.
16 changes: 15 additions & 1 deletion Documentation/git-remote-helpers.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ Supported if the helper has the "fetch" capability.
'import' <name>::
Produces a fast-import stream which imports the current value
of the named ref. It may additionally import other refs as
needed to construct the history efficiently.
needed to construct the history efficiently. The script writes
to a helper-specific private namespace. The value of the named
ref should be written to a location in this namespace derived
by applying the refspecs from the "refspec" capability to the
name of the ref.
+
Supported if the helper has the "import" capability.

Expand All @@ -67,6 +71,16 @@ CAPABILITIES
'import'::
This helper supports the 'import' command.

'refspec' 'spec'::
When using the import command, expect the source ref to have
been written to the destination ref. The earliest applicable
refspec takes precedence. For example
"refs/heads/*:refs/svn/origin/branches/*" means that, after an
"import refs/heads/name", the script has written to
refs/svn/origin/branches/name. If this capability is used at
all, it must cover all refs reported by the list command; if
it is not used, it is effectively "*:*"

REF LIST ATTRIBUTES
-------------------

Expand Down
27 changes: 27 additions & 0 deletions remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,16 @@ static struct refspec *parse_push_refspec(int nr_refspec, const char **refspec)
return parse_refspec_internal(nr_refspec, refspec, 0, 0);
}

void free_refspec(int nr_refspec, struct refspec *refspec)
{
int i;
for (i = 0; i < nr_refspec; i++) {
free(refspec[i].src);
free(refspec[i].dst);
}
free(refspec);
}

static int valid_remote_nick(const char *name)
{
if (!name[0] || is_dot_or_dotdot(name))
Expand Down Expand Up @@ -811,6 +821,23 @@ static int match_name_with_pattern(const char *key, const char *name,
return ret;
}

char *apply_refspecs(struct refspec *refspecs, int nr_refspec,
const char *name)
{
int i;
char *ret = NULL;
for (i = 0; i < nr_refspec; i++) {
struct refspec *refspec = refspecs + i;
if (refspec->pattern) {
if (match_name_with_pattern(refspec->src, name,
refspec->dst, &ret))
return ret;
} else if (!strcmp(refspec->src, name))
return strdup(refspec->dst);
}
return NULL;
}

int remote_find_tracking(struct remote *remote, struct refspec *refspec)
{
int find_src = refspec->src == NULL;
Expand Down
5 changes: 5 additions & 0 deletions remote.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ void ref_remove_duplicates(struct ref *ref_map);
int valid_fetch_refspec(const char *refspec);
struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec);

void free_refspec(int nr_refspec, struct refspec *refspec);

char *apply_refspecs(struct refspec *refspecs, int nr_refspec,
const char *name);

int match_refs(struct ref *src, struct ref **dst,
int nr_refspec, const char **refspec, int all);

Expand Down
34 changes: 33 additions & 1 deletion transport-helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
#include "commit.h"
#include "diff.h"
#include "revision.h"
#include "remote.h"

struct helper_data
{
const char *name;
struct child_process *helper;
unsigned fetch : 1;
unsigned import : 1;
/* These go from remote name (as in "list") to private name */
struct refspec *refspecs;
int refspec_nr;
};

static struct child_process *get_helper(struct transport *transport)
Expand All @@ -20,6 +24,9 @@ static struct child_process *get_helper(struct transport *transport)
struct strbuf buf = STRBUF_INIT;
struct child_process *helper;
FILE *file;
const char **refspecs = NULL;
int refspec_nr = 0;
int refspec_alloc = 0;

if (data->helper)
return data->helper;
Expand Down Expand Up @@ -51,6 +58,21 @@ static struct child_process *get_helper(struct transport *transport)
data->fetch = 1;
if (!strcmp(buf.buf, "import"))
data->import = 1;
if (!data->refspecs && !prefixcmp(buf.buf, "refspec ")) {
ALLOC_GROW(refspecs,
refspec_nr + 1,
refspec_alloc);
refspecs[refspec_nr++] = strdup(buf.buf + strlen("refspec "));
}
}
if (refspecs) {
int i;
data->refspec_nr = refspec_nr;
data->refspecs = parse_fetch_refspec(refspec_nr, refspecs);
for (i = 0; i < refspec_nr; i++) {
free((char *)refspecs[i]);
}
free(refspecs);
}
return data->helper;
}
Expand All @@ -72,6 +94,9 @@ static int disconnect_helper(struct transport *transport)

static int release_helper(struct transport *transport)
{
struct helper_data *data = transport->data;
free_refspec(data->refspec_nr, data->refspecs);
data->refspecs = NULL;
disconnect_helper(transport);
free(transport->data);
return 0;
Expand Down Expand Up @@ -119,6 +144,7 @@ static int fetch_with_import(struct transport *transport,
{
struct child_process fastimport;
struct child_process *helper = get_helper(transport);
struct helper_data *data = transport->data;
int i;
struct ref *posn;
struct strbuf buf = STRBUF_INIT;
Expand All @@ -139,10 +165,16 @@ static int fetch_with_import(struct transport *transport,
finish_command(&fastimport);

for (i = 0; i < nr_heads; i++) {
char *private;
posn = to_fetch[i];
if (posn->status & REF_STATUS_UPTODATE)
continue;
read_ref(posn->name, posn->old_sha1);
if (data->refspecs)
private = apply_refspecs(data->refspecs, data->refspec_nr, posn->name);
else
private = strdup(posn->name);
read_ref(private, posn->old_sha1);
free(private);
}
return 0;
}
Expand Down

0 comments on commit 72ff894

Please sign in to comment.