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 setup_traverse_info(struct traverse_info
*info
, const char *base
)
109 int pathlen
= strlen(base
);
111 memset(info
, 0, sizeof(*info
));
112 if (pathlen
&& base
[pathlen
-1] == '/')
114 info
->pathlen
= pathlen
? pathlen
+ 1 : 0;
115 info
->name
.path
= base
;
116 info
->name
.sha1
= (void *)(base
+ pathlen
+ 1);
119 char *make_traverse_path(char *path
, const struct traverse_info
*info
, const struct name_entry
*n
)
121 int len
= tree_entry_len(n
->path
, n
->sha1
);
122 int pathlen
= info
->pathlen
;
124 path
[pathlen
+ len
] = 0;
126 memcpy(path
+ pathlen
, n
->path
, len
);
129 path
[--pathlen
] = '/';
131 len
= tree_entry_len(n
->path
, n
->sha1
);
138 int traverse_trees(int n
, struct tree_desc
*t
, struct traverse_info
*info
)
141 struct name_entry
*entry
= xmalloc(n
*sizeof(*entry
));
144 unsigned long mask
= 0;
148 for (i
= 0; i
< n
; i
++) {
151 entry_extract(t
+i
, entry
+i
);
153 int cmp
= entry_compare(entry
+i
, entry
+last
);
156 * Is the new name bigger than the old one?
162 * Is the new name smaller than the old one?
163 * Ignore all old ones
175 * Clear all the unused name-entries.
177 for (i
= 0; i
< n
; i
++) {
178 if (mask
& (1ul << i
))
180 entry_clear(entry
+ i
);
182 ret
= info
->fn(n
, mask
, entry
, info
);
188 for (i
= 0; i
< n
; i
++) {
189 if (mask
& (1ul << i
))
190 update_tree_entry(t
+ i
);
197 static int find_tree_entry(struct tree_desc
*t
, const char *name
, unsigned char *result
, unsigned *mode
)
199 int namelen
= strlen(name
);
202 const unsigned char *sha1
;
205 sha1
= tree_entry_extract(t
, &entry
, mode
);
206 update_tree_entry(t
);
207 entrylen
= tree_entry_len(entry
, sha1
);
208 if (entrylen
> namelen
)
210 cmp
= memcmp(name
, entry
, entrylen
);
215 if (entrylen
== namelen
) {
216 hashcpy(result
, sha1
);
219 if (name
[entrylen
] != '/')
223 if (++entrylen
== namelen
) {
224 hashcpy(result
, sha1
);
227 return get_tree_entry(sha1
, name
+ entrylen
, result
, mode
);
232 int get_tree_entry(const unsigned char *tree_sha1
, const char *name
, unsigned char *sha1
, unsigned *mode
)
238 unsigned char root
[20];
240 tree
= read_object_with_reference(tree_sha1
, tree_type
, &size
, root
);
244 if (name
[0] == '\0') {
249 init_tree_desc(&t
, tree
, size
);
250 retval
= find_tree_entry(&t
, name
, sha1
, mode
);