Code

http-push: push <remote> :<branch> deletes remote branch
[git.git] / builtin-push.c
index 4b39ef3852a5dcb9b099527d4aafc33ba3bb6da1..9f727c00f689ae23373502c7fb21b2234a1c1748 100644 (file)
@@ -7,8 +7,12 @@
 #include "builtin.h"
 #include "remote.h"
 #include "transport.h"
+#include "parse-options.h"
 
-static const char push_usage[] = "git-push [--all] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]";
+static const char * const push_usage[] = {
+       "git-push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]",
+       NULL,
+};
 
 static int thin, verbose;
 static const char *receivepack;
@@ -40,6 +44,15 @@ static void set_refspecs(const char **refs, int nr)
                        strcat(tag, refs[i]);
                        ref = tag;
                }
+               if (!strcmp("HEAD", ref)) {
+                       unsigned char sha1_dummy[20];
+                       ref = resolve_ref(ref, sha1_dummy, 1, NULL);
+                       if (!ref)
+                               die("HEAD cannot be resolved.");
+                       if (prefixcmp(ref, "refs/heads/"))
+                               die("HEAD cannot be resolved to branch.");
+                       ref = xstrdup(ref + 11);
+               }
                add_refspec(ref);
        }
 }
@@ -77,7 +90,7 @@ static int do_push(const char *repo, int flags)
                if (!err)
                        continue;
 
-               error("failed to push to '%s'", remote->url[i]);
+               error("failed to push some refs to '%s'", remote->url[i]);
                errs++;
        }
        return !!errs;
@@ -85,63 +98,55 @@ static int do_push(const char *repo, int flags)
 
 int cmd_push(int argc, const char **argv, const char *prefix)
 {
-       int i;
        int flags = 0;
+       int all = 0;
+       int mirror = 0;
+       int dry_run = 0;
+       int force = 0;
+       int tags = 0;
        const char *repo = NULL;        /* default repository */
 
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
+       struct option options[] = {
+               OPT__VERBOSE(&verbose),
+               OPT_STRING( 0 , "repo", &repo, "repository", "repository"),
+               OPT_BOOLEAN( 0 , "all", &all, "push all refs"),
+               OPT_BOOLEAN( 0 , "mirror", &mirror, "mirror all refs"),
+               OPT_BOOLEAN( 0 , "tags", &tags, "push tags"),
+               OPT_BOOLEAN( 0 , "dry-run", &dry_run, "dry run"),
+               OPT_BOOLEAN('f', "force", &force, "force updates"),
+               OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
+               OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
+               OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"),
+               OPT_END()
+       };
 
-               if (arg[0] != '-') {
-                       repo = arg;
-                       i++;
-                       break;
-               }
-               if (!strcmp(arg, "-v")) {
-                       verbose=1;
-                       continue;
-               }
-               if (!prefixcmp(arg, "--repo=")) {
-                       repo = arg+7;
-                       continue;
-               }
-               if (!strcmp(arg, "--all")) {
-                       flags |= TRANSPORT_PUSH_ALL;
-                       continue;
-               }
-               if (!strcmp(arg, "--dry-run")) {
-                       flags |= TRANSPORT_PUSH_DRY_RUN;
-                       continue;
-               }
-               if (!strcmp(arg, "--tags")) {
-                       add_refspec("refs/tags/*");
-                       continue;
-               }
-               if (!strcmp(arg, "--force") || !strcmp(arg, "-f")) {
-                       flags |= TRANSPORT_PUSH_FORCE;
-                       continue;
-               }
-               if (!strcmp(arg, "--thin")) {
-                       thin = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "--no-thin")) {
-                       thin = 0;
-                       continue;
-               }
-               if (!prefixcmp(arg, "--receive-pack=")) {
-                       receivepack = arg + 15;
-                       continue;
-               }
-               if (!prefixcmp(arg, "--exec=")) {
-                       receivepack = arg + 7;
-                       continue;
-               }
-               usage(push_usage);
+       argc = parse_options(argc, argv, options, push_usage, 0);
+
+       if (force)
+               flags |= TRANSPORT_PUSH_FORCE;
+       if (dry_run)
+               flags |= TRANSPORT_PUSH_DRY_RUN;
+       if (verbose)
+               flags |= TRANSPORT_PUSH_VERBOSE;
+       if (tags)
+               add_refspec("refs/tags/*");
+       if (all)
+               flags |= TRANSPORT_PUSH_ALL;
+       if (mirror)
+               flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
+
+       if (argc > 0) {
+               repo = argv[0];
+               set_refspecs(argv + 1, argc - 1);
+       }
+       if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) && refspec)
+               usage_with_options(push_usage, options);
+
+       if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
+                               (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
+               error("--all and --mirror are incompatible");
+               usage_with_options(push_usage, options);
        }
-       set_refspecs(argv + i, argc - i);
-       if ((flags & TRANSPORT_PUSH_ALL) && refspec)
-               usage(push_usage);
 
        return do_push(repo, flags);
 }