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
, a
->pathlen
, a
->mode
,
24 b
->path
, b
->pathlen
, 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
);
35 a
->pathlen
= strlen(a
->path
);
38 void update_tree_entry(struct tree_desc
*desc
)
40 const void *buf
= desc
->buf
;
41 unsigned long size
= desc
->size
;
42 int len
= strlen(buf
) + 1 + 20;
45 die("corrupt tree file");
46 desc
->buf
= buf
+ len
;
47 desc
->size
= size
- len
;
50 static const char *get_mode(const char *str
, unsigned int *modep
)
53 unsigned int mode
= 0;
55 while ((c
= *str
++) != ' ') {
56 if (c
< '0' || c
> '7')
58 mode
= (mode
<< 3) + (c
- '0');
64 const unsigned char *tree_entry_extract(struct tree_desc
*desc
, const char **pathp
, unsigned int *modep
)
66 const void *tree
= desc
->buf
;
67 unsigned long size
= desc
->size
;
68 int len
= strlen(tree
)+1;
69 const unsigned char *sha1
= tree
+ len
;
73 path
= get_mode(tree
, &mode
);
74 if (!path
|| size
< len
+ 20)
75 die("corrupt tree file");
77 *modep
= canon_mode(mode
);
81 int tree_entry(struct tree_desc
*desc
, struct name_entry
*entry
)
83 const void *tree
= desc
->buf
, *path
;
84 unsigned long len
, size
= desc
->size
;
89 path
= get_mode(tree
, &entry
->mode
);
91 die("corrupt tree file");
103 die("corrupt tree file");
106 desc
->size
= size
- len
;
110 void traverse_trees(int n
, struct tree_desc
*t
, const char *base
, traverse_callback_t callback
)
112 struct name_entry
*entry
= xmalloc(n
*sizeof(*entry
));
115 struct name_entry entry
[3];
116 unsigned long mask
= 0;
120 for (i
= 0; i
< n
; i
++) {
123 entry_extract(t
+i
, entry
+i
);
125 int cmp
= entry_compare(entry
+i
, entry
+last
);
128 * Is the new name bigger than the old one?
134 * Is the new name smaller than the old one?
135 * Ignore all old ones
147 * Update the tree entries we've walked, and clear
148 * all the unused name-entries.
150 for (i
= 0; i
< n
; i
++) {
151 if (mask
& (1ul << i
)) {
152 update_tree_entry(t
+i
);
155 entry_clear(entry
+ i
);
157 callback(n
, mask
, entry
, base
);
162 static int find_tree_entry(struct tree_desc
*t
, const char *name
, unsigned char *result
, unsigned *mode
)
164 int namelen
= strlen(name
);
167 const unsigned char *sha1
;
170 sha1
= tree_entry_extract(t
, &entry
, mode
);
171 update_tree_entry(t
);
172 entrylen
= strlen(entry
);
173 if (entrylen
> namelen
)
175 cmp
= memcmp(name
, entry
, entrylen
);
180 if (entrylen
== namelen
) {
181 memcpy(result
, sha1
, 20);
184 if (name
[entrylen
] != '/')
188 if (++entrylen
== namelen
) {
189 memcpy(result
, sha1
, 20);
192 return get_tree_entry(sha1
, name
+ entrylen
, result
, mode
);
197 int get_tree_entry(const unsigned char *tree_sha1
, const char *name
, unsigned char *sha1
, unsigned *mode
)
203 tree
= read_object_with_reference(tree_sha1
, tree_type
, &t
.size
, NULL
);
207 retval
= find_tree_entry(&t
, name
, sha1
, mode
);