option old data in `.git/FETCH_HEAD` will be overwritten.
--depth=<depth>::
- Deepen or shorten the history of a 'shallow' repository created by
- `git clone` with `--depth=<depth>` option (see linkgit:git-clone[1])
- to the specified number of commits from the tip of each remote
- branch history. Tags for the deepened commits are not fetched.
+ Limit fetching to the specified number of commits from the tip of
+ each remote branch history. If fetching to a 'shallow' repository
+ created by `git clone` with `--depth=<depth>` option (see
+ linkgit:git-clone[1]), deepen or shorten the history to the specified
+ number of commits. Tags for the deepened commits are not fetched.
--unshallow::
If the source repository is complete, convert a shallow
reference to a commit that isn't already in the local submodule
clone.
+-j::
+--jobs=<n>::
+ Number of parallel children to be used for fetching submodules.
+ Each will fetch from different submodules, such that fetching many
+ submodules will be faster. By default submodules will be fetched
+ one at a time.
+
--no-recurse-submodules::
Disable recursive fetching of submodules (this has the same effect as
using the '--recurse-submodules=no' option).
by default when it is attached to a terminal, unless -q
is specified. This flag forces progress status even if the
standard error stream is not directed to a terminal.
+
+ -4::
+ --ipv4::
+ Use IPv4 addresses only, ignoring IPv6 addresses.
+
+ -6::
+ --ipv6::
+ Use IPv6 addresses only, ignoring IPv4 addresses.
--------
[verse]
'git push' [--all | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
- [--repo=<repository>] [-f | --force] [--prune] [-v | --verbose]
+ [--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-v | --verbose]
[-u | --set-upstream]
[--[no-]signed|--sign=(true|false|if-asked)]
[--force-with-lease[=<refname>[:<expect>]]]
default is --verify, giving the hook a chance to prevent the
push. With --no-verify, the hook is bypassed completely.
+ -4::
+ --ipv4::
+ Use IPv4 addresses only, ignoring IPv6 addresses.
+
+ -6::
+ --ipv6::
+ Use IPv6 addresses only, ignoring IPv4 addresses.
include::urls-remotes.txt[]
static char *option_upload_pack = "git-upload-pack";
static int option_verbosity;
static int option_progress = -1;
+ static enum transport_family family;
static struct string_list option_config;
static struct string_list option_reference;
static int option_dissociate;
N_("separate git dir from working tree")),
OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
N_("set config inside the new repository")),
+ OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
+ TRANSPORT_FAMILY_IPV4),
+ OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
+ TRANSPORT_FAMILY_IPV6),
OPT_END()
};
FILE *in = fopen(src->buf, "r");
struct strbuf line = STRBUF_INIT;
- while (strbuf_getline(&line, in, '\n') != EOF) {
+ while (strbuf_getline(&line, in) != EOF) {
char *abs_path;
if (!line.len || line.buf[0] == '#')
continue;
struct strbuf head_ref = STRBUF_INIT;
strbuf_addstr(&head_ref, branch_top);
strbuf_addstr(&head_ref, "HEAD");
- create_symref(head_ref.buf,
- remote_head_points_at->peer_ref->name,
- msg);
+ if (create_symref(head_ref.buf,
+ remote_head_points_at->peer_ref->name,
+ msg) < 0)
+ die("unable to update %s", head_ref.buf);
+ strbuf_release(&head_ref);
}
}
const char *head;
if (our && skip_prefix(our->name, "refs/heads/", &head)) {
/* Local default branch link */
- create_symref("HEAD", our->name, NULL);
+ if (create_symref("HEAD", our->name, NULL) < 0)
+ die("unable to update HEAD");
if (!option_bare) {
update_ref(msg, "HEAD", our->old_oid.hash, NULL, 0,
UPDATE_REFS_DIE_ON_ERR);
remote = remote_get(option_origin);
transport = transport_get(remote, remote->url[0]);
transport_set_verbosity(transport, option_verbosity, option_progress);
+ transport->family = family;
path = get_repo_path(remote->url[0], &is_bundle);
is_local = option_local != 0 && path && !is_bundle;
static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity;
static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
static int tags = TAGS_DEFAULT, unshallow, update_shallow;
+static int max_children = 1;
+ static enum transport_family family;
static const char *depth;
static const char *upload_pack;
static struct strbuf default_rla = STRBUF_INIT;
N_("fetch all tags and associated objects"), TAGS_SET),
OPT_SET_INT('n', NULL, &tags,
N_("do not fetch all tags (--no-tags)"), TAGS_UNSET),
+ OPT_INTEGER('j', "jobs", &max_children,
+ N_("number of submodules fetched in parallel")),
OPT_BOOL('p', "prune", &prune,
N_("prune remote-tracking branches no longer on remote")),
{ OPTION_CALLBACK, 0, "recurse-submodules", NULL, N_("on-demand"),
N_("accept refs that update .git/shallow")),
{ OPTION_CALLBACK, 0, "refmap", NULL, N_("refmap"),
N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg },
+ OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
+ TRANSPORT_FAMILY_IPV4),
+ OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
+ TRANSPORT_FAMILY_IPV6),
OPT_END()
};
static int truncate_fetch_head(void)
{
const char *filename = git_path_fetch_head();
- FILE *fp = fopen(filename, "w");
+ FILE *fp = fopen_for_writing(filename);
if (!fp)
return error(_("cannot open %s: %s\n"), filename, strerror(errno));
struct transport *transport;
transport = transport_get(remote, NULL);
transport_set_verbosity(transport, verbosity, progress);
+ transport->family = family;
if (upload_pack)
set_option(transport, TRANS_OPT_UPLOADPACK, upload_pack);
if (keep)
result = fetch_populated_submodules(&options,
submodule_prefix,
recurse_submodules,
- verbosity < 0);
+ verbosity < 0,
+ max_children);
argv_array_clear(&options);
}
list.strdup_strings = 1;
string_list_clear(&list, 0);
+ close_all_packs();
+
argv_array_pushl(&argv_gc_auto, "gc", "--auto", NULL);
if (verbosity < 0)
argv_array_push(&argv_gc_auto, "--quiet");
static int verbosity;
static int progress = -1;
static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
+ static enum transport_family family;
static struct push_cas_option cas;
unsigned int reject_reasons;
transport_set_verbosity(transport, verbosity, progress);
+ transport->family = family;
if (receivepack)
transport_set_option(transport,
OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL),
OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"),
(TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
- OPT_BOOL( 0, "delete", &deleterefs, N_("delete refs")),
+ OPT_BOOL('d', "delete", &deleterefs, N_("delete refs")),
OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")),
OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN),
OPT_BIT( 0, "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN),
0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the push"),
PARSE_OPT_OPTARG, option_parse_push_signed },
OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC),
+ OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
+ TRANSPORT_FAMILY_IPV4),
+ OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
+ TRANSPORT_FAMILY_IPV6),
OPT_END()
};
#include "gettext.h"
#include "transport.h"
+ #if LIBCURL_VERSION_NUM >= 0x070a08
+ long int git_curl_ipresolve = CURL_IPRESOLVE_WHATEVER;
+ #else
+ long int git_curl_ipresolve;
+ #endif
int active_requests;
int http_is_verbose;
size_t http_post_buffer = 16 * LARGE_PACKET_MAX;
static long curl_low_speed_time = -1;
static int curl_ftp_no_epsv;
static const char *curl_http_proxy;
+static const char *http_proxy_authmethod;
+static struct {
+ const char *name;
+ long curlauth_param;
+} proxy_authmethods[] = {
+ { "basic", CURLAUTH_BASIC },
+ { "digest", CURLAUTH_DIGEST },
+ { "negotiate", CURLAUTH_GSSNEGOTIATE },
+ { "ntlm", CURLAUTH_NTLM },
+#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
+ { "anyauth", CURLAUTH_ANY },
+#endif
+ /*
+ * CURLAUTH_DIGEST_IE has no corresponding command-line option in
+ * curl(1) and is not included in CURLAUTH_ANY, so we leave it out
+ * here, too
+ */
+};
+static struct credential proxy_auth = CREDENTIAL_INIT;
+static const char *curl_proxyuserpwd;
static const char *curl_cookie_file;
static int curl_save_cookies;
struct credential http_auth = CREDENTIAL_INIT;
#else
slot->results->auth_avail = 0;
#endif
+
+ curl_easy_getinfo(slot->curl, CURLINFO_HTTP_CONNECTCODE,
+ &slot->results->http_connectcode);
}
/* Run callback if appropriate */
if (!strcmp("http.proxy", var))
return git_config_string(&curl_http_proxy, var, value);
+ if (!strcmp("http.proxyauthmethod", var))
+ return git_config_string(&http_proxy_authmethod, var, value);
+
if (!strcmp("http.cookiefile", var))
return git_config_string(&curl_cookie_file, var, value);
if (!strcmp("http.savecookies", var)) {
#endif
}
+/* *var must be free-able */
+static void var_override(const char **var, char *value)
+{
+ if (value) {
+ free((void *)*var);
+ *var = xstrdup(value);
+ }
+}
+
+static void set_proxyauth_name_password(CURL *result)
+{
+#if LIBCURL_VERSION_NUM >= 0x071301
+ curl_easy_setopt(result, CURLOPT_PROXYUSERNAME,
+ proxy_auth.username);
+ curl_easy_setopt(result, CURLOPT_PROXYPASSWORD,
+ proxy_auth.password);
+#else
+ struct strbuf s = STRBUF_INIT;
+
+ strbuf_addstr_urlencode(&s, proxy_auth.username, 1);
+ strbuf_addch(&s, ':');
+ strbuf_addstr_urlencode(&s, proxy_auth.password, 1);
+ curl_proxyuserpwd = strbuf_detach(&s, NULL);
+ curl_easy_setopt(result, CURLOPT_PROXYUSERPWD, curl_proxyuserpwd);
+#endif
+}
+
+static void init_curl_proxy_auth(CURL *result)
+{
+ if (proxy_auth.username) {
+ if (!proxy_auth.password)
+ credential_fill(&proxy_auth);
+ set_proxyauth_name_password(result);
+ }
+
+ var_override(&http_proxy_authmethod, getenv("GIT_HTTP_PROXY_AUTHMETHOD"));
+
+#if LIBCURL_VERSION_NUM >= 0x070a07 /* CURLOPT_PROXYAUTH and CURLAUTH_ANY */
+ if (http_proxy_authmethod) {
+ int i;
+ for (i = 0; i < ARRAY_SIZE(proxy_authmethods); i++) {
+ if (!strcmp(http_proxy_authmethod, proxy_authmethods[i].name)) {
+ curl_easy_setopt(result, CURLOPT_PROXYAUTH,
+ proxy_authmethods[i].curlauth_param);
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(proxy_authmethods)) {
+ warning("unsupported proxy authentication method %s: using anyauth",
+ http_proxy_authmethod);
+ curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
+ }
+ }
+ else
+ curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
+#endif
+}
+
static int has_cert_password(void)
{
if (ssl_cert == NULL || ssl_cert_password_required != 1)
curl_easy_setopt(result, CURLOPT_USE_SSL, CURLUSESSL_TRY);
#endif
+ /*
+ * CURL also examines these variables as a fallback; but we need to query
+ * them here in order to decide whether to prompt for missing password (cf.
+ * init_curl_proxy_auth()).
+ *
+ * Unlike many other common environment variables, these are historically
+ * lowercase only. It appears that CURL did not know this and implemented
+ * only uppercase variants, which was later corrected to take both - with
+ * the exception of http_proxy, which is lowercase only also in CURL. As
+ * the lowercase versions are the historical quasi-standard, they take
+ * precedence here, as in CURL.
+ */
+ if (!curl_http_proxy) {
+ if (!strcmp(http_auth.protocol, "https")) {
+ var_override(&curl_http_proxy, getenv("HTTPS_PROXY"));
+ var_override(&curl_http_proxy, getenv("https_proxy"));
+ } else {
+ var_override(&curl_http_proxy, getenv("http_proxy"));
+ }
+ if (!curl_http_proxy) {
+ var_override(&curl_http_proxy, getenv("ALL_PROXY"));
+ var_override(&curl_http_proxy, getenv("all_proxy"));
+ }
+ }
+
if (curl_http_proxy) {
curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);
#if LIBCURL_VERSION_NUM >= 0x071800
curl_easy_setopt(result,
CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
#endif
+ if (strstr(curl_http_proxy, "://"))
+ credential_from_url(&proxy_auth, curl_http_proxy);
+ else {
+ struct strbuf url = STRBUF_INIT;
+ strbuf_addf(&url, "http://%s", curl_http_proxy);
+ credential_from_url(&proxy_auth, url.buf);
+ strbuf_release(&url);
+ }
+
+ curl_easy_setopt(result, CURLOPT_PROXY, proxy_auth.host);
}
-#if LIBCURL_VERSION_NUM >= 0x070a07
- curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
-#endif
+ init_curl_proxy_auth(result);
set_curl_keepalive(result);
if (remote && remote->http_proxy)
curl_http_proxy = xstrdup(remote->http_proxy);
+ if (remote)
+ var_override(&http_proxy_authmethod, remote->http_proxy_authmethod);
+
pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache");
no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
curl_http_proxy = NULL;
}
+ if (proxy_auth.password) {
+ memset(proxy_auth.password, 0, strlen(proxy_auth.password));
+ free(proxy_auth.password);
+ proxy_auth.password = NULL;
+ }
+
+ free((void *)curl_proxyuserpwd);
+ curl_proxyuserpwd = NULL;
+
+ free((void *)http_proxy_authmethod);
+ http_proxy_authmethod = NULL;
+
if (cert_auth.password != NULL) {
memset(cert_auth.password, 0, strlen(cert_auth.password));
free(cert_auth.password);
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1);
curl_easy_setopt(slot->curl, CURLOPT_RANGE, NULL);
+
+ #if LIBCURL_VERSION_NUM >= 0x070a08
+ curl_easy_setopt(slot->curl, CURLOPT_IPRESOLVE, git_curl_ipresolve);
+ #endif
#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, http_auth_methods);
#endif
if (results->curl_result == CURLE_OK) {
credential_approve(&http_auth);
+ if (proxy_auth.password)
+ credential_approve(&proxy_auth);
return HTTP_OK;
} else if (missing_target(results))
return HTTP_MISSING_TARGET;
return HTTP_REAUTH;
}
} else {
+ if (results->http_connectcode == 407)
+ credential_reject(&proxy_auth);
#if LIBCURL_VERSION_NUM >= 0x070c00
if (!curl_errorstr[0])
strlcpy(curl_errorstr,
CURLcode curl_result;
long http_code;
long auth_avail;
+ long http_connectcode;
};
struct active_request_slot {
int proactive_auth);
extern void http_cleanup(void);
+ extern long int git_curl_ipresolve;
extern int active_requests;
extern int http_is_verbose;
extern size_t http_post_buffer;
else
return -1;
return 0;
+
+ #if LIBCURL_VERSION_NUM >= 0x070a08
+ } else if (!strcmp(name, "family")) {
+ if (!strcmp(value, "ipv4"))
+ git_curl_ipresolve = CURL_IPRESOLVE_V4;
+ else if (!strcmp(value, "ipv6"))
+ git_curl_ipresolve = CURL_IPRESOLVE_V6;
+ else if (!strcmp(value, "all"))
+ git_curl_ipresolve = CURL_IPRESOLVE_WHATEVER;
+ else
+ return -1;
+ return 0;
+ #endif /* LIBCURL_VERSION_NUM >= 0x070a08 */
} else {
return 1 /* unsupported */;
}
die("http transport does not support %s", buf->buf);
strbuf_reset(buf);
- if (strbuf_getline(buf, stdin, '\n') == EOF)
+ if (strbuf_getline_lf(buf, stdin) == EOF)
return;
if (!*buf->buf)
break;
die("http transport does not support %s", buf->buf);
strbuf_reset(buf);
- if (strbuf_getline(buf, stdin, '\n') == EOF)
+ if (strbuf_getline_lf(buf, stdin) == EOF)
goto free_specs;
if (!*buf->buf)
break;
do {
const char *arg;
- if (strbuf_getline(&buf, stdin, '\n') == EOF) {
+ if (strbuf_getline_lf(&buf, stdin) == EOF) {
if (ferror(stdin))
error("remote-curl: error reading command stream from git");
return 1;
strbuf_reset(buffer);
if (debug)
fprintf(stderr, "Debug: Remote helper: Waiting...\n");
- if (strbuf_getline(buffer, helper, '\n') == EOF) {
+ if (strbuf_getline(buffer, helper) == EOF) {
if (debug)
fprintf(stderr, "Debug: Remote helper quit.\n");
return 1;
data->no_disconnect_req = 0;
/*
- * Open the output as FILE* so strbuf_getline() can be used.
+ * Open the output as FILE* so strbuf_getline_*() family of
+ * functions can be used.
* Do this with duped fd because fclose() will close the fd,
* and stuff like taking over will require the fd to remain.
*/
if (n >= sizeof(buf))
die("impossibly large verbosity value");
set_helper_option(t, "verbosity", buf);
+
+ switch (t->family) {
+ case TRANSPORT_FAMILY_ALL:
+ /*
+ * this is already the default,
+ * do not break old remote helpers by setting "all" here
+ */
+ break;
+ case TRANSPORT_FAMILY_IPV4:
+ set_helper_option(t, "family", "ipv4");
+ break;
+ case TRANSPORT_FAMILY_IPV6:
+ set_helper_option(t, "family", "ipv6");
+ break;
+ }
}
static int release_helper(struct transport *transport)
#include "sha1-array.h"
#include "sigchain.h"
-/* rsync support */
-
-/*
- * We copy packed-refs and refs/ into a temporary file, then read the
- * loose refs recursively (sorting whenever possible), and then inserting
- * those packed refs that are not yet in the list (not validating, but
- * assuming that the file is sorted).
- *
- * Appears refactoring this from refs.c is too cumbersome.
- */
-
-static int str_cmp(const void *a, const void *b)
-{
- const char *s1 = a;
- const char *s2 = b;
-
- return strcmp(s1, s2);
-}
-
-/* path->buf + name_offset is expected to point to "refs/" */
-
-static int read_loose_refs(struct strbuf *path, int name_offset,
- struct ref **tail)
-{
- DIR *dir = opendir(path->buf);
- struct dirent *de;
- struct {
- char **entries;
- int nr, alloc;
- } list;
- int i, pathlen;
-
- if (!dir)
- return -1;
-
- memset (&list, 0, sizeof(list));
-
- while ((de = readdir(dir))) {
- if (is_dot_or_dotdot(de->d_name))
- continue;
- ALLOC_GROW(list.entries, list.nr + 1, list.alloc);
- list.entries[list.nr++] = xstrdup(de->d_name);
- }
- closedir(dir);
-
- /* sort the list */
-
- qsort(list.entries, list.nr, sizeof(char *), str_cmp);
-
- pathlen = path->len;
- strbuf_addch(path, '/');
-
- for (i = 0; i < list.nr; i++, strbuf_setlen(path, pathlen + 1)) {
- strbuf_addstr(path, list.entries[i]);
- if (read_loose_refs(path, name_offset, tail)) {
- int fd = open(path->buf, O_RDONLY);
- char buffer[40];
- struct ref *next;
-
- if (fd < 0)
- continue;
- next = alloc_ref(path->buf + name_offset);
- if (read_in_full(fd, buffer, 40) != 40 ||
- get_oid_hex(buffer, &next->old_oid)) {
- close(fd);
- free(next);
- continue;
- }
- close(fd);
- (*tail)->next = next;
- *tail = next;
- }
- }
- strbuf_setlen(path, pathlen);
-
- for (i = 0; i < list.nr; i++)
- free(list.entries[i]);
- free(list.entries);
-
- return 0;
-}
-
-/* insert the packed refs for which no loose refs were found */
-
-static void insert_packed_refs(const char *packed_refs, struct ref **list)
-{
- FILE *f = fopen(packed_refs, "r");
- static char buffer[PATH_MAX];
-
- if (!f)
- return;
-
- for (;;) {
- int cmp = 0; /* assigned before used */
- int len;
-
- if (!fgets(buffer, sizeof(buffer), f)) {
- fclose(f);
- return;
- }
-
- if (!isxdigit(buffer[0]))
- continue;
- len = strlen(buffer);
- if (len && buffer[len - 1] == '\n')
- buffer[--len] = '\0';
- if (len < 41)
- continue;
- while ((*list)->next &&
- (cmp = strcmp(buffer + 41,
- (*list)->next->name)) > 0)
- list = &(*list)->next;
- if (!(*list)->next || cmp < 0) {
- struct ref *next = alloc_ref(buffer + 41);
- buffer[40] = '\0';
- if (get_oid_hex(buffer, &next->old_oid)) {
- warning ("invalid SHA-1: %s", buffer);
- free(next);
- continue;
- }
- next->next = (*list)->next;
- (*list)->next = next;
- list = &(*list)->next;
- }
- }
-}
-
static void set_upstreams(struct transport *transport, struct ref *refs,
int pretend)
{
}
}
-static const char *rsync_url(const char *url)
-{
- if (!starts_with(url, "rsync://"))
- skip_prefix(url, "rsync:", &url);
- return url;
-}
-
-static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
-{
- struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
- struct ref dummy = {NULL}, *tail = &dummy;
- struct child_process rsync = CHILD_PROCESS_INIT;
- const char *args[5];
- int temp_dir_len;
-
- if (for_push)
- return NULL;
-
- /* copy the refs to the temporary directory */
-
- strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
- if (!mkdtemp(temp_dir.buf))
- die_errno ("Could not make temporary directory");
- temp_dir_len = temp_dir.len;
-
- strbuf_addstr(&buf, rsync_url(transport->url));
- strbuf_addstr(&buf, "/refs");
-
- rsync.argv = args;
- rsync.stdout_to_stderr = 1;
- args[0] = "rsync";
- args[1] = (transport->verbose > 1) ? "-rv" : "-r";
- args[2] = buf.buf;
- args[3] = temp_dir.buf;
- args[4] = NULL;
-
- if (run_command(&rsync))
- die ("Could not run rsync to get refs");
-
- strbuf_reset(&buf);
- strbuf_addstr(&buf, rsync_url(transport->url));
- strbuf_addstr(&buf, "/packed-refs");
-
- args[2] = buf.buf;
-
- if (run_command(&rsync))
- die ("Could not run rsync to get refs");
-
- /* read the copied refs */
-
- strbuf_addstr(&temp_dir, "/refs");
- read_loose_refs(&temp_dir, temp_dir_len + 1, &tail);
- strbuf_setlen(&temp_dir, temp_dir_len);
-
- tail = &dummy;
- strbuf_addstr(&temp_dir, "/packed-refs");
- insert_packed_refs(temp_dir.buf, &tail);
- strbuf_setlen(&temp_dir, temp_dir_len);
-
- if (remove_dir_recursively(&temp_dir, 0))
- warning ("Error removing temporary directory %s.",
- temp_dir.buf);
-
- strbuf_release(&buf);
- strbuf_release(&temp_dir);
-
- return dummy.next;
-}
-
-static int fetch_objs_via_rsync(struct transport *transport,
- int nr_objs, struct ref **to_fetch)
-{
- struct child_process rsync = CHILD_PROCESS_INIT;
-
- rsync.stdout_to_stderr = 1;
- argv_array_push(&rsync.args, "rsync");
- argv_array_push(&rsync.args, (transport->verbose > 1) ? "-rv" : "-r");
- argv_array_push(&rsync.args, "--ignore-existing");
- argv_array_push(&rsync.args, "--exclude");
- argv_array_push(&rsync.args, "info");
- argv_array_pushf(&rsync.args, "%s/objects/", rsync_url(transport->url));
- argv_array_push(&rsync.args, get_object_directory());
-
- /* NEEDSWORK: handle one level of alternates */
- return run_command(&rsync);
-}
-
-static int write_one_ref(const char *name, const struct object_id *oid,
- int flags, void *data)
-{
- struct strbuf *buf = data;
- int len = buf->len;
-
- /* when called via for_each_ref(), flags is non-zero */
- if (flags && !starts_with(name, "refs/heads/") &&
- !starts_with(name, "refs/tags/"))
- return 0;
-
- strbuf_addstr(buf, name);
- if (safe_create_leading_directories(buf->buf) ||
- write_file_gently(buf->buf, "%s", oid_to_hex(oid)))
- return error("problems writing temporary file %s: %s",
- buf->buf, strerror(errno));
- strbuf_setlen(buf, len);
- return 0;
-}
-
-static int write_refs_to_temp_dir(struct strbuf *temp_dir,
- int refspec_nr, const char **refspec)
-{
- int i;
-
- for (i = 0; i < refspec_nr; i++) {
- struct object_id oid;
- char *ref;
-
- if (dwim_ref(refspec[i], strlen(refspec[i]), oid.hash, &ref) != 1)
- return error("Could not get ref %s", refspec[i]);
-
- if (write_one_ref(ref, &oid, 0, temp_dir)) {
- free(ref);
- return -1;
- }
- free(ref);
- }
- return 0;
-}
-
-static int rsync_transport_push(struct transport *transport,
- int refspec_nr, const char **refspec, int flags)
-{
- struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
- int result = 0, i;
- struct child_process rsync = CHILD_PROCESS_INIT;
- const char *args[10];
-
- if (flags & TRANSPORT_PUSH_MIRROR)
- return error("rsync transport does not support mirror mode");
-
- /* first push the objects */
-
- strbuf_addstr(&buf, rsync_url(transport->url));
- strbuf_addch(&buf, '/');
-
- rsync.argv = args;
- rsync.stdout_to_stderr = 1;
- i = 0;
- args[i++] = "rsync";
- args[i++] = "-a";
- if (flags & TRANSPORT_PUSH_DRY_RUN)
- args[i++] = "--dry-run";
- if (transport->verbose > 1)
- args[i++] = "-v";
- args[i++] = "--ignore-existing";
- args[i++] = "--exclude";
- args[i++] = "info";
- args[i++] = get_object_directory();
- args[i++] = buf.buf;
- args[i++] = NULL;
-
- if (run_command(&rsync))
- return error("Could not push objects to %s",
- rsync_url(transport->url));
-
- /* copy the refs to the temporary directory; they could be packed. */
-
- strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
- if (!mkdtemp(temp_dir.buf))
- die_errno ("Could not make temporary directory");
- strbuf_addch(&temp_dir, '/');
-
- if (flags & TRANSPORT_PUSH_ALL) {
- if (for_each_ref(write_one_ref, &temp_dir))
- return -1;
- } else if (write_refs_to_temp_dir(&temp_dir, refspec_nr, refspec))
- return -1;
-
- i = 2;
- if (flags & TRANSPORT_PUSH_DRY_RUN)
- args[i++] = "--dry-run";
- if (!(flags & TRANSPORT_PUSH_FORCE))
- args[i++] = "--ignore-existing";
- args[i++] = temp_dir.buf;
- args[i++] = rsync_url(transport->url);
- args[i++] = NULL;
- if (run_command(&rsync))
- result = error("Could not push to %s",
- rsync_url(transport->url));
-
- if (remove_dir_recursively(&temp_dir, 0))
- warning ("Could not remove temporary directory %s.",
- temp_dir.buf);
-
- strbuf_release(&buf);
- strbuf_release(&temp_dir);
-
- return result;
-}
-
struct bundle_transport_data {
int fd;
struct bundle_header header;
if (data->conn)
return 0;
+ switch (transport->family) {
+ case TRANSPORT_FAMILY_ALL: break;
+ case TRANSPORT_FAMILY_IPV4: flags |= CONNECT_IPV4; break;
+ case TRANSPORT_FAMILY_IPV6: flags |= CONNECT_IPV6; break;
+ }
+
data->conn = git_connect(data->fd, transport->url,
for_push ? data->options.receivepack :
data->options.uploadpack,
if (helper) {
transport_helper_init(ret, helper);
} else if (starts_with(url, "rsync:")) {
- transport_check_allowed("rsync");
- ret->get_refs_list = get_refs_via_rsync;
- ret->fetch = fetch_objs_via_rsync;
- ret->push = rsync_transport_push;
- ret->smart_options = NULL;
+ die("git-over-rsync is no longer supported");
} else if (url_is_local_not_ssh(url) && is_file(url) && is_bundle(url, 1)) {
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
transport_check_allowed("file");