6 #include "run-command.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
, tags
, force
, thin
= 1, verbose
;
14 static const char *receivepack
;
16 #define BUF_SIZE (2084)
17 static char buffer
[BUF_SIZE
];
19 static const char **refspec
;
20 static int refspec_nr
;
22 static void add_refspec(const char *ref
)
24 int nr
= refspec_nr
+ 1;
25 refspec
= xrealloc(refspec
, nr
* sizeof(char *));
30 static int expand_one_ref(const char *ref
, const unsigned char *sha1
, int flag
, void *cb_data
)
32 /* Ignore the "refs/" at the beginning of the refname */
35 if (!strncmp(ref
, "tags/", 5))
36 add_refspec(xstrdup(ref
));
40 static void expand_refspecs(void)
44 die("cannot mix '--all' and a refspec");
47 * No need to expand "--all" - we'll just use
48 * the "--all" flag to send-pack
54 for_each_ref(expand_one_ref
, NULL
);
57 static void set_refspecs(const char **refs
, int nr
)
61 for (pass
= 0; pass
< 2; pass
++) {
62 /* pass 0 counts and allocates, pass 1 fills */
64 for (i
= cnt
= 0; i
< nr
; i
++) {
65 if (!strcmp("tag", refs
[i
])) {
69 die("tag <tag> shorthand without <tag>");
71 len
= strlen(refs
[i
]) + 11;
73 strcpy(tag
, "refs/tags/");
81 refspec
[cnt
] = refs
[i
];
85 size_t bytes
= cnt
* sizeof(char *);
87 refspec
= xrealloc(refspec
, bytes
);
94 static int get_remotes_uri(const char *repo
, const char *uri
[MAX_URI
])
97 FILE *f
= fopen(git_path("remotes/%s", repo
), "r");
98 int has_explicit_refspec
= refspec_nr
|| all
|| tags
;
102 while (fgets(buffer
, BUF_SIZE
, f
)) {
106 if (!strncmp("URL:", buffer
, 4)) {
109 } else if (!strncmp("Push:", buffer
, 5)) {
115 /* Remove whitespace at the head.. */
121 /* ..and at the end */
123 while (isspace(p
[-1]))
128 uri
[n
++] = xstrdup(s
);
130 error("more than %d URL's specified, ignoring the rest", MAX_URI
);
132 else if (is_refspec
&& !has_explicit_refspec
)
133 add_refspec(xstrdup(s
));
137 die("remote '%s' has no URL", repo
);
141 static const char **config_uri
;
142 static const char *config_repo
;
143 static int config_repo_len
;
144 static int config_current_uri
;
145 static int config_get_refspecs
;
146 static int config_get_receivepack
;
148 static int get_remote_config(const char* key
, const char* value
)
150 if (!strncmp(key
, "remote.", 7) &&
151 !strncmp(key
+ 7, config_repo
, config_repo_len
)) {
152 if (!strcmp(key
+ 7 + config_repo_len
, ".url")) {
153 if (config_current_uri
< MAX_URI
)
154 config_uri
[config_current_uri
++] = xstrdup(value
);
156 error("more than %d URL's specified, ignoring the rest", MAX_URI
);
158 else if (config_get_refspecs
&&
159 !strcmp(key
+ 7 + config_repo_len
, ".push"))
160 add_refspec(xstrdup(value
));
161 else if (config_get_receivepack
&&
162 !strcmp(key
+ 7 + config_repo_len
, ".receivepack")) {
164 char *rp
= xmalloc(strlen(value
) + 16);
165 sprintf(rp
, "--receive-pack=%s", value
);
168 error("more than one receivepack given, using the first");
174 static int get_config_remotes_uri(const char *repo
, const char *uri
[MAX_URI
])
176 config_repo_len
= strlen(repo
);
178 config_current_uri
= 0;
180 config_get_refspecs
= !(refspec_nr
|| all
|| tags
);
181 config_get_receivepack
= (receivepack
== NULL
);
183 git_config(get_remote_config
);
184 return config_current_uri
;
187 static int get_branches_uri(const char *repo
, const char *uri
[MAX_URI
])
189 const char *slash
= strchr(repo
, '/');
190 int n
= slash
? slash
- repo
: 1000;
191 FILE *f
= fopen(git_path("branches/%.*s", n
, repo
), "r");
197 s
= fgets(buffer
, BUF_SIZE
, f
);
206 while (isspace(p
[-1]))
210 len
+= strlen(slash
);
211 p
= xmalloc(len
+ 1);
220 * Read remotes and branches file, fill the push target URI
221 * list. If there is no command line refspecs, read Push: lines
222 * to set up the *refspec list as well.
223 * return the number of push target URIs
225 static int read_config(const char *repo
, const char *uri
[MAX_URI
])
230 n
= get_remotes_uri(repo
, uri
);
234 n
= get_config_remotes_uri(repo
, uri
);
238 n
= get_branches_uri(repo
, uri
);
247 static int do_push(const char *repo
)
249 const char *uri
[MAX_URI
];
255 n
= read_config(repo
, uri
);
257 die("bad repository '%s'", repo
);
259 argv
= xmalloc((refspec_nr
+ 10) * sizeof(char *));
260 argv
[0] = "dummy-send-pack";
263 argv
[argc
++] = "--all";
265 argv
[argc
++] = "--force";
267 argv
[argc
++] = receivepack
;
270 for (i
= 0; i
< n
; i
++) {
272 int dest_argc
= common_argc
;
273 int dest_refspec_nr
= refspec_nr
;
274 const char **dest_refspec
= refspec
;
275 const char *dest
= uri
[i
];
276 const char *sender
= "git-send-pack";
277 if (!strncmp(dest
, "http://", 7) ||
278 !strncmp(dest
, "https://", 8))
279 sender
= "git-http-push";
281 argv
[dest_argc
++] = "--thin";
283 argv
[dest_argc
++] = dest
;
284 while (dest_refspec_nr
--)
285 argv
[dest_argc
++] = *dest_refspec
++;
286 argv
[dest_argc
] = NULL
;
288 fprintf(stderr
, "Pushing to %s\n", dest
);
289 err
= run_command_v(argv
);
293 case -ERR_RUN_COMMAND_FORK
:
294 die("unable to fork for %s", sender
);
295 case -ERR_RUN_COMMAND_EXEC
:
296 die("unable to exec %s", sender
);
297 case -ERR_RUN_COMMAND_WAITPID
:
298 case -ERR_RUN_COMMAND_WAITPID_WRONG_PID
:
299 case -ERR_RUN_COMMAND_WAITPID_SIGNAL
:
300 case -ERR_RUN_COMMAND_WAITPID_NOEXIT
:
301 die("%s died with strange error", sender
);
309 int cmd_push(int argc
, const char **argv
, const char *prefix
)
312 const char *repo
= "origin"; /* default repository */
314 for (i
= 1; i
< argc
; i
++) {
315 const char *arg
= argv
[i
];
322 if (!strcmp(arg
, "-v")) {
326 if (!strncmp(arg
, "--repo=", 7)) {
330 if (!strcmp(arg
, "--all")) {
334 if (!strcmp(arg
, "--tags")) {
338 if (!strcmp(arg
, "--force") || !strcmp(arg
, "-f")) {
342 if (!strcmp(arg
, "--thin")) {
346 if (!strcmp(arg
, "--no-thin")) {
350 if (!strncmp(arg
, "--receive-pack=", 15)) {
354 if (!strncmp(arg
, "--exec=", 7)) {
360 set_refspecs(argv
+ i
, argc
- i
);
361 return do_push(repo
);