archive.c 15.1 KB
Newer Older
1
#include "cache.h"
2
#include "config.h"
3
#include "refs.h"
4
#include "object-store.h"
5
#include "commit.h"
6
#include "tree-walk.h"
7
#include "attr.h"
8
#include "archive.h"
9
#include "parse-options.h"
10
#include "unpack-trees.h"
11
#include "dir.h"
12 13

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

21 22 23
static const struct archiver **archivers;
static int nr_archivers;
static int alloc_archivers;
24
static int remote_allow_unreachable;
25 26 27 28 29 30

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

32 33 34 35 36 37
void init_archivers(void)
{
	init_tar_archiver();
	init_zip_archiver();
}

38
static void format_subst(const struct commit *commit,
Duy Nguyen's avatar
Duy Nguyen committed
39 40
			 const char *src, size_t len,
			 struct strbuf *buf)
41 42
{
	char *to_free = NULL;
43
	struct strbuf fmt = STRBUF_INIT;
44
	struct pretty_print_context ctx = {0};
45
	ctx.date_mode.type = DATE_NORMAL;
46
	ctx.abbrev = DEFAULT_ABBREV;
47 48 49 50 51 52 53

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

		b = memmem(src, len, "$Format:", 8);
54
		if (!b)
55
			break;
56
		c = memchr(b + 8, '$', (src + len) - b - 8);
57 58 59 60 61 62 63
		if (!c)
			break;

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

		strbuf_add(buf, src, b - src);
64
		format_commit_message(commit, fmt.buf, buf, &ctx);
65 66 67 68 69 70 71 72
		len -= c + 1 - src;
		src  = c + 1;
	}
	strbuf_add(buf, src, len);
	strbuf_release(&fmt);
	free(to_free);
}

73 74 75 76
void *object_file_to_archive(const struct archiver_args *args,
			     const char *path, const struct object_id *oid,
			     unsigned int mode, enum object_type *type,
			     unsigned long *sizep)
77 78
{
	void *buffer;
79
	const struct commit *commit = args->convert ? args->commit : NULL;
80

81
	path += args->baselen;
82
	buffer = read_object_file(oid, type, sizep);
83
	if (buffer && S_ISREG(mode)) {
84
		struct strbuf buf = STRBUF_INIT;
85 86 87
		size_t size = 0;

		strbuf_attach(&buf, buffer, *sizep, *sizep + 1);
88
		convert_to_working_tree(args->repo->index, path, buf.buf, buf.len, &buf);
89 90
		if (commit)
			format_subst(commit, buf.buf, buf.len, &buf);
91 92 93 94 95 96 97
		buffer = strbuf_detach(&buf, &size);
		*sizep = size;
	}

	return buffer;
}

98 99
struct directory {
	struct directory *up;
100
	struct object_id oid;
101 102 103 104 105 106
	int baselen, len;
	unsigned mode;
	int stage;
	char path[FLEX_ARRAY];
};

107 108 109
struct archiver_context {
	struct archiver_args *args;
	write_archive_entry_fn_t write_entry;
110
	struct directory *bottom;
111 112
};

113 114
static const struct attr_check *get_archive_attrs(struct index_state *istate,
						  const char *path)
115 116 117 118
{
	static struct attr_check *check;
	if (!check)
		check = attr_check_initl("export-ignore", "export-subst", NULL);
119 120
	git_check_attr(istate, path, check);
	return check;
121 122 123 124 125 126 127 128 129 130 131 132
}

static int check_attr_export_ignore(const struct attr_check *check)
{
	return check && ATTR_TRUE(check->items[0].value);
}

static int check_attr_export_subst(const struct attr_check *check)
{
	return check && ATTR_TRUE(check->items[1].value);
}

133
static int write_archive_entry(const struct object_id *oid, const char *base,
134 135 136 137 138 139 140 141
		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;
	int err;
142
	const char *path_without_prefix;
143

144
	args->convert = 0;
145 146
	strbuf_reset(&path);
	strbuf_grow(&path, PATH_MAX);
147
	strbuf_add(&path, args->base, args->baselen);
148 149
	strbuf_add(&path, base, baselen);
	strbuf_addstr(&path, filename);
150 151
	if (S_ISDIR(mode) || S_ISGITLINK(mode))
		strbuf_addch(&path, '/');
152
	path_without_prefix = path.buf + args->baselen;
153

154
	if (!S_ISDIR(mode)) {
155
		const struct attr_check *check;
156
		check = get_archive_attrs(args->repo->index, path_without_prefix);
157
		if (check_attr_export_ignore(check))
158
			return 0;
159
		args->convert = check_attr_export_subst(check);
160
	}
161 162 163 164

	if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
		if (args->verbose)
			fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
165
		err = write_entry(args, oid, path.buf, path.len, mode);
166 167
		if (err)
			return err;
168
		return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
169 170 171 172
	}

	if (args->verbose)
		fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
