Skip to content

Commit ad16f74

Browse files
committed
Merge branch 'ab/read-tree'
Code simplification by removing support for a caller that is long gone. * ab/read-tree: tree.h API: simplify read_tree_recursive() signature tree.h API: expose read_tree_1() as read_tree_at() archive: stop passing "stage" through read_tree_recursive() ls-files: refactor away read_tree() ls-files: don't needlessly pass around stage variable tree.c API: move read_tree() into builtin/ls-files.c ls-files tests: add meaningful --with-tree tests show tests: add test for "git show <tree>"
2 parents aab55b1 + 4795748 commit ad16f74

File tree

11 files changed

+205
-147
lines changed

11 files changed

+205
-147
lines changed

archive.c

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ struct directory {
104104
struct object_id oid;
105105
int baselen, len;
106106
unsigned mode;
107-
int stage;
108107
char path[FLEX_ARRAY];
109108
};
110109

@@ -135,7 +134,7 @@ static int check_attr_export_subst(const struct attr_check *check)
135134
}
136135

137136
static int write_archive_entry(const struct object_id *oid, const char *base,
138-
int baselen, const char *filename, unsigned mode, int stage,
137+
int baselen, const char *filename, unsigned mode,
139138
void *context)
140139
{
141140
static struct strbuf path = STRBUF_INIT;
@@ -194,15 +193,14 @@ static int write_archive_entry(const struct object_id *oid, const char *base,
194193

195194
static void queue_directory(const unsigned char *sha1,
196195
struct strbuf *base, const char *filename,
197-
unsigned mode, int stage, struct archiver_context *c)
196+
unsigned mode, struct archiver_context *c)
198197
{
199198
struct directory *d;
200199
size_t len = st_add4(base->len, 1, strlen(filename), 1);
201200
d = xmalloc(st_add(sizeof(*d), len));
202201
d->up = c->bottom;
203202
d->baselen = base->len;
204203
d->mode = mode;
205-
d->stage = stage;
206204
c->bottom = d;
207205
d->len = xsnprintf(d->path, len, "%.*s%s/", (int)base->len, base->buf, filename);
208206
hashcpy(d->oid.hash, sha1);
@@ -221,14 +219,14 @@ static int write_directory(struct archiver_context *c)
221219
write_directory(c) ||
222220
write_archive_entry(&d->oid, d->path, d->baselen,
223221
d->path + d->baselen, d->mode,
224-
d->stage, c) != READ_TREE_RECURSIVE;
222+
c) != READ_TREE_RECURSIVE;
225223
free(d);
226224
return ret ? -1 : 0;
227225
}
228226

229227
static int queue_or_write_archive_entry(const struct object_id *oid,
230228
struct strbuf *base, const char *filename,
231-
unsigned mode, int stage, void *context)
229+
unsigned mode, void *context)
232230
{
233231
struct archiver_context *c = context;
234232

@@ -253,14 +251,14 @@ static int queue_or_write_archive_entry(const struct object_id *oid,
253251
if (check_attr_export_ignore(check))
254252
return 0;
255253
queue_directory(oid->hash, base, filename,
256-
mode, stage, c);
254+
mode, c);
257255
return READ_TREE_RECURSIVE;
258256
}
259257

260258
if (write_directory(c))
261259
return -1;
262260
return write_archive_entry(oid, base->buf, base->len, filename, mode,
263-
stage, context);
261+
context);
264262
}
265263

