aboutsummaryrefslogtreecommitdiffstats
path: root/transport-helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'transport-helper.c')
-rw-r--r--transport-helper.c115
1 files changed, 69 insertions, 46 deletions
diff --git a/transport-helper.c b/transport-helper.c
index 49811ef176..bc27653cde 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -1,15 +1,15 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "git-compat-util.h"
#include "transport.h"
#include "quote.h"
#include "run-command.h"
#include "commit.h"
-#include "diff.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
#include "object-name.h"
#include "repository.h"
-#include "revision.h"
#include "remote.h"
#include "string-list.h"
#include "thread-utils.h"
@@ -19,11 +19,12 @@
#include "refspec.h"
#include "transport-internal.h"
#include "protocol.h"
+#include "packfile.h"
static int debug;
struct helper_data {
- const char *name;
+ char *name;
struct child_process *helper;
FILE *out;
unsigned fetch : 1,
@@ -88,11 +89,18 @@ static int recvline(struct helper_data *helper, struct strbuf *buffer)
return recvline_fh(helper->out, buffer);
}
-static void write_constant(int fd, const char *str)
+static int write_constant_gently(int fd, const char *str)
{
if (debug)
fprintf(stderr, "Debug: Remote helper: -> %s", str);
if (write_in_full(fd, str, strlen(str)) < 0)
+ return -1;
+ return 0;
+}
+
+static void write_constant(int fd, const char *str)
+{
+ if (write_constant_gently(fd, str) < 0)
die_errno(_("full write to remote helper failed"));
}
@@ -112,6 +120,7 @@ static void do_take_over(struct transport *transport)
data = (struct helper_data *)transport->data;
transport_take_over(transport, data->helper);
fclose(data->out);
+ free(data->name);
free(data);
}
@@ -141,7 +150,7 @@ static struct child_process *get_helper(struct transport *transport)
if (have_git_dir())
strvec_pushf(&helper->env, "%s=%s",
- GIT_DIR_ENVIRONMENT, get_git_dir());
+ GIT_DIR_ENVIRONMENT, repo_get_git_dir(the_repository));
helper->trace2_child_class = helper->args.v[0]; /* "remote-<name>" */
@@ -166,13 +175,16 @@ static struct child_process *get_helper(struct transport *transport)
die_errno(_("can't dup helper output fd"));
data->out = xfdopen(duped, "r");
- write_constant(helper->in, "capabilities\n");
+ sigchain_push(SIGPIPE, SIG_IGN);
+ if (write_constant_gently(helper->in, "capabilities\n") < 0)
+ die("remote helper '%s' aborted session", data->name);
+ sigchain_pop(SIGPIPE);
while (1) {
const char *capname, *arg;
int mandatory = 0;
if (recvline(data, &buf))
- exit(128);
+ die("remote helper '%s' aborted session", data->name);
if (!*buf.buf)
break;
@@ -254,6 +266,7 @@ static int disconnect_helper(struct transport *transport)
close(data->helper->out);
fclose(data->out);
res = finish_command(data->helper);
+ FREE_AND_NULL(data->name);
FREE_AND_NULL(data->helper);
}
return res;
@@ -386,6 +399,8 @@ static int release_helper(struct transport *transport)
int res = 0;
struct helper_data *data = transport->data;
refspec_clear(&data->rs);
+ free(data->import_marks);
+ free(data->export_marks);
res = disconnect_helper(transport);
free(transport->data);
return res;
@@ -434,6 +449,8 @@ static int fetch_with_fetch(struct transport *transport,
warning(_("%s unexpectedly said: '%s'"), data->name, buf.buf);
}
strbuf_release(&buf);
+
+ reprepare_packed_git(the_repository);
return 0;
}
@@ -550,7 +567,7 @@ static int fetch_with_import(struct transport *transport,
else
private = xstrdup(name);
if (private) {
- if (read_ref(private, &posn->old_oid) < 0)
+ if (refs_read_ref(get_main_ref_store(the_repository), private, &posn->old_oid) < 0)
die(_("could not read ref %s"), private);
free(private);
}
@@ -628,7 +645,8 @@ static int process_connect_service(struct transport *transport,
ret = run_connect(transport, &cmdbuf);
} else if (data->stateless_connect &&
(get_protocol_version_config() == protocol_v2) &&
- !strcmp("git-upload-pack", name)) {
+ (!strcmp("git-upload-pack", name) ||
+ !strcmp("git-upload-archive", name))) {
strbuf_addf(&cmdbuf, "stateless-connect %s\n", name);
ret = run_connect(transport, &cmdbuf);
if (ret)
@@ -645,6 +663,7 @@ static int process_connect(struct transport *transport,
struct helper_data *data = transport->data;
const char *name;
const char *exec;
+ int ret;
name = for_push ? "git-receive-pack" : "git-upload-pack";
if (for_push)
@@ -652,7 +671,10 @@ static int process_connect(struct transport *transport,
else
exec = data->transport_options.uploadpack;
- return process_connect_service(transport, name, exec);
+ ret = process_connect_service(transport, name, exec);
+ if (ret)
+ do_take_over(transport);
+ return ret;
}
static int connect_helper(struct transport *transport, const char *name,
@@ -662,14 +684,14 @@ static int connect_helper(struct transport *transport, const char *name,
/* Get_helper so connect is inited. */
get_helper(transport);
- if (!data->connect)
- die(_("operation not supported by protocol"));
if (!process_connect_service(transport, name, exec))
die(_("can't connect to subservice %s"), name);
fd[0] = data->helper->out;
fd[1] = data->helper->in;
+
+ do_take_over(transport);
return 0;
}
@@ -684,10 +706,8 @@ static int fetch_refs(struct transport *transport,
get_helper(transport);
- if (process_connect(transport, 0)) {
- do_take_over(transport);
+ if (process_connect(transport, 0))
return transport->vtable->fetch_refs(transport, nr_heads, to_fetch);
- }
/*
* If we reach here, then the server, the client, and/or the transport
@@ -699,8 +719,14 @@ static int fetch_refs(struct transport *transport,
return -1;
}
- if (!data->get_refs_list_called)
- get_refs_list_using_list(transport, 0);
+ if (!data->get_refs_list_called) {
+ /*
+ * We do not care about the list of refs returned, but only
+ * that the "list" command was sent.
+ */
+ struct ref *dummy = get_refs_list_using_list(transport, 0);
+ free_refs(dummy);
+ }
count = 0;
for (i = 0; i < nr_heads; i++)
@@ -919,8 +945,10 @@ static int push_update_refs_status(struct helper_data *data,
private = apply_refspecs(&data->rs, ref->name);
if (!private)
continue;
- update_ref("update by helper", private, &(ref->new_oid),
- NULL, 0, 0);
+ refs_update_ref(get_main_ref_store(the_repository),
+ "update by helper", private,
+ &(ref->new_oid),
+ NULL, 0, 0);
free(private);
} else {
for (report = ref->report; report; report = report->next) {
@@ -930,11 +958,12 @@ static int push_update_refs_status(struct helper_data *data,
: ref->name);
if (!private)
continue;
- update_ref("update by helper", private,
- report->new_oid
- ? report->new_oid
- : &(ref->new_oid),
- NULL, 0, 0);
+ refs_update_ref(get_main_ref_store(the_repository),
+ "update by helper", private,
+ report->new_oid
+ ? report->new_oid
+ : &(ref->new_oid),
+ NULL, 0, 0);
free(private);
}
}
@@ -1002,6 +1031,7 @@ static int push_refs_with_push(struct transport *transport,
if (atomic) {
reject_atomic_push(remote_refs, mirror);
string_list_clear(&cas_options, 0);
+ strbuf_release(&buf);
return 0;
} else
continue;
@@ -1074,7 +1104,7 @@ static int push_refs_with_export(struct transport *transport,
set_common_push_options(transport, data->name, flags);
if (flags & TRANSPORT_PUSH_FORCE) {
if (set_helper_option(transport, "force", "true") != 0)
- warning(_("helper %s does not support 'force'"), data->name);
+ warning(_("helper %s does not support '--force'"), data->name);
}
helper = get_helper(transport);
@@ -1101,9 +1131,11 @@ static int push_refs_with_export(struct transport *transport,
int flag;
/* Follow symbolic refs (mainly for HEAD). */
- name = resolve_ref_unsafe(ref->peer_ref->name,
- RESOLVE_REF_READING,
- &oid, &flag);
+ name = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ ref->peer_ref->name,
+ RESOLVE_REF_READING,
+ &oid,
+ &flag);
if (!name || !(flag & REF_ISSYMREF))
name = ref->peer_ref->name;
@@ -1144,10 +1176,8 @@ static int push_refs(struct transport *transport,
{
struct helper_data *data = transport->data;
- if (process_connect(transport, 1)) {
- do_take_over(transport);
+ if (process_connect(transport, 1))
return transport->vtable->push_refs(transport, remote_refs, flags);
- }
if (!remote_refs) {
fprintf(stderr,
@@ -1188,11 +1218,9 @@ static struct ref *get_refs_list(struct transport *transport, int for_push,
{
get_helper(transport);
- if (process_connect(transport, for_push)) {
- do_take_over(transport);
+ if (process_connect(transport, for_push))
return transport->vtable->get_refs_list(transport, for_push,
transport_options);
- }
return get_refs_list_using_list(transport, for_push);
}
@@ -1210,16 +1238,13 @@ static struct ref *get_refs_list_using_list(struct transport *transport,
data->get_refs_list_called = 1;
helper = get_helper(transport);
- if (data->object_format) {
- write_str_in_full(helper->in, "option object-format\n");
- if (recvline(data, &buf) || strcmp(buf.buf, "ok"))
- exit(128);
- }
+ if (data->object_format)
+ set_helper_option(transport, "object-format", "true");
if (data->push && for_push)
- write_str_in_full(helper->in, "list for-push\n");
+ write_constant(helper->in, "list for-push\n");
else
- write_str_in_full(helper->in, "list\n");
+ write_constant(helper->in, "list\n");
while (1) {
char *eov, *eon;
@@ -1255,7 +1280,7 @@ static struct ref *get_refs_list_using_list(struct transport *transport,
if (eon) {
if (has_attribute(eon + 1, "unchanged")) {
(*tail)->status |= REF_STATUS_UPTODATE;
- if (read_ref((*tail)->name, &(*tail)->old_oid) < 0)
+ if (refs_read_ref(get_main_ref_store(the_repository), (*tail)->name, &(*tail)->old_oid) < 0)
die(_("could not read ref %s"),
(*tail)->name);
}
@@ -1276,10 +1301,8 @@ static int get_bundle_uri(struct transport *transport)
{
get_helper(transport);
- if (process_connect(transport, 0)) {
- do_take_over(transport);
+ if (process_connect(transport, 0))
return transport->vtable->get_bundle_uri(transport);
- }
return -1;
}
@@ -1297,7 +1320,7 @@ static struct transport_vtable vtable = {
int transport_helper_init(struct transport *transport, const char *name)
{
struct helper_data *data = xcalloc(1, sizeof(*data));
- data->name = name;
+ data->name = xstrdup(name);
transport_check_allowed(name);