Skip to content

Commit 5ff247a

Browse files
rscharfegitster
authored andcommitted
archive: don't queue excluded directories
Reject directories with the attribute export-ignore already while queuing them. This prevents read_tree_recursive() from descending into them and this avoids write_archive_entry() rejecting them later on, which queue_or_write_archive_entry() is not prepared for. Borrow the existing strbuf to build the full path to avoid string copies and extra allocations; just make sure we restore the original value before moving on. Keep checking any other attributes in write_archive_entry() as before, but avoid checking them twice. Signed-off-by: Rene Scharfe <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent c6c08f7 commit 5ff247a

File tree

2 files changed

+27
-9
lines changed

2 files changed

+27
-9
lines changed

archive.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -121,17 +121,21 @@ static int check_attr_export_subst(const struct attr_check *check)
121121
return check && ATTR_TRUE(check->items[1].value);
122122
}
123123

124+
static int should_queue_directories(const struct archiver_args *args)
125+
{
126+
return args->pathspec.has_wildcard;
127+
}
128+
124129
static int write_archive_entry(const unsigned char *sha1, const char *base,
125130
int baselen, const char *filename, unsigned mode, int stage,
126131
void *context)
127132
{
128133
static struct strbuf path = STRBUF_INIT;
129-
const struct attr_check *check;
130134
struct archiver_context *c = context;
131135
struct archiver_args *args = c->args;
132136
write_archive_entry_fn_t write_entry = c->write_entry;
133-
const char *path_without_prefix;
134137
int err;
138+
const char *path_without_prefix;
135139

136140
args->convert = 0;
137141
strbuf_reset(&path);
@@ -143,10 +147,13 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
143147
strbuf_addch(&path, '/');
144148
path_without_prefix = path.buf + args->baselen;
145149

146-
check = get_archive_attrs(path_without_prefix);
147-
if (check_attr_export_ignore(check))
148-
return 0;
149-
args->convert = check_attr_export_subst(check);
150+
if (!S_ISDIR(mode) || !should_queue_directories(args)) {
151+
const struct attr_check *check;
152+
check = get_archive_attrs(path_without_prefix);
153+
if (check_attr_export_ignore(check))
154+
return 0;
155+
args->convert = check_attr_export_subst(check);
156+
}
150157

151158
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
152159
if (args->verbose)
@@ -219,6 +226,17 @@ static int queue_or_write_archive_entry(const unsigned char *sha1,
219226
}
220227

221228
if (S_ISDIR(mode)) {
229+
size_t baselen = base->len;
230+
const struct attr_check *check;
231+
232+
/* Borrow base, but restore its original value when done. */
233+
strbuf_addstr(base, filename);
234+
strbuf_addch(base, '/');
235+
check = get_archive_attrs(base->buf);
236+
strbuf_setlen(base, baselen);
237+
238+
if (check_attr_export_ignore(check))
239+
return 0;
222240
queue_directory(sha1, base, filename,
223241
mode, stage, c);
224242
return READ_TREE_RECURSIVE;
@@ -272,7 +290,7 @@ int write_archive_entries(struct archiver_args *args,
272290
}
273291

274292
err = read_tree_recursive(args->tree, "", 0, 0, &args->pathspec,
275-
args->pathspec.has_wildcard ?
293+
should_queue_directories(args) ?
276294
queue_or_write_archive_entry :
277295
write_archive_entry_buf,
278296
&context);

t/t5001-archive-attr.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ test_expect_exists archive-pathspec/ignored-by-worktree
7676
test_expect_missing archive-pathspec/excluded-by-pathspec.d failure
7777
test_expect_missing archive-pathspec/excluded-by-pathspec.d/file
7878

79-
test_expect_failure 'git archive with wildcard pathspec' '
79+
test_expect_success 'git archive with wildcard pathspec' '
8080
git archive HEAD ":!excluded-by-p*" >archive-pathspec-wildcard.tar &&
8181
extract_tar_to_dir archive-pathspec-wildcard
8282
'
@@ -85,7 +85,7 @@ test_expect_missing archive-pathspec-wildcard/ignored
8585
test_expect_missing archive-pathspec-wildcard/ignored-by-tree
8686
test_expect_missing archive-pathspec-wildcard/ignored-by-tree.d
8787
test_expect_missing archive-pathspec-wildcard/ignored-by-tree.d/file
88-
test_expect_exists archive-pathspec-wildcard/ignored-by-worktree failure
88+
test_expect_exists archive-pathspec-wildcard/ignored-by-worktree
8989
test_expect_missing archive-pathspec-wildcard/excluded-by-pathspec.d
9090
test_expect_missing archive-pathspec-wildcard/excluded-by-pathspec.d/file
9191

0 commit comments

Comments
 (0)