aboutsummaryrefslogtreecommitdiff
path: root/receive-pack.c
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2006-11-24 00:26:49 -0800
committerJunio C Hamano <junkio@cox.net>2006-11-24 03:59:05 -0800
commitd4f694ba89857a87e259557d0f236c761b4041ef (patch)
tree08453ccc3a39a74ad5e74ff4bf1cf13dd88b85c7 /receive-pack.c
parent634b8d05142a4812bf35fe8b14cc62c84494c78f (diff)
downloadgit-d4f694ba89857a87e259557d0f236c761b4041ef.tar.gz
git-d4f694ba89857a87e259557d0f236c761b4041ef.tar.xz
Allow git push to delete remote ref.
This allows you to say git send-pack $URL :refs/heads/$branch to delete the named remote branch. The refspec $src:$dst means replace the destination ref with the object known as $src on the local side, so this is a natural extension to make an empty $src mean "No object" to delete the target. Signed-off-by: Junio C Hamano <junkio@cox.net>
Diffstat (limited to 'receive-pack.c')
-rw-r--r--receive-pack.c45
1 files changed, 34 insertions, 11 deletions
diff --git a/receive-pack.c b/receive-pack.c
index d56898c9b..1a141dc1e 100644
--- a/receive-pack.c
+++ b/receive-pack.c
@@ -14,7 +14,7 @@ static int deny_non_fast_forwards = 0;
static int unpack_limit = 5000;
static int report_status;
-static char capabilities[] = "report-status";
+static char capabilities[] = " report-status delete-refs ";
static int capabilities_sent;
static int receive_pack_config(const char *var, const char *value)
@@ -113,12 +113,14 @@ static int update(struct command *cmd)
strcpy(new_hex, sha1_to_hex(new_sha1));
strcpy(old_hex, sha1_to_hex(old_sha1));
- if (!has_sha1_file(new_sha1)) {
+
+ if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {
cmd->error_string = "bad pack";
return error("unpack should have generated %s, "
"but I can't find it!", new_hex);
}
- if (deny_non_fast_forwards && !is_null_sha1(old_sha1)) {
+ if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
+ !is_null_sha1(old_sha1)) {
struct commit *old_commit, *new_commit;
struct commit_list *bases, *ent;
@@ -138,14 +140,22 @@ static int update(struct command *cmd)
return error("hook declined to update %s", name);
}
- lock = lock_any_ref_for_update(name, old_sha1);
- if (!lock) {
- cmd->error_string = "failed to lock";
- return error("failed to lock %s", name);
+ if (is_null_sha1(new_sha1)) {
+ if (delete_ref(name, old_sha1)) {
+ cmd->error_string = "failed to delete";
+ return error("failed to delete %s", name);
+ }
+ fprintf(stderr, "%s: %s -> deleted\n", name, old_hex);
+ }
+ else {
+ lock = lock_any_ref_for_update(name, old_sha1);
+ if (!lock) {
+ cmd->error_string = "failed to lock";
+ return error("failed to lock %s", name);
+ }
+ write_ref_sha1(lock, new_sha1, "push");
+ fprintf(stderr, "%s: %s -> %s\n", name, old_hex, new_hex);
}
- write_ref_sha1(lock, new_sha1, "push");
-
- fprintf(stderr, "%s: %s -> %s\n", name, old_hex, new_hex);
return 0;
}
@@ -375,6 +385,16 @@ static void report(const char *unpack_status)
packet_flush(1);
}
+static int delete_only(struct command *cmd)
+{
+ while (cmd) {
+ if (!is_null_sha1(cmd->new_sha1))
+ return 0;
+ cmd = cmd->next;
+ }
+ return 1;
+}
+
int main(int argc, char **argv)
{
int i;
@@ -408,7 +428,10 @@ int main(int argc, char **argv)
read_head_info();
if (commands) {
- const char *unpack_status = unpack();
+ const char *unpack_status = NULL;
+
+ if (!delete_only(commands))
+ unpack_status = unpack();
if (!unpack_status)
execute_commands();
if (pack_lockfile)