archive.c 14.6 KB
Newer Older
1 2
#include "cache.h"
#include "commit.h"
3
#include "tree-walk.h"
4
#include "attr.h"
5
#include "archive.h"
6
#include "parse-options.h"
7
#include "unpack-trees.h"
8
#include "dir.h"
9 10

static char const * const archive_usage[] = {
11
	N_("git archive [<options>] <tree-ish> [<path>...]"),
12
	N_("git archive --list"),
13
	N_("git archive --remote <repo> [--exec <cmd>] [<options>] <tree-ish> [<path>...]"),
14
	N_("git archive --remote <repo> [--exec <cmd>] --list"),
15 16
	NULL
};
17

18 19 20
static const struct archiver **archivers;
static int nr_archivers;
static int alloc_archivers;
21
static int remote_allow_unreachable;
22 23 24 25 26 27

void register_archiver(struct archiver *ar)
{
	ALLOC_GROW(archivers, nr_archivers + 1, alloc_archivers);
	archivers[nr_archivers++] = ar;
}
28

29 30 31 32 33
static void format_subst(const struct commit *commit,
                         const char *src, size_t len,
                         struct strbuf *buf)
{
	char *to_free = NULL;
34
	struct strbuf fmt = STRBUF_INIT;
35 36
	struct pretty_print_context ctx = {0};
	ctx.date_mode = DATE_NORMAL;
37
	ctx.abbrev = DEFAULT_ABBREV;
38 39 40 41 42 43 44

	if (src == buf->buf)
		to_free = strbuf_detach(buf, NULL);
	for (;;) {
		const char *b, *c;

		b = memmem(src, len, "$Format:", 8);
45
		if (!b)
46
			break;
47
		c = memchr(b + 8, '$', (src + len) - b - 8);
48 49 50 51 52 53 54
		if (!c)
			break;

		strbuf_reset(&fmt);
		strbuf_add(&fmt, b + 8, c - b - 8);

		strbuf_add(buf, src, b - src);
55
		format_commit_message(commit, fmt.buf, buf, &ctx);
56 57 58 59 60 61 62 63
		len -= c + 1 - src;
		src  = c + 1;
	}
	strbuf_add(buf, src, len);
	strbuf_release(&fmt);
	free(to_free);
}

64 65 66 67
void *sha1_file_to_archive(const struct archiver_args *args,
			   const char *path, const unsigned char *sha1,
			   unsigned int mode, enum object_type *type,
			   unsigned long *sizep)
68 69
{
	void *buffer;
70
	const struct commit *commit = args->convert ? args->commit : NULL;
71

72
	path += args->baselen;
73 74
	buffer = read_sha1_file(sha1, type, sizep);
	if (buffer && S_ISREG(mode)) {
75
		struct strbuf buf = STRBUF_INIT;
76 77 78 79
		size_t size = 0;

		strbuf_attach(&buf, buffer, *sizep, *sizep + 1);
		convert_to_working_tree(path, buf.buf, buf.len, &buf);
80 81
		if (commit)
			format_subst(commit, buf.buf, buf.len, &buf);
82 83 84 85 86 87 88
		buffer = strbuf_detach(&buf, &size);
		*sizep = size;
	}

	return buffer;
}

89
static void setup_archive_check(struct git_attr_check *check)
90 91
{
	static struct git_attr *attr_export_ignore;
92
	static struct git_attr *attr_export_subst;
93

94
	if (!attr_export_ignore) {
95 96
		attr_export_ignore = git_attr("export-ignore");
		attr_export_subst = git_attr("export-subst");
97
	}
98
	check[0].attr = attr_export_ignore;
99
	check[1].attr = attr_export_subst;
100
}
101

102 103 104 105 106 107 108 109 110
struct directory {
	struct directory *up;
	unsigned char sha1[20];
	int baselen, len;
	unsigned mode;
	int stage;
	char path[FLEX_ARRAY];
};

111 112 113
struct archiver_context {
	struct archiver_args *args;
	write_archive_entry_fn_t write_entry;
114
	struct directory *bottom;
115 116 117 118 119 120 121 122 123 124
};

