]>
git.proxmox.com Git - libgit2.git/blob - src/tree-cache.c
2 * Copyright (C) 2009-2012 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(const 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 const git_tree_cache
*git_tree_cache_get(const git_tree_cache
*tree
, const char *path
)
58 const char *ptr
= path
, *end
;
65 end
= strchr(ptr
, '/');
67 tree
= find_child(tree
, ptr
);
68 if (tree
== NULL
) { /* Can't find it */
72 if (end
== NULL
|| *end
+ 1 == '\0')
79 static int read_tree_internal(git_tree_cache
**out
,
80 const char **buffer_in
, const char *buffer_end
, git_tree_cache
*parent
)
82 git_tree_cache
*tree
= NULL
;
83 const char *name_start
, *buffer
;
87 buffer
= name_start
= *buffer_in
;
89 if ((buffer
= memchr(buffer
, '\0', buffer_end
- buffer
)) == NULL
)
92 if (++buffer
>= buffer_end
)
95 name_len
= strlen(name_start
);
96 tree
= git__malloc(sizeof(git_tree_cache
) + name_len
+ 1);
97 GITERR_CHECK_ALLOC(tree
);
99 memset(tree
, 0x0, sizeof(git_tree_cache
));
100 tree
->parent
= parent
;
102 /* NUL-terminated tree name */
103 memcpy(tree
->name
, name_start
, name_len
);
104 tree
->name
[name_len
] = '\0';
106 /* Blank-terminated ASCII decimal number of entries in this tree */
107 if (git__strtol32(&count
, buffer
, &buffer
, 10) < 0)
110 tree
->entries
= count
;
112 if (*buffer
!= ' ' || ++buffer
>= buffer_end
)
115 /* Number of children of the tree, newline-terminated */
116 if (git__strtol32(&count
, buffer
, &buffer
, 10) < 0 || count
< 0)
119 tree
->children_count
= count
;
121 if (*buffer
!= '\n' || ++buffer
> buffer_end
)
124 /* The SHA1 is only there if it's not invalidated */
125 if (tree
->entries
>= 0) {
126 /* 160-bit SHA-1 for this tree and it's children */
127 if (buffer
+ GIT_OID_RAWSZ
> buffer_end
)
130 git_oid_fromraw(&tree
->oid
, (const unsigned char *)buffer
);
131 buffer
+= GIT_OID_RAWSZ
;
134 /* Parse children: */
135 if (tree
->children_count
> 0) {
138 tree
->children
= git__malloc(tree
->children_count
* sizeof(git_tree_cache
*));
139 GITERR_CHECK_ALLOC(tree
->children
);
141 for (i
= 0; i
< tree
->children_count
; ++i
) {
142 if (read_tree_internal(&tree
->children
[i
], &buffer
, buffer_end
, tree
) < 0)
152 git_tree_cache_free(tree
);
153 giterr_set(GITERR_INDEX
, "Corruped TREE extension in index");
157 int git_tree_cache_read(git_tree_cache
**tree
, const char *buffer
, size_t buffer_size
)
159 const char *buffer_end
= buffer
+ buffer_size
;
161 if (read_tree_internal(tree
, &buffer
, buffer_end
, NULL
) < 0)
164 if (buffer
< buffer_end
) {
165 giterr_set(GITERR_INDEX
, "Corruped TREE extension in index (unexpected trailing data)");
172 void git_tree_cache_free(git_tree_cache
*tree
)
179 for (i
= 0; i
< tree
->children_count
; ++i
)
180 git_tree_cache_free(tree
->children
[i
]);
182 git__free(tree
->children
);