Skip to content

Commit ec18b10

Browse files
peffgitster
authored andcommitted
tree-walk: add a mechanism for getting non-canonicalized modes
When using init_tree_desc() and tree_entry() to iterate over a tree, we always canonicalize the modes coming out of the tree. This is a good thing to prevent bugs or oddities in normal code paths, but it's counter-productive for tools like fsck that want to see the exact contents. We can address this by adding an option to avoid the extra canonicalization. A few notes on the implementation: - I've attached the new option to the tree_desc struct itself. The actual code change is in decode_tree_entry(), which is in turn called by the public update_tree_entry(), tree_entry(), and init_tree_desc() functions, plus their "gently" counterparts. By letting it ride along in the struct, we can avoid changing the signature of those functions, which are called many times. Plus it's conceptually simpler: you really want a particular iteration of a tree to be "raw" or not, rather than individual calls. - We still have to set the new option somewhere. The struct is initialized by init_tree_desc(). I added the new flags field only to the "gently" version. That avoids disturbing the much more numerous non-gentle callers, and it makes sense that anybody being careful about looking at raw modes would also be careful about bogus trees (i.e., the caller will be something like fsck in the first place). Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent a5b4466 commit ec18b10

File tree

4 files changed

+19
-9
lines changed

4 files changed

+19
-9
lines changed

fsck.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op
308308
return -1;
309309

310310
name = fsck_get_object_name(options, &tree->object.oid);
311-
if (init_tree_desc_gently(&desc, tree->buffer, tree->size))
311+
if (init_tree_desc_gently(&desc, tree->buffer, tree->size, 0))
312312
return -1;
313313
while (tree_entry_gently(&desc, &entry)) {
314314
struct object *obj;
@@ -578,7 +578,7 @@ static int fsck_tree(const struct object_id *tree_oid,
578578
const char *o_name;
579579
struct name_stack df_dup_candidates = { NULL };
580580

581-
if (init_tree_desc_gently(&desc, buffer, size)) {
581+
if (init_tree_desc_gently(&desc, buffer, size, 0)) {
582582
retval += report(options, tree_oid, OBJ_TREE,
583583
FSCK_MSG_BAD_TREE,
584584
"cannot be parsed as a tree");

packfile.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2243,7 +2243,7 @@ static int add_promisor_object(const struct object_id *oid,
22432243
struct tree *tree = (struct tree *)obj;
22442244
struct tree_desc desc;
22452245
struct name_entry entry;
2246-
if (init_tree_desc_gently(&desc, tree->buffer, tree->size))
2246+
if (init_tree_desc_gently(&desc, tree->buffer, tree->size, 0))
22472247
/*
22482248
* Error messages are given when packs are
22492249
* verified, so do not print any here.

tree-walk.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,20 @@ static int decode_tree_entry(struct tree_desc *desc, const char *buf, unsigned l
4747

4848
/* Initialize the descriptor entry */
4949
desc->entry.path = path;
50-
desc->entry.mode = canon_mode(mode);
50+
desc->entry.mode = (desc->flags & TREE_DESC_RAW_MODES) ? mode : canon_mode(mode);
5151
desc->entry.pathlen = len - 1;
5252
oidread(&desc->entry.oid, (const unsigned char *)path + len);
5353

5454
return 0;
5555
}
5656

57-
static int init_tree_desc_internal(struct tree_desc *desc, const void *buffer, unsigned long size, struct strbuf *err)
57+
static int init_tree_desc_internal(struct tree_desc *desc, const void *buffer,
58+
unsigned long size, struct strbuf *err,
59+
enum tree_desc_flags flags)
5860
{
5961
desc->buffer = buffer;
6062
desc->size = size;
63+
desc->flags = flags;
6164
if (size)
6265
return decode_tree_entry(desc, buffer, size, err);
6366
return 0;
@@ -66,15 +69,16 @@ static int init_tree_desc_internal(struct tree_desc *desc, const void *buffer, u
6669
void init_tree_desc(struct tree_desc *desc, const void *buffer, unsigned long size)
6770
{
6871
struct strbuf err = STRBUF_INIT;
69-
if (init_tree_desc_internal(desc, buffer, size, &err))
72+
if (init_tree_desc_internal(desc, buffer, size, &err, 0))
7073
die("%s", err.buf);
7174
strbuf_release(&err);
7275
}
7376

74-
int init_tree_desc_gently(struct tree_desc *desc, const void *buffer, unsigned long size)
77+
int init_tree_desc_gently(struct tree_desc *desc, const void *buffer, unsigned long size,
78+
enum tree_desc_flags flags)
7579
{
7680
struct strbuf err = STRBUF_INIT;
77-
int result = init_tree_desc_internal(desc, buffer, size, &err);
81+
int result = init_tree_desc_internal(desc, buffer, size, &err, flags);
7882
if (result)
7983
error("%s", err.buf);
8084
strbuf_release(&err);

tree-walk.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ struct tree_desc {
3434

3535
/* counts the number of bytes left in the `buffer`. */
3636
unsigned int size;
37+
38+
/* option flags passed via init_tree_desc_gently() */
39+
enum tree_desc_flags {
40+
TREE_DESC_RAW_MODES = (1 << 0),
41+
} flags;
3742
};
3843

3944
/**
@@ -79,7 +84,8 @@ int update_tree_entry_gently(struct tree_desc *);
7984
*/
8085
void init_tree_desc(struct tree_desc *desc, const void *buf, unsigned long size);
8186

82-
int init_tree_desc_gently(struct tree_desc *desc, const void *buf, unsigned long size);
87+
int init_tree_desc_gently(struct tree_desc *desc, const void *buf, unsigned long size,
88+
enum tree_desc_flags flags);
8389

8490
/*
8591
* Visit the next entry in a tree. Returns 1 when there are more entries

0 commit comments

Comments
 (0)