static int write_archive_entry(const unsigned char *sha1, const char *base,
		int baselen, const char *filename, unsigned mode, int stage,
		void *context)
{
	static struct strbuf path = STRBUF_INIT;
	struct archiver_context *c = context;
	struct archiver_args *args = c->args;
	write_archive_entry_fn_t write_entry = c->write_entry;
125 126
	struct git_attr_check check[2];
	const char *path_without_prefix;
127 128
	int err;

129
	args->convert = 0;
130 131
	strbuf_reset(&path);
	strbuf_grow(&path, PATH_MAX);
132
	strbuf_add(&path, args->base, args->baselen);
133 134
	strbuf_add(&path, base, baselen);
	strbuf_addstr(&path, filename);
135 136
	if (S_ISDIR(mode) || S_ISGITLINK(mode))
		strbuf_addch(&path, '/');
137
	path_without_prefix = path.buf + args->baselen;
138

139
	setup_archive_check(check);
140
	if (!git_check_attr(path_without_prefix, ARRAY_SIZE(check), check)) {
141 142
		if (ATTR_TRUE(check[0].value))
			return 0;
143
		args->convert = ATTR_TRUE(check[1].value);
144
	}
145 146 147 148

	if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
		if (args->verbose)
			fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
149
		err = write_entry(args, sha1, path.buf, path.len, mode);
150 151
		if (err)
			return err;
152
		return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
153 154 155 156
	}

	if (args->verbose)
		fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
157
	return write_entry(args, sha1, path.buf, path.len, mode);
158 159
}

160 161 162 163 164 165 166 167
static int write_archive_entry_buf(const unsigned char *sha1, struct strbuf *base,
		const char *filename, unsigned mode, int stage,
		void *context)
{
	return write_archive_entry(sha1, base->buf, base->len,
				     filename, mode, stage, context);
}

168
static void queue_directory(const unsigned char *sha1,
169
		struct strbuf *base, const char *filename,
170 171 172
		unsigned mode, int stage, struct archiver_context *c)
{
	struct directory *d;
173
	d = xmallocz(sizeof(*d) + base->len + 1 + strlen(filename));
174
	d->up	   = c->bottom;
175
	d->baselen = base->len;
176 177 178
	d->mode	   = mode;
	d->stage   = stage;
	c->bottom  = d;
179
	d->len = sprintf(d->path, "%.*s%s/", (int)base->len, base->buf, filename);
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
	hashcpy(d->sha1, sha1);
}

static int write_directory(struct archiver_context *c)
{
	struct directory *d = c->bottom;
	int ret;

	if (!d)
		return 0;
	c->bottom = d->up;
	d->path[d->len - 1] = '\0'; /* no trailing slash */
	ret =
		write_directory(c) ||
		write_archive_entry(d->sha1, d->path, d->baselen,
				    d->path + d->baselen, d->mode,
				    d->stage, c) != READ_TREE_RECURSIVE;
	free(d);
	return ret ? -1 : 0;
}

static int queue_or_write_archive_entry(const unsigned char *sha1,
202
		struct strbuf *base, const char *filename,
203 204 205 206 207
		unsigned mode, int stage, void *context)
{
	struct archiver_context *c = context;

	while (c->bottom &&
208 209
	       !(base->len >= c->bottom->len &&
		 !strncmp(base->buf, c->bottom->path, c->bottom->len))) {
210 211 212 213 214 215
		struct directory *next = c->bottom->up;
		free(c->bottom);
		c->bottom = next;
	}

	if (S_ISDIR(mode)) {
216
		queue_directory(sha1, base, filename,
217 218 219 220 221 222
				mode, stage, c);
		return READ_TREE_RECURSIVE;
	}

	if (write_directory(c))
		return -1;
223
	return write_archive_entry(sha1, base->buf, base->len, filename, mode,
224 225 226
				   stage, context);
}

