1 #define USE_THE_REPOSITORY_VARIABLE
3 #include "git-compat-util.h"
6 #include "object-name.h"
7 #include "object-store-ll.h"
10 #include "tree-walk.h"
11 #include "repository.h"
12 #include "environment.h"
14 const char *tree_type
= "tree";
16 int read_tree_at(struct repository
*r
,
17 struct tree
*tree
, struct strbuf
*base
,
19 const struct pathspec
*pathspec
,
20 read_tree_fn_t fn
, void *context
)
22 struct tree_desc desc
;
23 struct name_entry entry
;
25 int len
, oldlen
= base
->len
;
26 enum interesting retval
= entry_not_interesting
;
28 if (depth
> max_allowed_tree_depth
)
29 return error("exceeded maximum allowed tree depth");
34 init_tree_desc(&desc
, &tree
->object
.oid
, tree
->buffer
, tree
->size
);
36 while (tree_entry(&desc
, &entry
)) {
37 if (retval
!= all_entries_interesting
) {
38 retval
= tree_entry_interesting(r
->index
, &entry
,
40 if (retval
== all_entries_not_interesting
)
42 if (retval
== entry_not_interesting
)
46 switch (fn(&entry
.oid
, base
,
47 entry
.path
, entry
.mode
, context
)) {
50 case READ_TREE_RECURSIVE
:
56 if (S_ISDIR(entry
.mode
))
57 oidcpy(&oid
, &entry
.oid
);
58 else if (S_ISGITLINK(entry
.mode
)) {
59 struct commit
*commit
;
61 commit
= lookup_commit(r
, &entry
.oid
);
63 die("Commit %s in submodule path %s%s not found",
64 oid_to_hex(&entry
.oid
),
65 base
->buf
, entry
.path
);
67 if (repo_parse_commit(r
, commit
))
68 die("Invalid commit %s in submodule path %s%s",
69 oid_to_hex(&entry
.oid
),
70 base
->buf
, entry
.path
);
72 oidcpy(&oid
, get_commit_tree_oid(commit
));
77 len
= tree_entry_len(&entry
);
78 strbuf_add(base
, entry
.path
, len
);
79 strbuf_addch(base
, '/');
80 retval
= read_tree_at(r
, lookup_tree(r
, &oid
),
81 base
, depth
+ 1, pathspec
,
83 strbuf_setlen(base
, oldlen
);
90 int read_tree(struct repository
*r
,
92 const struct pathspec
*pathspec
,
93 read_tree_fn_t fn
, void *context
)
95 struct strbuf sb
= STRBUF_INIT
;
96 int ret
= read_tree_at(r
, tree
, &sb
, 0, pathspec
, fn
, context
);
101 int base_name_compare(const char *name1
, size_t len1
, int mode1
,
102 const char *name2
, size_t len2
, int mode2
)
104 unsigned char c1
, c2
;
105 size_t len
= len1
< len2
? len1
: len2
;
108 cmp
= memcmp(name1
, name2
, len
);
113 if (!c1
&& S_ISDIR(mode1
))
115 if (!c2
&& S_ISDIR(mode2
))
117 return (c1
< c2
) ? -1 : (c1
> c2
) ? 1 : 0;
121 * df_name_compare() is identical to base_name_compare(), except it
122 * compares conflicting directory/file entries as equal. Note that
123 * while a directory name compares as equal to a regular file, they
124 * then individually compare _differently_ to a filename that has
125 * a dot after the basename (because '\0' < '.' < '/').
127 * This is used by routines that want to traverse the git namespace
128 * but then handle conflicting entries together when possible.
130 int df_name_compare(const char *name1
, size_t len1
, int mode1
,
131 const char *name2
, size_t len2
, int mode2
)
133 unsigned char c1
, c2
;
134 size_t len
= len1
< len2
? len1
: len2
;
137 cmp
= memcmp(name1
, name2
, len
);
140 /* Directories and files compare equal (same length, same name) */
144 if (!c1
&& S_ISDIR(mode1
))
147 if (!c2
&& S_ISDIR(mode2
))
149 if (c1
== '/' && !c2
)
151 if (c2
== '/' && !c1
)
156 int name_compare(const char *name1
, size_t len1
, const char *name2
, size_t len2
)
158 size_t min_len
= (len1
< len2
) ? len1
: len2
;
159 int cmp
= memcmp(name1
, name2
, min_len
);
169 struct tree
*lookup_tree(struct repository
*r
, const struct object_id
*oid
)
171 struct object
*obj
= lookup_object(r
, oid
);
173 return create_object(r
, oid
, alloc_tree_node(r
));
174 return object_as_type(obj
, OBJ_TREE
, 0);
177 int parse_tree_buffer(struct tree
*item
, void *buffer
, unsigned long size
)
179 if (item
->object
.parsed
)
181 item
->object
.parsed
= 1;
182 item
->buffer
= buffer
;
188 int parse_tree_gently(struct tree
*item
, int quiet_on_missing
)
190 enum object_type type
;
194 if (item
->object
.parsed
)
196 buffer
= repo_read_object_file(the_repository
, &item
->object
.oid
,
199 return quiet_on_missing
? -1 :
200 error("Could not read %s",
201 oid_to_hex(&item
->object
.oid
));
202 if (type
!= OBJ_TREE
) {
204 return error("Object %s not a tree",
205 oid_to_hex(&item
->object
.oid
));
207 return parse_tree_buffer(item
, buffer
, size
);
210 void free_tree_buffer(struct tree
*tree
)
212 FREE_AND_NULL(tree
->buffer
);
214 tree
->object
.parsed
= 0;
217 struct tree
*parse_tree_indirect(const struct object_id
*oid
)
219 struct repository
*r
= the_repository
;
220 struct object
*obj
= parse_object(r
, oid
);
221 return (struct tree
*)repo_peel_to_type(r
, NULL
, 0, obj
, OBJ_TREE
);