-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This moves the code to call push backends into a library that can be extended to make matching fetch and push decisions based on the URL it gets, and which could be changed to have built-in implementations instead of calling external programs. Signed-off-by: Daniel Barkalow <barkalow@iabervon.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
- Loading branch information
Daniel Barkalow
authored and
Junio C Hamano
committed
Sep 19, 2007
1 parent
2d4177c
commit 9b28851
Showing
4 changed files
with
280 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
#include "cache.h" | ||
#include "transport.h" | ||
#include "run-command.h" | ||
|
||
static const struct transport_ops rsync_transport; | ||
|
||
static int curl_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags) { | ||
const char **argv; | ||
int argc; | ||
int err; | ||
|
||
argv = xmalloc((refspec_nr + 11) * sizeof(char *)); | ||
argv[0] = "http-push"; | ||
argc = 1; | ||
if (flags & TRANSPORT_PUSH_ALL) | ||
argv[argc++] = "--all"; | ||
if (flags & TRANSPORT_PUSH_FORCE) | ||
argv[argc++] = "--force"; | ||
argv[argc++] = transport->url; | ||
while (refspec_nr--) | ||
argv[argc++] = *refspec++; | ||
argv[argc] = NULL; | ||
err = run_command_v_opt(argv, RUN_GIT_CMD); | ||
switch (err) { | ||
case -ERR_RUN_COMMAND_FORK: | ||
error("unable to fork for %s", argv[0]); | ||
case -ERR_RUN_COMMAND_EXEC: | ||
error("unable to exec %s", argv[0]); | ||
break; | ||
case -ERR_RUN_COMMAND_WAITPID: | ||
case -ERR_RUN_COMMAND_WAITPID_WRONG_PID: | ||
case -ERR_RUN_COMMAND_WAITPID_SIGNAL: | ||
case -ERR_RUN_COMMAND_WAITPID_NOEXIT: | ||
error("%s died with strange error", argv[0]); | ||
} | ||
return !!err; | ||
} | ||
|
||
static const struct transport_ops curl_transport = { | ||
/* set_option */ NULL, | ||
/* push */ curl_transport_push | ||
}; | ||
|
||
static const struct transport_ops bundle_transport = { | ||
}; | ||
|
||
struct git_transport_data { | ||
unsigned thin : 1; | ||
|
||
const char *receivepack; | ||
}; | ||
|
||
static int set_git_option(struct transport *connection, | ||
const char *name, const char *value) | ||
{ | ||
struct git_transport_data *data = connection->data; | ||
if (!strcmp(name, TRANS_OPT_RECEIVEPACK)) { | ||
data->receivepack = value; | ||
return 0; | ||
} else if (!strcmp(name, TRANS_OPT_THIN)) { | ||
data->thin = !!value; | ||
return 0; | ||
} | ||
return 1; | ||
} | ||
|
||
static int git_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags) { | ||
struct git_transport_data *data = transport->data; | ||
const char **argv; | ||
char *rem; | ||
int argc; | ||
int err; | ||
|
||
argv = xmalloc((refspec_nr + 11) * sizeof(char *)); | ||
argv[0] = "send-pack"; | ||
argc = 1; | ||
if (flags & TRANSPORT_PUSH_ALL) | ||
argv[argc++] = "--all"; | ||
if (flags & TRANSPORT_PUSH_FORCE) | ||
argv[argc++] = "--force"; | ||
if (data->receivepack) { | ||
char *rp = xmalloc(strlen(data->receivepack) + 16); | ||
sprintf(rp, "--receive-pack=%s", data->receivepack); | ||
argv[argc++] = rp; | ||
} | ||
if (data->thin) | ||
argv[argc++] = "--thin"; | ||
rem = xmalloc(strlen(transport->remote->name) + 10); | ||
sprintf(rem, "--remote=%s", transport->remote->name); | ||
argv[argc++] = rem; | ||
argv[argc++] = transport->url; | ||
while (refspec_nr--) | ||
argv[argc++] = *refspec++; | ||
argv[argc] = NULL; | ||
err = run_command_v_opt(argv, RUN_GIT_CMD); | ||
switch (err) { | ||
case -ERR_RUN_COMMAND_FORK: | ||
error("unable to fork for %s", argv[0]); | ||
case -ERR_RUN_COMMAND_EXEC: | ||
error("unable to exec %s", argv[0]); | ||
break; | ||
case -ERR_RUN_COMMAND_WAITPID: | ||
case -ERR_RUN_COMMAND_WAITPID_WRONG_PID: | ||
case -ERR_RUN_COMMAND_WAITPID_SIGNAL: | ||
case -ERR_RUN_COMMAND_WAITPID_NOEXIT: | ||
error("%s died with strange error", argv[0]); | ||
} | ||
return !!err; | ||
} | ||
|
||
static const struct transport_ops git_transport = { | ||
/* set_option */ set_git_option, | ||
/* push */ git_transport_push | ||
}; | ||
|
||
static int is_local(const char *url) | ||
{ | ||
const char *colon = strchr(url, ':'); | ||
const char *slash = strchr(url, '/'); | ||
return !colon || (slash && slash < colon); | ||
} | ||
|
||
static int is_file(const char *url) | ||
{ | ||
struct stat buf; | ||
if (stat(url, &buf)) | ||
return 0; | ||
return S_ISREG(buf.st_mode); | ||
} | ||
|
||
struct transport *transport_get(struct remote *remote, const char *url, | ||
int fetch) | ||
{ | ||
struct transport *ret = NULL; | ||
if (!prefixcmp(url, "rsync://")) { | ||
ret = xmalloc(sizeof(*ret)); | ||
ret->data = NULL; | ||
ret->ops = &rsync_transport; | ||
} else if (!prefixcmp(url, "http://") || !prefixcmp(url, "https://") || | ||
!prefixcmp(url, "ftp://")) { | ||
ret = xmalloc(sizeof(*ret)); | ||
ret->ops = &curl_transport; | ||
ret->data = NULL; | ||
} else if (is_local(url) && is_file(url)) { | ||
ret = xmalloc(sizeof(*ret)); | ||
ret->data = NULL; | ||
ret->ops = &bundle_transport; | ||
} else { | ||
struct git_transport_data *data = xcalloc(1, sizeof(*data)); | ||
ret = xcalloc(1, sizeof(*ret)); | ||
ret->data = data; | ||
data->thin = 1; | ||
data->receivepack = "git-receive-pack"; | ||
if (remote && remote->receivepack) | ||
data->receivepack = remote->receivepack; | ||
ret->ops = &git_transport; | ||
} | ||
if (ret) { | ||
ret->remote = remote; | ||
ret->url = url; | ||
ret->fetch = !!fetch; | ||
} | ||
return ret; | ||
} | ||
|
||
int transport_set_option(struct transport *transport, | ||
const char *name, const char *value) | ||
{ | ||
int ret = 1; | ||
if (transport->ops->set_option) | ||
ret = transport->ops->set_option(transport, name, value); | ||
if (ret < 0) | ||
fprintf(stderr, "For '%s' option %s cannot be set to '%s'\n", | ||
transport->url, name, value); | ||
if (ret > 0) | ||
fprintf(stderr, "For '%s' option %s is ignored\n", | ||
transport->url, name); | ||
return ret; | ||
} | ||
|
||
int transport_push(struct transport *transport, | ||
int refspec_nr, const char **refspec, int flags) | ||
{ | ||
if (!transport->ops->push) | ||
return 1; | ||
return transport->ops->push(transport, refspec_nr, refspec, flags); | ||
} | ||
|
||
int transport_disconnect(struct transport *transport) | ||
{ | ||
int ret = 0; | ||
if (transport->ops->disconnect) | ||
ret = transport->ops->disconnect(transport); | ||
free(transport); | ||
return ret; | ||
} |
Oops, something went wrong.