227 228 229 230
int write_archive_entries(struct archiver_args *args,
		write_archive_entry_fn_t write_entry)
{
	struct archiver_context context;
231 232
	struct unpack_trees_options opts;
	struct tree_desc t;
233 234 235 236 237 238 239 240 241 242
	int err;

	if (args->baselen > 0 && args->base[args->baselen - 1] == '/') {
		size_t len = args->baselen;

		while (len > 1 && args->base[len - 2] == '/')
			len--;
		if (args->verbose)
			fprintf(stderr, "%.*s\n", (int)len, args->base);
		err = write_entry(args, args->tree->object.sha1, args->base,
243
				  len, 040777);
244 245 246 247
		if (err)
			return err;
	}

248
	memset(&context, 0, sizeof(context));
249 250 251
	context.args = args;
	context.write_entry = write_entry;

252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
	/*
	 * Setup index and instruct attr to read index only
	 */
	if (!args->worktree_attributes) {
		memset(&opts, 0, sizeof(opts));
		opts.index_only = 1;
		opts.head_idx = -1;
		opts.src_index = &the_index;
		opts.dst_index = &the_index;
		opts.fn = oneway_merge;
		init_tree_desc(&t, args->tree->buffer, args->tree->size);
		if (unpack_trees(1, &t, &opts))
			return -1;
		git_attr_set_direction(GIT_ATTR_INDEX, &the_index);
	}

268
	err = read_tree_recursive(args->tree, "", 0, 0, &args->pathspec,
269 270
				  args->pathspec.has_wildcard ?
				  queue_or_write_archive_entry :
271
				  write_archive_entry_buf,
272
				  &context);
273 274
	if (err == READ_TREE_RECURSIVE)
		err = 0;
275 276 277 278 279
	while (context.bottom) {
		struct directory *next = context.bottom->up;
		free(context.bottom);
		context.bottom = next;
	}
280 281
	return err;
}
R
Rene Scharfe 已提交
282

283 284 285 286
static const struct archiver *lookup_archiver(const char *name)
{
	int i;

287 288 289
	if (!name)
		return NULL;

290 291 292
	for (i = 0; i < nr_archivers; i++) {
		if (!strcmp(name, archivers[i]->name))
			return archivers[i];
293 294 295 296
	}
	return NULL;
}

297 298
static int reject_entry(const unsigned char *sha1, struct strbuf *base,
			const char *filename, unsigned mode,
299 300
			int stage, void *context)
{
301 302 303
	int ret = -1;
	if (S_ISDIR(mode)) {
		struct strbuf sb = STRBUF_INIT;
304
		strbuf_addbuf(&sb, base);
305 306 307 308 309 310
		strbuf_addstr(&sb, filename);
		if (!match_pathspec(context, sb.buf, sb.len, 0, NULL, 1))
			ret = READ_TREE_RECURSIVE;
		strbuf_release(&sb);
	}
	return ret;
311 312 313 314
}

static int path_exists(struct tree *tree, const char *path)
{
315 316 317 318
	const char *paths[] = { path, NULL };
	struct pathspec pathspec;
	int ret;

319
	parse_pathspec(&pathspec, 0, 0, "", paths);
320 321 322
	pathspec.recursive = 1;
	ret = read_tree_recursive(tree, "", 0, 0, &pathspec,
				  reject_entry, &pathspec);
323 324
	free_pathspec(&pathspec);
	return ret != 0;
325 326
}

327 328 329
static void parse_pathspec_arg(const char **pathspec,
		struct archiver_args *ar_args)
{
330 331 332 333 334 335 336 337
	/*
	 * must be consistent with parse_pathspec in path_exists()
	 * Also if pathspec patterns are dependent, we're in big
	 * trouble as we test each one separately
	 */
	parse_pathspec(&ar_args->pathspec, 0,
		       PATHSPEC_PREFER_FULL,
		       "", pathspec);
338
	ar_args->pathspec.recursive = 1;
339 340
	if (pathspec) {
		while (*pathspec) {
341
			if (**pathspec && !path_exists(ar_args->tree, *pathspec))
342
				die(_("pathspec '%s' did not match any files"), *pathspec);
343 344 345
			pathspec++;
		}
	}
346 347 348
}

static void parse_treeish_arg(const char **argv,
349 350
		struct archiver_args *ar_args, const char *prefix,
		int remote)
