]>
git.proxmox.com Git - libgit2.git/blob - src/tree-cache.c
2 * Copyright (C) 2009-2011 the libgit2 contributors
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
8 #include "tree-cache.h"
10 static git_tree_cache
*find_child(git_tree_cache
*tree
, const char *path
)
15 end
= strchr(path
, '/');
17 end
= strrchr(path
, '\0');
22 for (i
= 0; i
< tree
->children_count
; ++i
) {
23 const char *childname
= tree
->children
[i
]->name
;
25 if (strlen(childname
) == dirlen
&& !memcmp(path
, childname
, dirlen
))
26 return tree
->children
[i
];
32 void git_tree_cache_invalidate_path(git_tree_cache
*tree
, const char *path
)
34 const char *ptr
= path
, *end
;
42 end
= strchr(ptr
, '/');
44 if (end
== NULL
) /* End of path */
47 tree
= find_child(tree
, ptr
);
48 if (tree
== NULL
) /* We don't have that tree */
56 static int read_tree_internal(git_tree_cache
**out
,
57 const char **buffer_in
, const char *buffer_end
, git_tree_cache
*parent
)
59 git_tree_cache
*tree
= NULL
;
60 const char *name_start
, *buffer
;
62 int error
= GIT_SUCCESS
;
65 buffer
= name_start
= *buffer_in
;
67 if ((buffer
= memchr(buffer
, '\0', buffer_end
- buffer
)) == NULL
) {
68 error
= GIT_EOBJCORRUPTED
;
72 if (++buffer
>= buffer_end
) {
73 error
= GIT_EOBJCORRUPTED
;
77 name_len
= strlen(name_start
);
78 if ((tree
= git__malloc(sizeof(git_tree_cache
) + name_len
+ 1)) == NULL
)
81 memset(tree
, 0x0, sizeof(git_tree_cache
));
82 tree
->parent
= parent
;
84 /* NUL-terminated tree name */
85 memcpy(tree
->name
, name_start
, name_len
);
86 tree
->name
[name_len
] = '\0';
88 /* Blank-terminated ASCII decimal number of entries in this tree */
89 if (git__strtol32(&count
, buffer
, &buffer
, 10) < GIT_SUCCESS
|| count
< -1) {
90 error
= GIT_EOBJCORRUPTED
;
94 tree
->entries
= count
;
96 if (*buffer
!= ' ' || ++buffer
>= buffer_end
) {
97 error
= GIT_EOBJCORRUPTED
;
101 /* Number of children of the tree, newline-terminated */
102 if (git__strtol32(&count
, buffer
, &buffer
, 10) < GIT_SUCCESS
||
104 error
= GIT_EOBJCORRUPTED
;
108 tree
->children_count
= count
;
110 if (*buffer
!= '\n' || ++buffer
>= buffer_end
) {
111 error
= GIT_EOBJCORRUPTED
;
115 /* The SHA1 is only there if it's not invalidated */
116 if (tree
->entries
>= 0) {
117 /* 160-bit SHA-1 for this tree and it's children */
118 if (buffer
+ GIT_OID_RAWSZ
> buffer_end
) {
119 error
= GIT_EOBJCORRUPTED
;
123 git_oid_fromraw(&tree
->oid
, (const unsigned char *)buffer
);
124 buffer
+= GIT_OID_RAWSZ
;
127 /* Parse children: */
128 if (tree
->children_count
> 0) {
132 tree
->children
= git__malloc(tree
->children_count
* sizeof(git_tree_cache
*));
133 if (tree
->children
== NULL
)
136 for (i
= 0; i
< tree
->children_count
; ++i
) {
137 err
= read_tree_internal(&tree
->children
[i
], &buffer
, buffer_end
, tree
);
139 if (err
< GIT_SUCCESS
)
149 git_tree_cache_free(tree
);
153 int git_tree_cache_read(git_tree_cache
**tree
, const char *buffer
, size_t buffer_size
)
155 const char *buffer_end
= buffer
+ buffer_size
;
158 error
= read_tree_internal(tree
, &buffer
, buffer_end
, NULL
);
160 if (buffer
< buffer_end
)
161 return GIT_EOBJCORRUPTED
;
166 void git_tree_cache_free(git_tree_cache
*tree
)
173 for (i
= 0; i
< tree
->children_count
; ++i
)
174 git_tree_cache_free(tree
->children
[i
]);
176 free(tree
->children
);