]>
git.proxmox.com Git - libgit2.git/blob - src/tree-cache.c
2 * Copyright (C) the libgit2 contributors. All rights reserved.
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(
11 const git_tree_cache
*tree
, const char *path
, const char *end
)
13 size_t i
, dirlen
= end
? (size_t)(end
- path
) : strlen(path
);
15 for (i
= 0; i
< tree
->children_count
; ++i
) {
16 git_tree_cache
*child
= tree
->children
[i
];
18 if (child
->namelen
== dirlen
&& !memcmp(path
, child
->name
, dirlen
))
25 void git_tree_cache_invalidate_path(git_tree_cache
*tree
, const char *path
)
27 const char *ptr
= path
, *end
;
35 end
= strchr(ptr
, '/');
37 if (end
== NULL
) /* End of path */
40 tree
= find_child(tree
, ptr
, end
);
41 if (tree
== NULL
) /* We don't have that tree */
49 const git_tree_cache
*git_tree_cache_get(const git_tree_cache
*tree
, const char *path
)
51 const char *ptr
= path
, *end
;
58 end
= strchr(ptr
, '/');
60 tree
= find_child(tree
, ptr
, end
);
61 if (tree
== NULL
) /* Can't find it */
64 if (end
== NULL
|| *end
+ 1 == '\0')
71 static int read_tree_internal(git_tree_cache
**out
,
72 const char **buffer_in
, const char *buffer_end
, git_tree_cache
*parent
)
74 git_tree_cache
*tree
= NULL
;
75 const char *name_start
, *buffer
;
78 buffer
= name_start
= *buffer_in
;
80 if ((buffer
= memchr(buffer
, '\0', buffer_end
- buffer
)) == NULL
)
83 if (++buffer
>= buffer_end
)
86 if (git_tree_cache_new(&tree
, name_start
, parent
) < 0)
89 /* Blank-terminated ASCII decimal number of entries in this tree */
90 if (git__strtol32(&count
, buffer
, &buffer
, 10) < 0)
93 tree
->entries
= count
;
95 if (*buffer
!= ' ' || ++buffer
>= buffer_end
)
98 /* Number of children of the tree, newline-terminated */
99 if (git__strtol32(&count
, buffer
, &buffer
, 10) < 0 || count
< 0)
102 tree
->children_count
= count
;
104 if (*buffer
!= '\n' || ++buffer
> buffer_end
)
107 /* The SHA1 is only there if it's not invalidated */
108 if (tree
->entries
>= 0) {
109 /* 160-bit SHA-1 for this tree and it's children */
110 if (buffer
+ GIT_OID_RAWSZ
> buffer_end
)
113 git_oid_fromraw(&tree
->oid
, (const unsigned char *)buffer
);
114 buffer
+= GIT_OID_RAWSZ
;
117 /* Parse children: */
118 if (tree
->children_count
> 0) {
121 tree
->children
= git__malloc(tree
->children_count
* sizeof(git_tree_cache
*));
122 GITERR_CHECK_ALLOC(tree
->children
);
124 memset(tree
->children
, 0x0, tree
->children_count
* sizeof(git_tree_cache
*));
126 for (i
= 0; i
< tree
->children_count
; ++i
) {
127 if (read_tree_internal(&tree
->children
[i
], &buffer
, buffer_end
, tree
) < 0)
137 git_tree_cache_free(tree
);
138 giterr_set(GITERR_INDEX
, "Corrupted TREE extension in index");
142 int git_tree_cache_read(git_tree_cache
**tree
, const char *buffer
, size_t buffer_size
)
144 const char *buffer_end
= buffer
+ buffer_size
;
146 if (read_tree_internal(tree
, &buffer
, buffer_end
, NULL
) < 0)
149 if (buffer
< buffer_end
) {
150 giterr_set(GITERR_INDEX
, "Corrupted TREE extension in index (unexpected trailing data)");
157 int git_tree_cache_new(git_tree_cache
**out
, const char *name
, git_tree_cache
*parent
)
160 git_tree_cache
*tree
;
162 name_len
= strlen(name
);
163 tree
= git__malloc(sizeof(git_tree_cache
) + name_len
+ 1);
164 GITERR_CHECK_ALLOC(tree
);
166 memset(tree
, 0x0, sizeof(git_tree_cache
));
167 tree
->parent
= parent
;
168 /* NUL-terminated tree name */
169 tree
->namelen
= name_len
;
170 memcpy(tree
->name
, name
, name_len
);
171 tree
->name
[name_len
] = '\0';
177 void git_tree_cache_free(git_tree_cache
*tree
)
184 if (tree
->children
!= NULL
) {
185 for (i
= 0; i
< tree
->children_count
; ++i
)
186 git_tree_cache_free(tree
->children
[i
]);
188 git__free(tree
->children
);