166
args->convert = check_attr_export_subst(check);
167
}
168
169
+ if (args->prefix) {
170
+ static struct strbuf new_path = STRBUF_INIT;
171
+ static struct strbuf buf = STRBUF_INIT;
172
+ const char *rel;
173
+
174
+ rel = relative_path(path_without_prefix, args->prefix, &buf);
175
+
176
+ /*
177
+ * We don't add an entry for the current working
178
+ * directory when we are at the root; skip it also when
179
+ * we're in a subdirectory or submodule. Skip entries
180
+ * higher up as well.
181
+ */
182
+ if (!strcmp(rel, "./") || starts_with(rel, "../"))
183
+ return S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0;
184
+
185
+ /* rel can refer to path, so don't edit it in place */
186
+ strbuf_reset(&new_path);
187
+ strbuf_add(&new_path, args->base, args->baselen);
188
+ strbuf_addstr(&new_path, rel);
189
+ strbuf_swap(&path, &new_path);
190
+ }
191
+
192
if (args->verbose)
193
fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
194
424
return ret;
425
}
426
427
+static int reject_outside(const struct object_id *oid UNUSED,
428
+ struct strbuf *base, const char *filename,
429
+ unsigned mode, void *context)
430
+{
431
+ struct archiver_args *args = context;
432
+ struct strbuf buf = STRBUF_INIT;
433
+ struct strbuf path = STRBUF_INIT;
434
+ int ret = 0;
435
+
436
+ if (S_ISDIR(mode))
437
+ return READ_TREE_RECURSIVE;
438
+
439
+ strbuf_addbuf(&path, base);
440
+ strbuf_addstr(&path, filename);
441
+ if (starts_with(relative_path(path.buf, args->prefix, &buf), "../"))
442
+ ret = -1;
443
+ strbuf_release(&buf);
444
+ strbuf_release(&path);
445
+ return ret;
446
+}
447
+
448
static int path_exists(struct archiver_args *args, const char *path)
449
{
450
const char *paths[] = { path, NULL };
452
int ret;
453
454
ctx.args = args;
411
- parse_pathspec(&ctx.pathspec, 0, 0, "", paths);
455
+ parse_pathspec(&ctx.pathspec, 0, PATHSPEC_PREFER_CWD,
456
+ args->prefix, paths);
457
ctx.pathspec.recursive = 1;
458
+ if (args->prefix && read_tree(args->repo, args->tree, &ctx.pathspec,
459
+ reject_outside, args))
460
+ die(_("pathspec '%s' matches files outside the "
461
+ "current directory"), path);
462
ret = read_tree(args->repo, args->tree,
463
&ctx.pathspec,
464
reject_entry, &ctx);
474
* Also if pathspec patterns are dependent, we're in big
475
* trouble as we test each one separately
476
*/
428
- parse_pathspec(&ar_args->pathspec, 0,
429
- PATHSPEC_PREFER_FULL,
430
- "", pathspec);
477
+ parse_pathspec(&ar_args->pathspec, 0, PATHSPEC_PREFER_CWD,
478
+ ar_args->prefix, pathspec);
479
ar_args->pathspec.recursive = 1;
480
if (pathspec) {
481
while (*pathspec) {
487
}
488
489
static void parse_treeish_arg(const char **argv,
442
- struct archiver_args *ar_args, const char *prefix,
443
- int remote)
490
+ struct archiver_args *ar_args, int remote)
491
{
492
const char *name = argv[0];
493
const struct object_id *commit_oid;
526
if (!tree)
527
die(_("not a tree object: %s"), oid_to_hex(&oid));
528
482
- if (prefix) {
483
- struct object_id tree_oid;
484
- unsigned short mode;
485
- int err;
486
-
487
- err = get_tree_entry(ar_args->repo,
488
- &tree->object.oid,
489
- prefix, &tree_oid,
490
- &mode);
491
- if (err || !S_ISDIR(mode))
492
- die(_("current working directory is untracked"));
493
-
494
- tree = parse_tree_indirect(&tree_oid);
495
- }
529
ar_args->refname = ref;
530
ar_args->tree = tree;
531
ar_args->commit_oid = commit_oid;
743
setup_git_directory();
744
}
745
713
- parse_treeish_arg(argv, &args, prefix, remote);
746
+ parse_treeish_arg(argv, &args, remote);
747
parse_pathspec_arg(argv + 1, &args);
748
749
rc = ar->write_archive(ar, &args);