173
	return write_entry(args, oid, path.buf, path.len, mode);
174 175
}

176
static void queue_directory(const unsigned char *sha1,
177
		struct strbuf *base, const char *filename,
178 179 180
		unsigned mode, int stage, struct archiver_context *c)
{
	struct directory *d;
181 182
	size_t len = st_add4(base->len, 1, strlen(filename), 1);
	d = xmalloc(st_add(sizeof(*d), len));
183
	d->up	   = c->bottom;
184
	d->baselen = base->len;
185 186 187
	d->mode	   = mode;
	d->stage   = stage;
	c->bottom  = d;
188
	d->len = xsnprintf(d->path, len, "%.*s%s/", (int)base->len, base->buf, filename);
189
	hashcpy(d->oid.hash, sha1);
190 191 192 193 194 195 196 197 198 199 200 201 202
}

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) ||
203
		write_archive_entry(&d->oid, d->path, d->baselen,
204 205 206 207 208 209
				    d->path + d->baselen, d->mode,
				    d->stage, c) != READ_TREE_RECURSIVE;
	free(d);
	return ret ? -1 : 0;
}

210
static int queue_or_write_archive_entry(const struct object_id *oid,
211
		struct strbuf *base, const char *filename,
212 213 214 215 216
		unsigned mode, int stage, void *context)
{
	struct archiver_context *c = context;

	while (c->bottom &&
217 218
	       !(base->len >= c->bottom->len &&
		 !strncmp(base->buf, c->bottom->path, c->bottom->len))) {
219 220 221 222 223 224
		struct directory *next = c->bottom->up;
		free(c->bottom);
		c->bottom = next;
	}

	if (S_ISDIR(mode)) {
225 226 227 228 229 230
		size_t baselen = base->len;
		const struct attr_check *check;

		/* Borrow base, but restore its original value when done. */
		strbuf_addstr(base, filename);
		strbuf_addch(base, '/');
231
		check = get_archive_attrs(c->args->repo->index, base->buf);
232 233 234 235
		strbuf_setlen(base, baselen);

		if (check_attr_export_ignore(check))
			return 0;
236
		queue_directory(oid->hash, base, filename,
237 238 239 240 241 242
				mode, stage, c);
		return READ_TREE_RECURSIVE;
	}

	if (write_directory(c))
		return -1;
243
	return write_archive_entry(oid, base->buf, base->len, filename, mode,
244 245 246
				   stage, context);
}

247 248 249 250
int write_archive_entries(struct archiver_args *args,
		write_archive_entry_fn_t write_entry)
{
	struct archiver_context context;
251 252
	struct unpack_trees_options opts;
	struct tree_desc t;
253 254 255 256 257 258 259 260 261
	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);
262
		err = write_entry(args, &args->tree->object.oid, args->base,
263
				  len, 040777);
264 265 266 267
		if (err)
			return err;
	}

268
	memset(&context, 0, sizeof(context));
269 270 271
	context.args = args;
	context.write_entry = write_entry;