351 352 353 354 355 356 357 358
{
	const char *name = argv[0];
	const unsigned char *commit_sha1;
	time_t archive_time;
	struct tree *tree;
	const struct commit *commit;
	unsigned char sha1[20];

359
	/* Remotes are only allowed to fetch actual refs */
360
	if (remote && !remote_allow_unreachable) {
361
		char *ref = NULL;
362 363
		const char *colon = strchrnul(name, ':');
		int refnamelen = colon - name;
364 365 366

		if (!dwim_ref(name, refnamelen, sha1, &ref))
			die("no such ref: %.*s", refnamelen, name);
367 368
		free(ref);
	}
369 370 371

	if (get_sha1(name, sha1))
		die("Not a valid object name");
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403

	commit = lookup_commit_reference_gently(sha1, 1);
	if (commit) {
		commit_sha1 = commit->object.sha1;
		archive_time = commit->date;
	} else {
		commit_sha1 = NULL;
		archive_time = time(NULL);
	}

	tree = parse_tree_indirect(sha1);
	if (tree == NULL)
		die("not a tree object");

	if (prefix) {
		unsigned char tree_sha1[20];
		unsigned int mode;
		int err;

		err = get_tree_entry(tree->object.sha1, prefix,
				     tree_sha1, &mode);
		if (err || !S_ISDIR(mode))
			die("current working directory is untracked");

		tree = parse_tree_indirect(tree_sha1);
	}
	ar_args->tree = tree;
	ar_args->commit_sha1 = commit_sha1;
	ar_args->commit = commit;
	ar_args->time = archive_time;
}

404 405 406 407 408 409 410
#define OPT__COMPR(s, v, h, p) \
	{ OPTION_SET_INT, (s), NULL, (v), NULL, (h), \
	  PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, (p) }
#define OPT__COMPR_HIDDEN(s, v, p) \
	{ OPTION_SET_INT, (s), NULL, (v), NULL, "", \
	  PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_HIDDEN, NULL, (p) }

411
static int parse_archive_args(int argc, const char **argv,
412
		const struct archiver **ar, struct archiver_args *args,
413
		const char *name_hint, int is_remote)
