git/transport-helper.c

#define USE_THE_REPOSITORY_VARIABLE

#include "git-compat-util.h"
#include "transport.h"
#include "quote.h"
#include "run-command.h"
#include "commit.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
#include "object-name.h"
#include "repository.h"
#include "remote.h"
#include "string-list.h"
#include "thread-utils.h"
#include "sigchain.h"
#include "strvec.h"
#include "refs.h"
#include "refspec.h"
#include "transport-internal.h"
#include "protocol.h"
#include "packfile.h"

static int debug;

struct helper_data {};

static void sendline(struct helper_data *helper, struct strbuf *buffer)
{}

static int recvline_fh(FILE *helper, struct strbuf *buffer)
{}

static int recvline(struct helper_data *helper, struct strbuf *buffer)
{}

static int write_constant_gently(int fd, const char *str)
{}

static void write_constant(int fd, const char *str)
{}

static const char *remove_ext_force(const char *url)
{}

static void do_take_over(struct transport *transport)
{}

static void standard_options(struct transport *t);

static struct child_process *get_helper(struct transport *transport)
{}

static int disconnect_helper(struct transport *transport)
{}

static const char *unsupported_options[] =;

static const char *boolean_options[] =;

static int strbuf_set_helper_option(struct helper_data *data,
				    struct strbuf *buf)
{}

static int string_list_set_helper_option(struct helper_data *data,
					 const char *name,
					 struct string_list *list)
{}

static int set_helper_option(struct transport *transport,
			  const char *name, const char *value)
{}

static void standard_options(struct transport *t)
{}

static int release_helper(struct transport *transport)
{}

static int fetch_with_fetch(struct transport *transport,
			    int nr_heads, struct ref **to_fetch)
{}

static int get_importer(struct transport *transport, struct child_process *fastimport)
{}

static int get_exporter(struct transport *transport,
			struct child_process *fastexport,
			struct string_list *revlist_args)
{}

static int fetch_with_import(struct transport *transport,
			     int nr_heads, struct ref **to_fetch)
{}

static int run_connect(struct transport *transport, struct strbuf *cmdbuf)
{}

static int process_connect_service(struct transport *transport,
				   const char *name, const char *exec)
{}

static int process_connect(struct transport *transport,
				     int for_push)
{}

static int connect_helper(struct transport *transport, const char *name,
		   const char *exec, int fd[2])
{}

static struct ref *get_refs_list_using_list(struct transport *transport,
					    int for_push);

static int fetch_refs(struct transport *transport,
		      int nr_heads, struct ref **to_fetch)
{}

struct push_update_ref_state {};

static int push_update_ref_status(struct strbuf *buf,
				   struct push_update_ref_state *state,
				   struct ref *remote_refs)
{}

static int push_update_refs_status(struct helper_data *data,
				    struct ref *remote_refs,
				    int flags)
{}

static void set_common_push_options(struct transport *transport,
				   const char *name, int flags)
{}

static int push_refs_with_push(struct transport *transport,
			       struct ref *remote_refs, int flags)
{}

static int push_refs_with_export(struct transport *transport,
		struct ref *remote_refs, int flags)
{}

static int push_refs(struct transport *transport,
		struct ref *remote_refs, int flags)
{}


static int has_attribute(const char *attrs, const char *attr)
{}

static struct ref *get_refs_list(struct transport *transport, int for_push,
				 struct transport_ls_refs_options *transport_options)
{}

static struct ref *get_refs_list_using_list(struct transport *transport,
					    int for_push)
{}

static int get_bundle_uri(struct transport *transport)
{}

static struct transport_vtable vtable =;

int transport_helper_init(struct transport *transport, const char *name)
{}

/*
 * Linux pipes can buffer 65536 bytes at once (and most platforms can
 * buffer less), so attempt reads and writes with up to that size.
 */
#define BUFFERSIZE
/* This should be enough to hold debugging message. */
#define PBUFFERSIZE

/* Print bidirectional transfer loop debug message. */
__attribute__((format (printf, 1, 2)))
static void transfer_debug(const char *fmt, ...)
{}

/* Stream state: More data may be coming in this direction. */
#define SSTATE_TRANSFERRING
/*
 * Stream state: No more data coming in this direction, flushing rest of
 * data.
 */