272 273 274 275 276 277 278
	/*
	 * 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;
279 280
		opts.src_index = args->repo->index;
		opts.dst_index = args->repo->index;
281 282 283 284
		opts.fn = oneway_merge;
		init_tree_desc(&t, args->tree->buffer, args->tree->size);
		if (unpack_trees(1, &t, &opts))
			return -1;
285
		git_attr_set_direction(GIT_ATTR_INDEX);
286 287
	}

288 289
	err = read_tree_recursive(args->repo, args->tree, "",
				  0, 0, &args->pathspec,
290
				  queue_or_write_archive_entry,
291
				  &context);
292 293
	if (err == READ_TREE_RECURSIVE)
		err = 0;
294 295 296 297 298
	while (context.bottom) {
		struct directory *next = context.bottom->up;
		free(context.bottom);
		context.bottom = next;
	}
299 300
	return err;
}
301

302 303 304 305
static const struct archiver *lookup_archiver(const char *name)
{
	int i;

306 307 308
	if (!name)
		return NULL;

309 310 311
	for (i = 0; i < nr_archivers; i++) {
		if (!strcmp(name, archivers[i]->name))
			return archivers[i];
312 313 314 315
	}
	return NULL;
}

316 317 318 319 320
struct path_exists_context {
	struct pathspec pathspec;
	struct archiver_args *args;
};

321
static int reject_entry(const struct object_id *oid, struct strbuf *base,
322
			const char *filename, unsigned mode,
323 324
			int stage, void *context)
{
325
	int ret = -1;
326 327
	struct path_exists_context *ctx = context;

328 329
	if (S_ISDIR(mode)) {
		struct strbuf sb = STRBUF_INIT;
330
		strbuf_addbuf(&sb, base);
331
		strbuf_addstr(&sb, filename);
332 333 334
		if (!match_pathspec(ctx->args->repo->index,
				    &ctx->pathspec,
				    sb.buf, sb.len, 0, NULL, 1))
335 336 337 338
			ret = READ_TREE_RECURSIVE;
		strbuf_release(&sb);
	}
	return ret;
339 340
}

341
static int path_exists(struct archiver_args *args, const char *path)
342
{
343
	const char *paths[] = { path, NULL };
344
	struct path_exists_context ctx;
345 346
	int ret;

347 348 349
	ctx.args = args;
	parse_pathspec(&ctx.pathspec, 0, 0, "", paths);
	ctx.pathspec.recursive = 1;
350 351
	ret = read_tree_recursive(args->repo, args->tree, "",
				  0, 0, &ctx.pathspec,
352 353
				  reject_entry, &ctx);
	clear_pathspec(&ctx.pathspec);
354
	return ret != 0;
355 356
}

357 358 359
static void parse_pathspec_arg(const char **pathspec,
		struct archiver_args *ar_args)
{
360 361 362 363 364 365 366 367
	/*
	 * 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);
368
	ar_args->pathspec.recursive = 1;
369 370
	if (pathspec) {
		while (*pathspec) {
371
			if (**pathspec && !path_exists(ar_args, *pathspec))
372
				die(_("pathspec '%s' did not match any files"), *pathspec);
373 374 375
			pathspec++;
		}
	}
376 377 378
}

static void parse_treeish_arg(const char **argv,
379 380
		struct archiver_args *ar_args, const char *prefix,
		int remote)
381 382 383 384 385 386
{
	const char *name = argv[0];
	const unsigned char *commit_sha1;
	time_t archive_time;
	struct tree *tree;
	const struct commit *commit;
387
	struct object_id oid;
388

389
	/* Remotes are only allowed to fetch actual refs */
390
	if (remote && !remote_allow_unreachable) {
391
		char *ref = NULL;
392 393
		const char *colon = strchrnul(name, ':');
		int refnamelen = colon - name;
394

395
		if (!dwim_ref(name, refnamelen, &oid, &ref))
396
			die(_("no such ref: %.*s"), refnamelen, name);
397 398
		free(ref);
	}
399

400
	if (get_oid(name, &oid))
401
		die(_("not a valid object name: %s"), name);
402

403
	commit = lookup_commit_reference_gently(ar_args->repo, &oid, 1);
404
	if (commit) {
405
		commit_sha1 = commit->object.oid.hash;
406 407 408 409 410 411
		archive_time = commit->date;
	} else {
		commit_sha1 = NULL;
		archive_time = time(NULL);
	}

412
	tree = parse_tree_indirect(&oid);
413
	if (tree == NULL)
414
		die(_("not a tree object: %s"), oid_to_hex(&oid));
415 416

	if (prefix) {
417
		struct object_id tree_oid;
418 419 420
		unsigned int mode;
		int err;

421 422
		err = get_tree_entry(&tree->object.oid, prefix, &tree_oid,
				     &mode);
423
		if (err || !S_ISDIR(mode))
424
			die(_("current working directory is untracked"));
425

426
		tree = parse_tree_indirect(&tree_oid);
427 428 429 430 431 432 433
	}
	ar_args->tree = tree;
	ar_args->commit_sha1 = commit_sha1;
	ar_args->commit = commit;
	ar_args->time = archive_time;
}

434
#define OPT__COMPR(s, v, h, p) \
435
	OPT_SET_INT_F(s, NULL, v, h, p, PARSE_OPT_NONEG)