266264
struct extra_file_info {
@@ -313,10 +311,10 @@ int write_archive_entries(struct archiver_args *args,
313311
git_attr_set_direction(GIT_ATTR_INDEX);
314312
}
315313

316-
err = read_tree_recursive(args->repo, args->tree, "",
317-
0, 0, &args->pathspec,
318-
queue_or_write_archive_entry,
319-
&context);
314+
err = read_tree(args->repo, args->tree,
315+
&args->pathspec,
316+
queue_or_write_archive_entry,
317+
&context);
320318
if (err == READ_TREE_RECURSIVE)
321319
err = 0;
322320
while (context.bottom) {
@@ -375,7 +373,7 @@ struct path_exists_context {
375373

376374
static int reject_entry(const struct object_id *oid, struct strbuf *base,
377375
const char *filename, unsigned mode,
378-
int stage, void *context)
376+
void *context)
379377
{
380378
int ret = -1;
381379
struct path_exists_context *ctx = context;
@@ -402,9 +400,9 @@ static int path_exists(struct archiver_args *args, const char *path)
402400
ctx.args = args;
403401
parse_pathspec(&ctx.pathspec, 0, 0, "", paths);
404402
ctx.pathspec.recursive = 1;
405-
ret = read_tree_recursive(args->repo, args->tree, "",
406-
0, 0, &ctx.pathspec,
407-
reject_entry, &ctx);
403+
ret = read_tree(args->repo, args->tree,
404+
&ctx.pathspec,
405+
reject_entry, &ctx);
408406
clear_pathspec(&ctx.pathspec);
409407
return ret != 0;
410408
}

builtin/checkout.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ static int post_checkout_hook(struct commit *old_commit, struct commit *new_comm
114114
}
115115

116116
static int update_some(const struct object_id *oid, struct strbuf *base,
117-
const char *pathname, unsigned mode, int stage, void *context)
117+
const char *pathname, unsigned mode, void *context)
118118
{
119119
int len;
120120
struct cache_entry *ce;
@@ -155,8 +155,8 @@ static int update_some(const struct object_id *oid, struct strbuf *base,
155155

156156
static int read_tree_some(struct tree *tree, const struct pathspec *pathspec)
157157
{
158-
read_tree_recursive(the_repository, tree, "", 0, 0,
159-
pathspec, update_some, NULL);
158+
read_tree(the_repository, tree,
159+
pathspec, update_some, NULL);
160160

161161
/* update the index with the given tree's info
162162
* for all args, expanding wildcards, and exit
@@ -322,7 +322,7 @@ static void mark_ce_for_checkout_overlay(struct cache_entry *ce,
322322
* If it comes from the tree-ish, we already know it
323323
* matches the pathspec and could just stamp
324324
* CE_MATCHED to it from update_some(). But we still
325-
* need ps_matched and read_tree_recursive (and
325+
* need ps_matched and read_tree (and
326326
* eventually tree_entry_interesting) cannot fill
327327
* ps_matched yet. Once it can, we can avoid calling
328328
* match_pathspec() for _all_ entries when

builtin/log.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ static int show_tag_object(const struct object_id *oid, struct rev_info *rev)
599599

600600
static int show_tree_object(const struct object_id *oid,
601601
struct strbuf *base,
602-
const char *pathname, unsigned mode, int stage, void *context)
602+
const char *pathname, unsigned mode, void *context)
603603
{
604604
FILE *file = context;
605605
fprintf(file, "%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");
@@ -681,9 +681,9 @@ int cmd_show(int argc, const char **argv, const char *prefix)
681681
diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
682682
name,
683683
diff_get_color_opt(&rev.diffopt, DIFF_RESET));
684-
read_tree_recursive(the_repository, (struct tree *)o, "",
685-
0, 0, &match_all, show_tree_object,
686-
rev.diffopt.file);
684+
read_tree(the_repository, (struct tree *)o,
685+
&match_all, show_tree_object,
686+
rev.diffopt.file);
687687
rev.shown_one = 1;
688688
break;
689689
case OBJ_COMMIT:

builtin/ls-files.c

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "dir.h"
1313
#include "builtin.h"
1414
#include "tree.h"
15+
#include "cache-tree.h"
1516
#include "parse-options.h"
1617
#include "resolve-undo.h"
1718
#include "string-list.h"
@@ -420,6 +421,53 @@ static int get_common_prefix_len(const char *common_prefix)
420421
return common_prefix_len;
421422
}
422423

424+
static int read_one_entry_opt(struct index_state *istate,
425+
const struct object_id *oid,
426+
struct strbuf *base,
427+
const char *pathname,
428+
unsigned mode, int opt)
429+
{
430+
int len;
431+
struct cache_entry *ce;
432+
433+
if (S_ISDIR(mode))
434+
return READ_TREE_RECURSIVE;
435+
436+
len = strlen(pathname);
437+
ce = make_empty_cache_entry(istate, base->len + len);
438+
439+
ce->ce_mode = create_ce_mode(mode);
440+
ce->ce_flags = create_ce_flags(1);
441+
ce->ce_namelen = base->len + len;
442+
memcpy(ce->name, base->buf, base->len);
443+
memcpy(ce->name + base->len, pathname, len+1);
444+
oidcpy(&ce->oid, oid);
445+
return add_index_entry(istate, ce, opt);
446+
}
447+
448+
static int read_one_entry(const struct object_id *oid, struct strbuf *base,
449+
const char *pathname, unsigned mode,
450+
void *context)
451+
{
452+
struct index_state *istate = context;
453+
return read_one_entry_opt(istate, oid, base, pathname,
454+
mode,
455+
ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK);
456+
}
457+
458+
/*
459+
* This is used when the caller knows there is no existing entries at
460+
* the stage that will conflict with the entry being added.
461+
*/
462+
static int read_one_entry_quick(const struct object_id *oid, struct strbuf *base,
463+
const char *pathname, unsigned mode,
464+
void *context)
465+
{
466+
struct index_state *istate = context;
467+
return read_one_entry_opt(istate, oid, base, pathname,
468+
mode, ADD_CACHE_JUST_APPEND);
469+
}
470+
423471
/*
424472
* Read the tree specified with --with-tree option
425473
* (typically, HEAD) into stage #1 and then
@@ -436,6 +484,8 @@ void overlay_tree_on_index(struct index_state *istate,
436484
struct pathspec pathspec;
437485
struct cache_entry *last_stage0 = NULL;
438486
int i;
487+
read_tree_fn_t fn = NULL;
488+
int err;
439489

440490
if (get_oid(tree_name, &oid))
441491
die("tree-ish %s not found.", tree_name);
@@ -458,9 +508,32 @@ void overlay_tree_on_index(struct index_state *istate,
458508
PATHSPEC_PREFER_CWD, prefix, matchbuf);
459509
} else
460510
memset(&pathspec, 0, sizeof(pathspec));
461-
if (read_tree(the_repository, tree, 1, &pathspec, istate))
511+
512+
/*
513+
* See if we have cache entry at the stage. If so,
514+
* do it the original slow way, otherwise, append and then
515+
* sort at the end.
516+
*/
517+
for (i = 0; !fn && i < istate->cache_nr; i++) {
518+
const struct cache_entry *ce = istate->cache[i];
519+
if (ce_stage(ce) == 1)
520+
fn = read_one_entry;
521+
}
522+
523+
if (!fn)
524+
fn = read_one_entry_quick;
525+
err = read_tree(the_repository, tree, &pathspec, fn, istate);
526+
if (err)
462527
die("unable to read tree entries %s", tree_name);
463528

529+
/*
530+
* Sort the cache entry -- we need to nuke the cache tree, though.
531+
*/
532+
if (fn == read_one_entry_quick) {
533+
cache_tree_free(&istate->cache_tree);
534+
QSORT(istate->cache, istate->cache_nr, cmp_cache_name_compare);
535+
}
536+
464537
for (i = 0; i < istate->cache_nr; i++) {
465538
struct cache_entry *ce = istate->cache[i];
466539
switch (ce_stage(ce)) {

builtin/ls-tree.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ static int show_recursive(const char *base, int baselen, const char *pathname)
6262
}
6363

6464
static int show_tree(const struct object_id *oid, struct strbuf *base,
65-
const char *pathname, unsigned mode, int stage, void *context)
65+
const char *pathname, unsigned mode, void *context)
6666
{
6767
int retval = 0;
6868
int baselen;
@@ -185,6 +185,6 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
185185
tree = parse_tree_indirect(&oid);
186186
if (!tree)
187187
die("not a tree object");
188-
return !!read_tree_recursive(the_repository, tree, "", 0, 0,
189-
&pathspec, show_tree, NULL);
188+
return !!read_tree(the_repository, tree,
189+
&pathspec, show_tree, NULL);
190190
}

cache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,7 @@ static inline int index_pos_to_insert_pos(uintmax_t pos)
803803
#define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */
804804
#define ADD_CACHE_OK_TO_REPLACE 2 /* Ok to replace file/directory */
805805
#define ADD_CACHE_SKIP_DFCHECK 4 /* Ok to skip DF conflict checks */
806-
#define ADD_CACHE_JUST_APPEND 8 /* Append only; tree.c::read_tree() */
806+
#define ADD_CACHE_JUST_APPEND 8 /* Append only */
807807
#define ADD_CACHE_NEW_ONLY 16 /* Do not replace existing ones */
808808
#define ADD_CACHE_KEEP_CACHE_TREE 32 /* Do not invalidate cache-tree */
809809
#define ADD_CACHE_RENORMALIZE 64 /* Pass along HASH_RENORMALIZE */

merge-recursive.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ static void unpack_trees_finish(struct merge_options *opt)
453453

454454
static int save_files_dirs(const struct object_id *oid,
455455
struct strbuf *base, const char *path,
456-
unsigned int mode, int stage, void *context)
456+
unsigned int mode, void *context)
457457
{
458458
struct path_hashmap_entry *entry;
459459
int baselen = base->len;
@@ -473,8 +473,8 @@ static void get_files_dirs(struct merge_options *opt, struct tree *tree)
473473
{
474474
struct pathspec match_all;
475475
memset(&match_all, 0, sizeof(match_all));
476-
read_tree_recursive(opt->repo, tree, "", 0, 0,
477-
&match_all, save_files_dirs, opt);
476+
read_tree(opt->repo, tree,
477+
&match_all, save_files_dirs, opt);
478478
}
479479

480480
static int get_tree_entry_if_blob(struct repository *r,

t/t3060-ls-files-with-tree.sh

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ test_expect_success setup '
4747
git add .
4848
'
4949

50+
test_expect_success 'usage' '
51+
test_expect_code 128 git ls-files --with-tree=HEAD -u &&
52+
test_expect_code 128 git ls-files --with-tree=HEAD -s &&
53+
test_expect_code 128 git ls-files --recurse-submodules --with-tree=HEAD
54+
'
55+
5056
test_expect_success 'git ls-files --with-tree should succeed from subdir' '
5157
# We have to run from a sub-directory to trigger prune_path
5258
# Then we finally get to run our --with-tree test
@@ -60,4 +66,39 @@ test_expect_success \
6066
'git ls-files --with-tree should add entries from named tree.' \
6167
'test_cmp expected output'
6268

69+
test_expect_success 'no duplicates in --with-tree output' '
70+
git ls-files --with-tree=HEAD >actual &&
71+
sort -u actual >expected &&
72+
test_cmp expected actual
73+
'
74+
75+
test_expect_success 'setup: output in a conflict' '
76+
test_create_repo conflict &&
77+
test_commit -C conflict BASE file &&
78+
test_commit -C conflict A file foo &&
79+
git -C conflict reset --hard BASE &&
80+
test_commit -C conflict B file bar
81+
'
82+
83+
test_expect_success 'output in a conflict' '
84+
test_must_fail git -C conflict merge A B &&
85+
cat >expected <<-\EOF &&
86+
file
87+
file
88+
file
89+
file
90+
EOF
91+
git -C conflict ls-files --with-tree=HEAD >actual &&
92+
test_cmp expected actual
93+
'
94+
95+
test_expect_success 'output with removed .git/index' '
96+
cat >expected <<-\EOF &&
97+
file
98+
EOF
99+
rm conflict/.git/index &&
100+
git -C conflict ls-files --with-tree=HEAD >actual &&
101+
test_cmp expected actual
102+
'
103+
63104
test_done

0 commit comments

Comments
 (0)