#define SSTATE_FLUSHING
/* Stream state: Transfer in this direction finished. */
#define SSTATE_FINISHED

#define STATE_NEEDS_READING(state)
#define STATE_NEEDS_WRITING(state)
#define STATE_NEEDS_CLOSING(state)

/* Unidirectional transfer. */
struct unidirectional_transfer {};

/* Closes the target (for writing) if transfer has finished. */
static void udt_close_if_finished(struct unidirectional_transfer *t)
{}

/*
 * Tries to read data from source into buffer. If buffer is full,
 * no data is read. Returns 0 on success, -1 on error.
 */
static int udt_do_read(struct unidirectional_transfer *t)
{}

/* Tries to write data from buffer into destination. If buffer is empty,
 * no data is written. Returns 0 on success, -1 on error.
 */
static int udt_do_write(struct unidirectional_transfer *t)
{}


/* State of bidirectional transfer loop. */
struct bidirectional_transfer_state {};

static void *udt_copy_task_routine(void *udt)
{}

#ifndef NO_PTHREADS

/*
 * Join thread, with appropriate errors on failure. Name is name for the
 * thread (for error messages). Returns 0 on success, 1 on failure.
 */
static int tloop_join(pthread_t thread, const char *name)
{}

/*
 * Spawn the transfer tasks and then wait for them. Returns 0 on success,
 * -1 on failure.
 */
static int tloop_spawnwait_tasks(struct bidirectional_transfer_state *s)
{}
#else

/* Close the source and target (for writing) for transfer. */
static void udt_kill_transfer(struct unidirectional_transfer *t)
{
	t->state = SSTATE_FINISHED;
	/*
	 * Socket read end left open isn't a disaster if nobody
	 * attempts to read from it (mingw compat headers do not
	 * have SHUT_RD)...
	 *
	 * We can't fully close the socket since otherwise gtp
	 * task would first close the socket it sends data to
	 * while closing the ptg file descriptors.
	 */
	if (!t->src_is_sock)
		close(t->src);
	if (t->dest_is_sock)
		shutdown(t->dest, SHUT_WR);
	else
		close(t->dest);
}

/*
 * Join process, with appropriate errors on failure. Name is name for the
 * process (for error messages). Returns 0 on success, 1 on failure.
 */
static int tloop_join(pid_t pid, const char *name)
{
	int tret;
	if (waitpid(pid, &tret, 0) < 0) {
		error_errno(_("%s process failed to wait"), name);
		return 1;
	}
	if (!WIFEXITED(tret) || WEXITSTATUS(tret)) {
		error(_("%s process failed"), name);
		return 1;
	}
	return 0;
}

/*
 * Spawn the transfer tasks and then wait for them. Returns 0 on success,
 * -1 on failure.
 */
static int tloop_spawnwait_tasks(struct bidirectional_transfer_state *s)
{
	pid_t pid1, pid2;
	int ret = 0;

	/* Fork thread #1: git to program. */
	pid1 = fork();
	if (pid1 < 0)
		die_errno(_("can't start thread for copying data"));
	else if (pid1 == 0) {
		udt_kill_transfer(&s->ptg);
		exit(udt_copy_task_routine(&s->gtp) ? 0 : 1);
	}

	/* Fork thread #2: program to git. */
	pid2 = fork();
	if (pid2 < 0)
		die_errno(_("can't start thread for copying data"));
	else if (pid2 == 0) {
		udt_kill_transfer(&s->gtp);
		exit(udt_copy_task_routine(&s->ptg) ? 0 : 1);
	}

	/*
	 * Close both streams in parent as to not interfere with
	 * end of file detection and wait for both tasks to finish.
	 */
	udt_kill_transfer(&s->gtp);
	udt_kill_transfer(&s->ptg);
	ret |= tloop_join(pid1, "Git to program copy");
	ret |= tloop_join(pid2, "Program to git copy");
	return ret;
}
#endif

/*
 * Copies data from stdin to output and from input to stdout simultaneously.
 * Additionally filtering through given filter. If filter is NULL, uses
 * identity filter.
 */
int bidirectional_transfer_loop(int input, int output)
{}

void reject_atomic_push(struct ref *remote_refs, int mirror_mode)
{}