5 void *fill_tree_descriptor(struct tree_desc
*desc
, const unsigned char *sha1
)
7 unsigned long size
= 0;
11 buf
= read_object_with_reference(sha1
, tree_type
, &size
, NULL
);
13 die("unable to read tree %s", sha1_to_hex(sha1
));
20 static int entry_compare(struct name_entry
*a
, struct name_entry
*b
)
22 return base_name_compare(
23 a
->path
, tree_entry_len(a
->path
, a
->sha1
), a
->mode
,
24 b
->path
, tree_entry_len(b
->path
, b
->sha1
), b
->mode
);
27 static void entry_clear(struct name_entry
*a
)
29 memset(a
, 0, sizeof(*a
));
32 static void entry_extract(struct tree_desc
*t
, struct name_entry
*a
)
34 a
->sha1
= tree_entry_extract(t
, &a
->path
, &a
->mode
);
37 void update_tree_entry(struct tree_desc
*desc
)
39 const void *buf
= desc
->buf
;
40 unsigned long size
= desc
->size
;
41 int len
= strlen(buf
) + 1 + 20;
44 die("corrupt tree file");
45 desc
->buf
= (char *) buf
+ len
;
46 desc
->size
= size
- len
;
49 static const char *get_mode(const char *str
, unsigned int *modep
)
52 unsigned int mode
= 0;
54 while ((c
= *str
++) != ' ') {
55 if (c
< '0' || c
> '7')
57 mode
= (mode
<< 3) + (c
- '0');
63 const unsigned char *tree_entry_extract(struct tree_desc
*desc
, const char **pathp
, unsigned int *modep
)
65 const void *tree
= desc
->buf
;
66 unsigned long size
= desc
->size
;
67 int len
= strlen(tree
)+1;
68 const unsigned char *sha1
= (unsigned char *) tree
+ len
;
72 path
= get_mode(tree
, &mode
);
73 if (!path
|| size
< len
+ 20)
74 die("corrupt tree file");
76 *modep
= canon_mode(mode
);
80 int tree_entry(struct tree_desc
*desc
, struct name_entry
*entry
)
82 const void *tree
= desc
->buf
;
84 unsigned long len
, size
= desc
->size
;
89 path
= get_mode(tree
, &entry
->mode
);
91 die("corrupt tree file");
97 entry
->sha1
= (const unsigned char *) path
;
100 len
= path
- (char *) tree
;
102 die("corrupt tree file");
105 desc
->size
= size
- len
;
109 void traverse_trees(int n
, struct tree_desc
*t
, const char *base
, traverse_callback_t callback
)
111 struct name_entry
*entry
= xmalloc(n
*sizeof(*entry
));
114 unsigned long mask
= 0;
118 for (i
= 0; i
< n
; i
++) {
121 entry_extract(t
+i
, entry
+i
);
123 int cmp
= entry_compare(entry
+i
, entry
+last
);
126 * Is the new name bigger than the old one?
132 * Is the new name smaller than the old one?
133 * Ignore all old ones
145 * Update the tree entries we've walked, and clear
146 * all the unused name-entries.
148 for (i
= 0; i
< n
; i
++) {
149 if (mask
& (1ul << i
)) {
150 update_tree_entry(t
+i
);
153 entry_clear(entry
+ i
);
155 callback(n
, mask
, entry
, base
);
160 static int find_tree_entry(struct tree_desc
*t
, const char *name
, unsigned char *result
, unsigned *mode
)
162 int namelen
= strlen(name
);
165 const unsigned char *sha1
;
168 sha1
= tree_entry_extract(t
, &entry
, mode
);
169 update_tree_entry(t
);
170 entrylen
= tree_entry_len(entry
, sha1
);
171 if (entrylen
> namelen
)
173 cmp
= memcmp(name
, entry
, entrylen
);
178 if (entrylen
== namelen
) {
179 hashcpy(result
, sha1
);
182 if (name
[entrylen
] != '/')
186 if (++entrylen
== namelen
) {
187 hashcpy(result
, sha1
);
190 return get_tree_entry(sha1
, name
+ entrylen
, result
, mode
);
195 int get_tree_entry(const unsigned char *tree_sha1
, const char *name
, unsigned char *sha1
, unsigned *mode
)
200 unsigned char root
[20];
202 tree
= read_object_with_reference(tree_sha1
, tree_type
, &t
.size
, root
);
206 if (name
[0] == '\0') {
212 retval
= find_tree_entry(&t
, name
, sha1
, mode
);