5 static const char *get_mode(const char *str
, unsigned int *modep
)
13 while ((c
= *str
++) != ' ') {
14 if (c
< '0' || c
> '7')
16 mode
= (mode
<< 3) + (c
- '0');
22 static void decode_tree_entry(struct tree_desc
*desc
, const char *buf
, unsigned long size
)
25 unsigned int mode
, len
;
27 if (size
< 24 || buf
[size
- 21])
28 die("corrupt tree file");
30 path
= get_mode(buf
, &mode
);
32 die("corrupt tree file");
33 len
= strlen(path
) + 1;
35 /* Initialize the descriptor entry */
36 desc
->entry
.path
= path
;
37 desc
->entry
.mode
= mode
;
38 desc
->entry
.sha1
= (const unsigned char *)(path
+ len
);
41 void init_tree_desc(struct tree_desc
*desc
, const void *buffer
, unsigned long size
)
43 desc
->buffer
= buffer
;
46 decode_tree_entry(desc
, buffer
, size
);
49 void *fill_tree_descriptor(struct tree_desc
*desc
, const unsigned char *sha1
)
51 unsigned long size
= 0;
55 buf
= read_object_with_reference(sha1
, tree_type
, &size
, NULL
);
57 die("unable to read tree %s", sha1_to_hex(sha1
));
59 init_tree_desc(desc
, buf
, size
);
63 static int entry_compare(struct name_entry
*a
, struct name_entry
*b
)
65 return base_name_compare(
66 a
->path
, tree_entry_len(a
->path
, a
->sha1
), a
->mode
,
67 b
->path
, tree_entry_len(b
->path
, b
->sha1
), b
->mode
);
70 static void entry_clear(struct name_entry
*a
)
72 memset(a
, 0, sizeof(*a
));
75 static void entry_extract(struct tree_desc
*t
, struct name_entry
*a
)
80 void update_tree_entry(struct tree_desc
*desc
)
82 const void *buf
= desc
->buffer
;
83 const unsigned char *end
= desc
->entry
.sha1
+ 20;
84 unsigned long size
= desc
->size
;
85 unsigned long len
= end
- (const unsigned char *)buf
;
88 die("corrupt tree file");
94 decode_tree_entry(desc
, buf
, size
);
97 int tree_entry(struct tree_desc
*desc
, struct name_entry
*entry
)
102 *entry
= desc
->entry
;
103 update_tree_entry(desc
);
107 void traverse_trees(int n
, struct tree_desc
*t
, const char *base
, traverse_callback_t callback
)
109 struct name_entry
*entry
= xmalloc(n
*sizeof(*entry
));
112 unsigned long mask
= 0;
116 for (i
= 0; i
< n
; i
++) {
119 entry_extract(t
+i
, entry
+i
);
121 int cmp
= entry_compare(entry
+i
, entry
+last
);
124 * Is the new name bigger than the old one?
130 * Is the new name smaller than the old one?
131 * Ignore all old ones
143 * Update the tree entries we've walked, and clear
144 * all the unused name-entries.
146 for (i
= 0; i
< n
; i
++) {
147 if (mask
& (1ul << i
)) {
148 update_tree_entry(t
+i
);
151 entry_clear(entry
+ i
);
153 callback(n
, mask
, entry
, base
);
158 static int find_tree_entry(struct tree_desc
*t
, const char *name
, unsigned char *result
, unsigned *mode
)
160 int namelen
= strlen(name
);
163 const unsigned char *sha1
;
166 sha1
= tree_entry_extract(t
, &entry
, mode
);
167 update_tree_entry(t
);
168 entrylen
= tree_entry_len(entry
, sha1
);
169 if (entrylen
> namelen
)
171 cmp
= memcmp(name
, entry
, entrylen
);
176 if (entrylen
== namelen
) {
177 hashcpy(result
, sha1
);
180 if (name
[entrylen
] != '/')
184 if (++entrylen
== namelen
) {
185 hashcpy(result
, sha1
);
188 return get_tree_entry(sha1
, name
+ entrylen
, result
, mode
);
193 int get_tree_entry(const unsigned char *tree_sha1
, const char *name
, unsigned char *sha1
, unsigned *mode
)
199 unsigned char root
[20];
201 tree
= read_object_with_reference(tree_sha1
, tree_type
, &size
, root
);
205 if (name
[0] == '\0') {
210 init_tree_desc(&t
, tree
, size
);
211 retval
= find_tree_entry(&t
, name
, sha1
, mode
);