Code

Push code for transport library
[git.git] / builtin-push.c
1 /*
2  * "git push"
3  */
4 #include "cache.h"
5 #include "refs.h"
6 #include "run-command.h"
7 #include "builtin.h"
8 #include "remote.h"
9 #include "transport.h"
11 static const char push_usage[] = "git-push [--all] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]";
13 static int all, thin, verbose;
14 static const char *receivepack;
16 static const char **refspec;
17 static int refspec_nr;
19 static void add_refspec(const char *ref)
20 {
21         int nr = refspec_nr + 1;
22         refspec = xrealloc(refspec, nr * sizeof(char *));
23         refspec[nr-1] = ref;
24         refspec_nr = nr;
25 }
27 static void set_refspecs(const char **refs, int nr)
28 {
29         int i;
30         for (i = 0; i < nr; i++) {
31                 const char *ref = refs[i];
32                 if (!strcmp("tag", ref)) {
33                         char *tag;
34                         int len;
35                         if (nr <= ++i)
36                                 die("tag shorthand without <tag>");
37                         len = strlen(refs[i]) + 11;
38                         tag = xmalloc(len);
39                         strcpy(tag, "refs/tags/");
40                         strcat(tag, refs[i]);
41                         ref = tag;
42                 }
43                 add_refspec(ref);
44         }
45 }
47 static int do_push(const char *repo, int flags)
48 {
49         int i, errs;
50         struct remote *remote = remote_get(repo);
52         if (!remote)
53                 die("bad repository '%s'", repo);
55         if (!refspec && !all && remote->push_refspec_nr) {
56                 refspec = remote->push_refspec;
57                 refspec_nr = remote->push_refspec_nr;
58         }
59         errs = 0;
60         for (i = 0; i < remote->uri_nr; i++) {
61                 struct transport *transport =
62                         transport_get(remote, remote->uri[i], 0);
63                 int err;
64                 if (receivepack)
65                         transport_set_option(transport,
66                                              TRANS_OPT_RECEIVEPACK, receivepack);
67                 if (thin)
68                         transport_set_option(transport, TRANS_OPT_THIN, "yes");
70                 if (verbose)
71                         fprintf(stderr, "Pushing to %s\n", remote->uri[i]);
72                 err = transport_push(transport, refspec_nr, refspec, flags);
73                 err |= transport_disconnect(transport);
75                 if (!err)
76                         continue;
78                 error("failed to push to '%s'", remote->uri[i]);
79                 errs++;
80         }
81         return !!errs;
82 }
84 int cmd_push(int argc, const char **argv, const char *prefix)
85 {
86         int i;
87         int flags = 0;
88         const char *repo = NULL;        /* default repository */
90         for (i = 1; i < argc; i++) {
91                 const char *arg = argv[i];
93                 if (arg[0] != '-') {
94                         repo = arg;
95                         i++;
96                         break;
97                 }
98                 if (!strcmp(arg, "-v")) {
99                         verbose=1;
100                         continue;
101                 }
102                 if (!prefixcmp(arg, "--repo=")) {
103                         repo = arg+7;
104                         continue;
105                 }
106                 if (!strcmp(arg, "--all")) {
107                         flags |= TRANSPORT_PUSH_ALL;
108                         continue;
109                 }
110                 if (!strcmp(arg, "--tags")) {
111                         add_refspec("refs/tags/*");
112                         continue;
113                 }
114                 if (!strcmp(arg, "--force") || !strcmp(arg, "-f")) {
115                         flags |= TRANSPORT_PUSH_FORCE;
116                         continue;
117                 }
118                 if (!strcmp(arg, "--thin")) {
119                         thin = 1;
120                         continue;
121                 }
122                 if (!strcmp(arg, "--no-thin")) {
123                         thin = 0;
124                         continue;
125                 }
126                 if (!prefixcmp(arg, "--receive-pack=")) {
127                         receivepack = arg + 15;
128                         continue;
129                 }
130                 if (!prefixcmp(arg, "--exec=")) {
131                         receivepack = arg + 7;
132                         continue;
133                 }
134                 usage(push_usage);
135         }
136         set_refspecs(argv + i, argc - i);
137         if (all && refspec)
138                 usage(push_usage);
140         return do_push(repo, flags);