]>
git.proxmox.com Git - libgit2.git/blob - src/tree.c
2 * This file is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2,
4 * as published by the Free Software Foundation.
6 * In addition to the permissions in the GNU General Public License,
7 * the authors give you unlimited permission to link the compiled
8 * version of this file into combinations with other programs,
9 * and to distribute those combinations without any restriction
10 * coming from the use of this file. (The General Public License
11 * restrictions do apply in other respects; for example, they cover
12 * modification of the file, and distribution when not linked into
13 * a combined executable.)
15 * This file is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; see the file COPYING. If not, write to
22 * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
30 #include "git/repository.h"
31 #include "git/object.h"
33 int entry_search_cmp(const void *key
, const void *array_member
)
35 const char *filename
= (const char *)key
;
36 const git_tree_entry
*entry
= *(const git_tree_entry
**)(array_member
);
38 return strcmp(filename
, entry
->filename
);
41 int entry_sort_cmp(const void *a
, const void *b
)
43 const git_tree_entry
*entry_a
= *(const git_tree_entry
**)(a
);
44 const git_tree_entry
*entry_b
= *(const git_tree_entry
**)(b
);
46 return strcmp(entry_a
->filename
, entry_b
->filename
);
49 static void free_tree_entries(git_tree
*tree
)
56 for (i
= 0; i
< tree
->entries
.length
; ++i
) {
58 e
= git_vector_get(&tree
->entries
, i
);
64 git_vector_free(&tree
->entries
);
69 void git_tree__free(git_tree
*tree
)
71 free_tree_entries(tree
);
75 const git_oid
*git_tree_id(git_tree
*c
)
77 return git_object_id((git_object
*)c
);
80 void git_tree_entry_set_attributes(git_tree_entry
*entry
, int attr
)
82 assert(entry
&& entry
->owner
);
85 entry
->owner
->object
.modified
= 1;
88 void git_tree_entry_set_name(git_tree_entry
*entry
, const char *name
)
90 assert(entry
&& entry
->owner
);
92 free(entry
->filename
);
93 entry
->filename
= git__strdup(name
);
94 git_vector_sort(&entry
->owner
->entries
);
95 entry
->owner
->object
.modified
= 1;
98 void git_tree_entry_set_id(git_tree_entry
*entry
, const git_oid
*oid
)
100 assert(entry
&& entry
->owner
);
102 git_oid_cpy(&entry
->oid
, oid
);
103 entry
->owner
->object
.modified
= 1;
106 unsigned int git_tree_entry_attributes(git_tree_entry
*entry
)
111 const char *git_tree_entry_name(git_tree_entry
*entry
)
114 return entry
->filename
;
117 const git_oid
*git_tree_entry_id(git_tree_entry
*entry
)
123 int git_tree_entry_2object(git_object
**object_out
, git_tree_entry
*entry
)
125 assert(entry
&& object_out
);
126 return git_repository_lookup(object_out
, entry
->owner
->object
.repo
, &entry
->oid
, GIT_OBJ_ANY
);
129 git_tree_entry
*git_tree_entry_byname(git_tree
*tree
, const char *filename
)
133 assert(tree
&& filename
);
135 idx
= git_vector_search(&tree
->entries
, filename
);
136 if (idx
== GIT_ENOTFOUND
)
139 return git_vector_get(&tree
->entries
, idx
);
142 git_tree_entry
*git_tree_entry_byindex(git_tree
*tree
, int idx
)
145 return git_vector_get(&tree
->entries
, (unsigned int)idx
);
148 size_t git_tree_entrycount(git_tree
*tree
)
151 return tree
->entries
.length
;
154 int git_tree_add_entry(git_tree
*tree
, const git_oid
*id
, const char *filename
, int attributes
)
156 git_tree_entry
*entry
;
158 assert(tree
&& id
&& filename
);
160 if ((entry
= git__malloc(sizeof(git_tree_entry
))) == NULL
)
163 memset(entry
, 0x0, sizeof(git_tree_entry
));
165 entry
->filename
= git__strdup(filename
);
166 git_oid_cpy(&entry
->oid
, id
);
167 entry
->attr
= attributes
;
170 if (git_vector_insert(&tree
->entries
, entry
) < 0)
173 git_vector_sort(&tree
->entries
);
175 tree
->object
.modified
= 1;
179 int git_tree_remove_entry_byindex(git_tree
*tree
, int idx
)
181 git_tree_entry
*remove_ptr
;
185 remove_ptr
= git_vector_get(&tree
->entries
, (unsigned int)idx
);
186 if (remove_ptr
== NULL
)
187 return GIT_ENOTFOUND
;
189 free(remove_ptr
->filename
);
192 tree
->object
.modified
= 1;
194 return git_vector_remove(&tree
->entries
, (unsigned int)idx
);
197 int git_tree_remove_entry_byname(git_tree
*tree
, const char *filename
)
201 assert(tree
&& filename
);
203 idx
= git_vector_search(&tree
->entries
, filename
);
204 if (idx
== GIT_ENOTFOUND
)
205 return GIT_ENOTFOUND
;
207 return git_tree_remove_entry_byindex(tree
, idx
);
210 int git_tree__writeback(git_tree
*tree
, git_odb_source
*src
)
217 if (tree
->entries
.length
== 0)
218 return GIT_EMISSINGOBJDATA
;
220 git_vector_sort(&tree
->entries
);
222 for (i
= 0; i
< tree
->entries
.length
; ++i
) {
223 git_tree_entry
*entry
;
225 entry
= git_vector_get(&tree
->entries
, i
);
227 sprintf(filemode
, "%06o ", entry
->attr
);
229 git__source_write(src
, filemode
, strlen(filemode
));
230 git__source_write(src
, entry
->filename
, strlen(entry
->filename
) + 1);
231 git__source_write(src
, entry
->oid
.id
, GIT_OID_RAWSZ
);
238 static int tree_parse_buffer(git_tree
*tree
, char *buffer
, char *buffer_end
)
240 static const size_t avg_entry_size
= 40;
241 unsigned int expected_size
;
242 int error
= GIT_SUCCESS
;
244 expected_size
= (tree
->object
.source
.raw
.len
/ avg_entry_size
) + 1;
246 free_tree_entries(tree
);
247 if (git_vector_init(&tree
->entries
, expected_size
, entry_sort_cmp
, entry_search_cmp
) < GIT_SUCCESS
)
250 while (buffer
< buffer_end
) {
251 git_tree_entry
*entry
;
253 entry
= git__malloc(sizeof(git_tree_entry
));
259 if (git_vector_insert(&tree
->entries
, entry
) < GIT_SUCCESS
)
263 entry
->attr
= strtol(buffer
, &buffer
, 8);
265 if (*buffer
++ != ' ') {
266 error
= GIT_EOBJCORRUPTED
;
270 if (memchr(buffer
, 0, buffer_end
- buffer
) == NULL
) {
271 error
= GIT_EOBJCORRUPTED
;
275 entry
->filename
= git__strdup(buffer
);
277 while (buffer
< buffer_end
&& *buffer
!= 0)
282 git_oid_mkraw(&entry
->oid
, (const unsigned char *)buffer
);
283 buffer
+= GIT_OID_RAWSZ
;
289 int git_tree__parse(git_tree
*tree
)
291 char *buffer
, *buffer_end
;
293 assert(tree
&& tree
->object
.source
.open
);
294 assert(!tree
->object
.in_memory
);
296 buffer
= tree
->object
.source
.raw
.data
;
297 buffer_end
= buffer
+ tree
->object
.source
.raw
.len
;
299 return tree_parse_buffer(tree
, buffer
, buffer_end
);