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 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 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 void traverse_trees(int n
, struct tree_desc
*t
, const char *base
, traverse_callback_t callback
)
83 struct name_entry
*entry
= xmalloc(n
*sizeof(*entry
));
86 struct name_entry entry
[3];
87 unsigned long mask
= 0;
91 for (i
= 0; i
< n
; i
++) {
94 entry_extract(t
+i
, entry
+i
);
96 int cmp
= entry_compare(entry
+i
, entry
+last
);
99 * Is the new name bigger than the old one?
105 * Is the new name smaller than the old one?
106 * Ignore all old ones
118 * Update the tree entries we've walked, and clear
119 * all the unused name-entries.
121 for (i
= 0; i
< n
; i
++) {
122 if (mask
& (1ul << i
)) {
123 update_tree_entry(t
+i
);
126 entry_clear(entry
+ i
);
128 callback(n
, mask
, entry
, base
);
133 static int find_tree_entry(struct tree_desc
*t
, const char *name
, unsigned char *result
, unsigned *mode
)
135 int namelen
= strlen(name
);
138 const unsigned char *sha1
;
141 sha1
= tree_entry_extract(t
, &entry
, mode
);
142 update_tree_entry(t
);
143 entrylen
= strlen(entry
);
144 if (entrylen
> namelen
)
146 cmp
= memcmp(name
, entry
, entrylen
);
151 if (entrylen
== namelen
) {
152 memcpy(result
, sha1
, 20);
155 if (name
[entrylen
] != '/')
159 if (++entrylen
== namelen
) {
160 memcpy(result
, sha1
, 20);
163 return get_tree_entry(sha1
, name
+ entrylen
, result
, mode
);
168 int get_tree_entry(const unsigned char *tree_sha1
, const char *name
, unsigned char *sha1
, unsigned *mode
)
174 tree
= read_object_with_reference(tree_sha1
, tree_type
, &t
.size
, NULL
);
178 retval
= find_tree_entry(&t
, name
, sha1
, mode
);