414
{
415
	const char *format = NULL;
416 417 418
	const char *base = NULL;
	const char *remote = NULL;
	const char *exec = NULL;
419
	const char *output = NULL;
420 421 422
	int compression_level = -1;
	int verbose = 0;
	int i;
423
	int list = 0;
424
	int worktree_attributes = 0;
425 426
	struct option opts[] = {
		OPT_GROUP(""),
427 428 429 430 431
		OPT_STRING(0, "format", &format, N_("fmt"), N_("archive format")),
		OPT_STRING(0, "prefix", &base, N_("prefix"),
			N_("prepend prefix to each pathname in the archive")),
		OPT_STRING('o', "output", &output, N_("file"),
			N_("write the archive to this file")),
J
Junio C Hamano 已提交
432
		OPT_BOOL(0, "worktree-attributes", &worktree_attributes,
433 434 435 436
			N_("read .gitattributes in working directory")),
		OPT__VERBOSE(&verbose, N_("report archived files on stderr")),
		OPT__COMPR('0', &compression_level, N_("store only"), 0),
		OPT__COMPR('1', &compression_level, N_("compress faster"), 1),
437 438 439 440 441 442 443
		OPT__COMPR_HIDDEN('2', &compression_level, 2),
		OPT__COMPR_HIDDEN('3', &compression_level, 3),
		OPT__COMPR_HIDDEN('4', &compression_level, 4),
		OPT__COMPR_HIDDEN('5', &compression_level, 5),
		OPT__COMPR_HIDDEN('6', &compression_level, 6),
		OPT__COMPR_HIDDEN('7', &compression_level, 7),
		OPT__COMPR_HIDDEN('8', &compression_level, 8),
444
		OPT__COMPR('9', &compression_level, N_("compress better"), 9),
445
		OPT_GROUP(""),
J
Junio C Hamano 已提交
446
		OPT_BOOL('l', "list", &list,
447
			N_("list supported archive formats")),
448
		OPT_GROUP(""),
449 450
		OPT_STRING(0, "remote", &remote, N_("repo"),
			N_("retrieve the archive from remote repository <repo>")),
451
		OPT_STRING(0, "exec", &exec, N_("command"),
452
			N_("path to the remote git-upload-archive command")),
453 454 455
		OPT_END()
	};

456
	argc = parse_options(argc, argv, NULL, opts, archive_usage, 0);
457 458 459 460 461

	if (remote)
		die("Unexpected option --remote");
	if (exec)
		die("Option --exec can only be used together with --remote");
462 463
	if (output)
		die("Unexpected option --output");
464 465 466 467 468

	if (!base)
		base = "";

	if (list) {
469
		for (i = 0; i < nr_archivers; i++)
470 471
			if (!is_remote || archivers[i]->flags & ARCHIVER_REMOTE)
				printf("%s\n", archivers[i]->name);
472
		exit(0);
473 474
	}

475 476 477 478 479
	if (!format && name_hint)
		format = archive_format_from_filename(name_hint);
	if (!format)
		format = "tar";

480
	/* We need at least one parameter -- tree-ish */
481 482
	if (argc < 1)
		usage_with_options(archive_usage, opts);
483
	*ar = lookup_archiver(format);
484
	if (!*ar || (is_remote && !((*ar)->flags & ARCHIVER_REMOTE)))
485 486 487 488
		die("Unknown archive format '%s'", format);

	args->compression_level = Z_DEFAULT_COMPRESSION;
	if (compression_level != -1) {
489
		if ((*ar)->flags & ARCHIVER_WANT_COMPRESSION_LEVELS)
490 491 492 493 494 495 496 497 498
			args->compression_level = compression_level;
		else {
			die("Argument not supported for format '%s': -%d",
					format, compression_level);
		}
	}
	args->verbose = verbose;
	args->base = base;
	args->baselen = strlen(base);
499
	args->worktree_attributes = worktree_attributes;
500

501
	return argc;
502 503
}

R
Rene Scharfe 已提交
504
int write_archive(int argc, const char **argv, const char *prefix,
505
		  int setup_prefix, const char *name_hint, int remote)
R
Rene Scharfe 已提交
506
{
507
	int nongit = 0;
R
Rene Scharfe 已提交
508 509 510 511
	const struct archiver *ar = NULL;
	struct archiver_args args;

	if (setup_prefix && prefix == NULL)
512 513
		prefix = setup_git_directory_gently(&nongit);

514 515 516
	git_config_get_bool("uploadarchive.allowunreachable", &remote_allow_unreachable);
	git_config(git_default_config, NULL);

517 518
	init_tar_archiver();
	init_zip_archiver();
519

520
	argc = parse_archive_args(argc, argv, &ar, &args, name_hint, remote);
521 522 523 524 525 526 527 528
	if (nongit) {
		/*
		 * We know this will die() with an error, so we could just
		 * die ourselves; but its error message will be more specific
		 * than what we could write here.
		 */
		setup_git_directory();
	}
R
Rene Scharfe 已提交
529

530
	parse_treeish_arg(argv, &args, prefix, remote);
R
Rene Scharfe 已提交
531 532
	parse_pathspec_arg(argv + 1, &args);

533
	return ar->write_archive(ar, &args);
R
Rene Scharfe 已提交
534
}
535

536 537 538 539 540 541 542 543 544
static int match_extension(const char *filename, const char *ext)
{
	int prefixlen = strlen(filename) - strlen(ext);

	/*
	 * We need 1 character for the '.', and 1 character to ensure that the
	 * prefix is non-empty (k.e., we don't match .tar.gz with no actual
	 * filename).
	 */
545
	if (prefixlen < 2 || filename[prefixlen - 1] != '.')
546 547 548 549
		return 0;
	return !strcmp(filename + prefixlen, ext);
}

550 551
const char *archive_format_from_filename(const char *filename)
{
552 553 554 555 556
	int i;

	for (i = 0; i < nr_archivers; i++)
		if (match_extension(filename, archivers[i]->name))
			return archivers[i]->name;
557 558
	return NULL;
}