436
#define OPT__COMPR_HIDDEN(s, v, p) \
437
	OPT_SET_INT_F(s, NULL, v, "", p, PARSE_OPT_NONEG | PARSE_OPT_HIDDEN)
438

439
static int parse_archive_args(int argc, const char **argv,
440
		const struct archiver **ar, struct archiver_args *args,
441
		const char *name_hint, int is_remote)
442
{
443
	const char *format = NULL;
444 445 446
	const char *base = NULL;
	const char *remote = NULL;
	const char *exec = NULL;
447
	const char *output = NULL;
448 449 450
	int compression_level = -1;
	int verbose = 0;
	int i;
451
	int list = 0;
452
	int worktree_attributes = 0;
453 454
	struct option opts[] = {
		OPT_GROUP(""),
455 456 457 458 459
		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")),
460
		OPT_BOOL(0, "worktree-attributes", &worktree_attributes,
461 462 463 464
			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),
465 466 467 468 469 470 471
		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),
472
		OPT__COMPR('9', &compression_level, N_("compress better"), 9),
473
		OPT_GROUP(""),
474
		OPT_BOOL('l', "list", &list,
475
			N_("list supported archive formats")),
476
		OPT_GROUP(""),
477 478
		OPT_STRING(0, "remote", &remote, N_("repo"),
			N_("retrieve the archive from remote repository <repo>")),
479
		OPT_STRING(0, "exec", &exec, N_("command"),
480
			N_("path to the remote git-upload-archive command")),
481 482 483
		OPT_END()
	};

484
	argc = parse_options(argc, argv, NULL, opts, archive_usage, 0);
485 486

	if (remote)
487
		die(_("Unexpected option --remote"));
488
	if (exec)
489
		die(_("Option --exec can only be used together with --remote"));
490
	if (output)
491
		die(_("Unexpected option --output"));
492 493 494 495 496

	if (!base)
		base = "";

	if (list) {
497
		for (i = 0; i < nr_archivers; i++)
498 499
			if (!is_remote || archivers[i]->flags & ARCHIVER_REMOTE)
				printf("%s\n", archivers[i]->name);
500
		exit(0);
501 502
	}

503 504 505 506 507
	if (!format && name_hint)
		format = archive_format_from_filename(name_hint);
	if (!format)
		format = "tar";

508
	/* We need at least one parameter -- tree-ish */
509 510
	if (argc < 1)
		usage_with_options(archive_usage, opts);
511
	*ar = lookup_archiver(format);
512
	if (!*ar || (is_remote && !((*ar)->flags & ARCHIVER_REMOTE)))
513
		die(_("Unknown archive format '%s'"), format);
514 515 516

	args->compression_level = Z_DEFAULT_COMPRESSION;
	if (compression_level != -1) {
517
		if ((*ar)->flags & ARCHIVER_WANT_COMPRESSION_LEVELS)
518 519
			args->compression_level = compression_level;
		else {
520
			die(_("Argument not supported for format '%s': -%d"),
521 522 523 524 525 526
					format, compression_level);
		}
	}
	args->verbose = verbose;
	args->base = base;
	args->baselen = strlen(base);
527
	args->worktree_attributes = worktree_attributes;
528

529
	return argc;
530 531
}

532
int write_archive(int argc, const char **argv, const char *prefix,
533
		  struct repository *repo,
534
		  const char *name_hint, int remote)
535 536 537 538
{
	const struct archiver *ar = NULL;
	struct archiver_args args;

539 540 541
	git_config_get_bool("uploadarchive.allowunreachable", &remote_allow_unreachable);
	git_config(git_default_config, NULL);

542
	args.repo = repo;
543
	argc = parse_archive_args(argc, argv, &ar, &args, name_hint, remote);
544
	if (!startup_info->have_repository) {
545 546 547 548 549 550 551
		/*
		 * 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();
	}
552

553
	parse_treeish_arg(argv, &args, prefix, remote);
554 555
	parse_pathspec_arg(argv + 1, &args);

556
	return ar->write_archive(ar, &args);
557
}
558

559 560 561 562 563 564 565 566 567
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).
	 */
568
	if (prefixlen < 2 || filename[prefixlen - 1] != '.')
569 570 571 572
		return 0;
	return !strcmp(filename + prefixlen, ext);
}

573 574
const char *archive_format_from_filename(const char *filename)
{
575 576 577 578 579
	int i;

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