git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
blob f02bb0ea15f80d9f2c455e867bcf3f49bc411acf 3194 bytes (raw)
name: builtin/upload-archive.c 	 # note: path name is non-authoritative(*)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
 
/*
 * Copyright (c) 2006 Franck Bui-Huu
 */
#include "cache.h"
#include "builtin.h"
#include "archive.h"
#include "pkt-line.h"
#include "sideband.h"
#include "run-command.h"
#include "strvec.h"

static const char upload_archive_usage[] =
	"git upload-archive <repo>";

static const char deadchild[] =
"git upload-archive: archiver died with error";

#define MAX_ARGS (64)

int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix)
{
	struct strvec sent_argv = STRVEC_INIT;
	const char *arg_cmd = "argument ";

	if (argc != 2 || !strcmp(argv[1], "-h"))
		usage(upload_archive_usage);

	if (!enter_repo(argv[1], 0))
		die("'%s' does not appear to be a git repository", argv[1]);

	init_archivers();

	/* put received options in sent_argv[] */
	strvec_push(&sent_argv, "git-upload-archive");
	for (;;) {
		char *buf = packet_read_line(0, NULL);
		if (!buf)
			break;	/* got a flush */
		if (sent_argv.argc > MAX_ARGS)
			die("Too many options (>%d)", MAX_ARGS - 1);

		if (!starts_with(buf, arg_cmd))
			die("'argument' token or flush expected");
		strvec_push(&sent_argv, buf + strlen(arg_cmd));
	}

	/* parse all options sent by the client */
	return write_archive(sent_argv.argc, sent_argv.argv, prefix,
			     the_repository, NULL, 1);
}

__attribute__((format (printf, 1, 2)))
static void error_clnt(const char *fmt, ...)
{
	struct strbuf buf = STRBUF_INIT;
	va_list params;

	va_start(params, fmt);
	strbuf_vaddf(&buf, fmt, params);
	va_end(params);
	send_sideband(1, 3, buf.buf, buf.len, LARGE_PACKET_MAX);
	die("sent error to the client: %s", buf.buf);
}

static ssize_t process_input(int child_fd, int band)
{
	char buf[16384];
	ssize_t sz = read(child_fd, buf, sizeof(buf));
	if (sz < 0) {
		if (errno != EAGAIN && errno != EINTR)
			error_clnt("read error: %s\n", strerror(errno));
		return sz;
	}
	send_sideband(1, band, buf, sz, LARGE_PACKET_MAX);
	return sz;
}

int cmd_upload_archive(int argc, const char **argv, const char *prefix)
{
	struct child_process writer = { argv };

	if (argc == 2 && !strcmp(argv[1], "-h"))
		usage(upload_archive_usage);

	/*
	 * Set up sideband subprocess.
	 *
	 * We (parent) monitor and read from child, sending its fd#1 and fd#2
	 * multiplexed out to our fd#1.  If the child dies, we tell the other
	 * end over channel #3.
	 */
	argv[0] = "upload-archive--writer";
	writer.out = writer.err = -1;
	writer.git_cmd = 1;
	if (start_command(&writer)) {
		int err = errno;
		packet_write_fmt(1, "NACK unable to spawn subprocess\n");
		die("upload-archive: %s", strerror(err));
	}

	packet_write_fmt(1, "ACK\n");
	packet_flush(1);

	while (1) {
		struct pollfd pfd[2];

		pfd[0].fd = writer.out;
		pfd[0].events = POLLIN;
		pfd[1].fd = writer.err;
		pfd[1].events = POLLIN;
		if (poll(pfd, 2, -1) < 0) {
			if (errno != EINTR) {
				error_errno("poll failed resuming");
				sleep(1);
			}
			continue;
		}
		if (pfd[1].revents & POLLIN)
			/* Status stream ready */
			if (process_input(pfd[1].fd, 2))
				continue;
		if (pfd[0].revents & POLLIN)
			/* Data stream ready */
			if (process_input(pfd[0].fd, 1))
				continue;

		if (finish_command(&writer))
			error_clnt("%s", deadchild);
		packet_flush(1);
		break;
	}
	return 0;
}

debug log:

solving f02bb0ea15 ...
found f02bb0ea15 in https://80x24.org/mirrors/git.git

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).