Skip to content

Commit

Permalink
ref namespaces: Support remote repositories via upload-pack and recei…
Browse files Browse the repository at this point in the history
…ve-pack

Change upload-pack and receive-pack to use the namespace-prefixed refs
when working with the repository, and use the unprefixed refs when
talking to the client, maintaining the masquerade.  This allows
clone, pull, fetch, and push to work with a suitably configured
GIT_NAMESPACE.

receive-pack advertises refs outside the current namespace as .have refs
(as it currently does for refs in alternates), so that the client can
use them to minimize data transfer but will otherwise ignore them.

With appropriate configuration, this also allows http-backend to expose
namespaces as multiple repositories with different paths.  This only
requires setting GIT_NAMESPACE, which http-backend passes through to
upload-pack and receive-pack.

Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Jamey Sharp <jamey@minilop.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
joshtriplett authored and gitster committed Jul 11, 2011
1 parent a1bea2c commit 6b01ecf
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 13 deletions.
45 changes: 39 additions & 6 deletions builtin/receive-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,25 @@ static int show_ref(const char *path, const unsigned char *sha1, int flag, void
return 0;
}

static int show_ref_cb(const char *path, const unsigned char *sha1, int flag, void *cb_data)
{
path = strip_namespace(path);
/*
* Advertise refs outside our current namespace as ".have"
* refs, so that the client can use them to minimize data
* transfer but will otherwise ignore them. This happens to
* cover ".have" that are thrown in by add_one_alternate_ref()
* to mark histories that are complete in our alternates as
* well.
*/
if (!path)
path = ".have";
return show_ref(path, sha1, flag, cb_data);
}

static void write_head_info(void)
{
for_each_ref(show_ref, NULL);
for_each_ref(show_ref_cb, NULL);
if (!sent_capabilities)
show_ref("capabilities^{}", null_sha1, 0, NULL);

Expand Down Expand Up @@ -332,6 +348,8 @@ static void refuse_unconfigured_deny_delete_current(void)
static const char *update(struct command *cmd)
{
const char *name = cmd->ref_name;
struct strbuf namespaced_name_buf = STRBUF_INIT;
const char *namespaced_name;
unsigned char *old_sha1 = cmd->old_sha1;
unsigned char *new_sha1 = cmd->new_sha1;
struct ref_lock *lock;
Expand All @@ -342,7 +360,10 @@ static const char *update(struct command *cmd)
return "funny refname";
}

if (is_ref_checked_out(name)) {
strbuf_addf(&namespaced_name_buf, "%s%s", get_git_namespace(), name);
namespaced_name = strbuf_detach(&namespaced_name_buf, NULL);

if (is_ref_checked_out(namespaced_name)) {
switch (deny_current_branch) {
case DENY_IGNORE:
break;
Expand Down Expand Up @@ -370,7 +391,7 @@ static const char *update(struct command *cmd)
return "deletion prohibited";
}

if (!strcmp(name, head_name)) {
if (!strcmp(namespaced_name, head_name)) {
switch (deny_delete_current) {
case DENY_IGNORE:
break;
Expand Down Expand Up @@ -426,14 +447,14 @@ static const char *update(struct command *cmd)
rp_warning("Allowing deletion of corrupt ref.");
old_sha1 = NULL;
}
if (delete_ref(name, old_sha1, 0)) {
if (delete_ref(namespaced_name, old_sha1, 0)) {
rp_error("failed to delete %s", name);
return "failed to delete";
}
return NULL; /* good */
}
else {
lock = lock_any_ref_for_update(name, old_sha1, 0);
lock = lock_any_ref_for_update(namespaced_name, old_sha1, 0);
if (!lock) {
rp_error("failed to lock %s", name);
return "failed to lock";
Expand Down Expand Up @@ -490,17 +511,29 @@ static void run_update_post_hook(struct command *commands)

static void check_aliased_update(struct command *cmd, struct string_list *list)
{
struct strbuf buf = STRBUF_INIT;
const char *dst_name;
struct string_list_item *item;
struct command *dst_cmd;
unsigned char sha1[20];
char cmd_oldh[41], cmd_newh[41], dst_oldh[41], dst_newh[41];
int flag;

const char *dst_name = resolve_ref(cmd->ref_name, sha1, 0, &flag);
strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name);
dst_name = resolve_ref(buf.buf, sha1, 0, &flag);
strbuf_release(&buf);

if (!(flag & REF_ISSYMREF))
return;

dst_name = strip_namespace(dst_name);
if (!dst_name) {
rp_error("refusing update to broken symref '%s'", cmd->ref_name);
cmd->skip_update = 1;
cmd->error_string = "broken symref";
return;
}

if ((item = string_list_lookup(list, dst_name)) == NULL)
return;

Expand Down
15 changes: 8 additions & 7 deletions upload-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -641,16 +641,17 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
" side-band-64k ofs-delta shallow no-progress"
" include-tag multi_ack_detailed";
struct object *o = parse_object(sha1);
const char *refname_nons = strip_namespace(refname);

if (!o)
die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));

if (capabilities)
packet_write(1, "%s %s%c%s%s\n", sha1_to_hex(sha1), refname,
packet_write(1, "%s %s%c%s%s\n", sha1_to_hex(sha1), refname_nons,
0, capabilities,
stateless_rpc ? " no-done" : "");
else
packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname);
packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname_nons);
capabilities = NULL;
if (!(o->flags & OUR_REF)) {
o->flags |= OUR_REF;
Expand All @@ -659,7 +660,7 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
if (o->type == OBJ_TAG) {
o = deref_tag(o, refname, 0);
if (o)
packet_write(1, "%s %s^{}\n", sha1_to_hex(o->sha1), refname);
packet_write(1, "%s %s^{}\n", sha1_to_hex(o->sha1), refname_nons);
}
return 0;
}
Expand All @@ -680,12 +681,12 @@ static void upload_pack(void)
{
if (advertise_refs || !stateless_rpc) {
reset_timeout();
head_ref(send_ref, NULL);
for_each_ref(send_ref, NULL);
head_ref_namespaced(send_ref, NULL);
for_each_namespaced_ref(send_ref, NULL);
packet_flush(1);
} else {
head_ref(mark_our_ref, NULL);
for_each_ref(mark_our_ref, NULL);
head_ref_namespaced(mark_our_ref, NULL);
for_each_namespaced_ref(mark_our_ref, NULL);
}
if (advertise_refs)
return;
Expand Down

0 comments on commit 6b01ecf

Please sign in to comment.