X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=builtin-receive-pack.c;h=2c0225c89a44a28150806608ea3956c44e27ef6f;hb=7429ed2bad6297f0aef921b83083c572975fde71;hp=6d6027ead17b86519d69c3dfc9b98c01e916d277;hpb=be5908aed35d1c129f1ea38913b230ee1927361b;p=git.git diff --git a/builtin-receive-pack.c b/builtin-receive-pack.c index 6d6027ead..2c0225c89 100644 --- a/builtin-receive-pack.c +++ b/builtin-receive-pack.c @@ -6,9 +6,12 @@ #include "exec_cmd.h" #include "commit.h" #include "object.h" +#include "remote.h" +#include "transport.h" static const char receive_pack_usage[] = "git-receive-pack "; +static int deny_deletes = 0; static int deny_non_fast_forwards = 0; static int receive_fsck_objects; static int receive_unpack_limit = -1; @@ -21,6 +24,11 @@ static int capabilities_sent; static int receive_pack_config(const char *var, const char *value, void *cb) { + if (strcmp(var, "receive.denydeletes") == 0) { + deny_deletes = git_config_bool(var, value); + return 0; + } + if (strcmp(var, "receive.denynonfastforwards") == 0) { deny_non_fast_forwards = git_config_bool(var, value); return 0; @@ -183,6 +191,12 @@ static const char *update(struct command *cmd) "but I can't find it!", sha1_to_hex(new_sha1)); return "bad pack"; } + if (deny_deletes && is_null_sha1(new_sha1) && + !is_null_sha1(old_sha1) && + !prefixcmp(name, "refs/heads/")) { + error("denying ref deletion for %s", name); + return "deletion prohibited"; + } if (deny_non_fast_forwards && !is_null_sha1(new_sha1) && !is_null_sha1(old_sha1) && !prefixcmp(name, "refs/heads/")) { @@ -462,6 +476,45 @@ static int delete_only(struct command *cmd) return 1; } +static int add_refs_from_alternate(struct alternate_object_database *e, void *unused) +{ + char *other; + size_t len; + struct remote *remote; + struct transport *transport; + const struct ref *extra; + + e->name[-1] = '\0'; + other = xstrdup(make_absolute_path(e->base)); + e->name[-1] = '/'; + len = strlen(other); + + while (other[len-1] == '/') + other[--len] = '\0'; + if (len < 8 || memcmp(other + len - 8, "/objects", 8)) + return 0; + /* Is this a git repository with refs? */ + memcpy(other + len - 8, "/refs", 6); + if (!is_directory(other)) + return 0; + other[len - 8] = '\0'; + remote = remote_get(other); + transport = transport_get(remote, other); + for (extra = transport_get_remote_refs(transport); + extra; + extra = extra->next) { + add_extra_ref(".have", extra->old_sha1, 0); + } + transport_disconnect(transport); + free(other); + return 0; +} + +static void add_alternate_refs(void) +{ + foreach_alt_odb(add_refs_from_alternate, NULL); +} + int cmd_receive_pack(int argc, const char **argv, const char *prefix) { int i; @@ -497,7 +550,9 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) else if (0 <= receive_unpack_limit) unpack_limit = receive_unpack_limit; + add_alternate_refs(); write_head_info(); + clear_extra_refs(); /* EOF */ packet_flush(1);