Commit 5b229e20 by Vicent Martí

Merge pull request #1413 from arrbee/more-iterator-refactor

Further tree_iterator refactoring
parents e953c160 14bedad9
......@@ -330,6 +330,33 @@ static int get_workdir_sm_content(
return 0;
}
static int get_filtered(
git_map *map, git_file fd, git_diff_file *file, git_vector *filters)
{
int error;
git_buf raw = GIT_BUF_INIT, filtered = GIT_BUF_INIT;
if ((error = git_futils_readbuffer_fd(&raw, fd, (size_t)file->size)) < 0)
return error;
if (!filters->length)
git_buf_swap(&filtered, &raw);
else
error = git_filters_apply(&filtered, &raw, filters);
if (!error) {
map->len = git_buf_len(&filtered);
map->data = git_buf_detach(&filtered);
file->flags |= GIT_DIFF_FLAG__FREE_DATA;
}
git_buf_free(&raw);
git_buf_free(&filtered);
return error;
}
static int get_workdir_content(
diff_context *ctxt,
git_diff_delta *delta,
......@@ -381,8 +408,8 @@ static int get_workdir_content(
goto cleanup;
}
if (!file->size)
file->size = git_futils_filesize(fd);
if (!file->size && !(file->size = git_futils_filesize(fd)))
goto close_and_cleanup;
if ((error = diff_delta_is_binary_by_size(ctxt, delta, file)) < 0 ||
(delta->flags & GIT_DIFF_FLAG_BINARY) != 0)
......@@ -394,26 +421,12 @@ static int get_workdir_content(
goto close_and_cleanup;
if (error == 0) { /* note: git_filters_load returns filter count */
if (!file->size)
goto close_and_cleanup;
error = git_futils_mmap_ro(map, fd, 0, (size_t)file->size);
if (!error)
file->flags |= GIT_DIFF_FLAG__UNMAP_DATA;
} else {
git_buf raw = GIT_BUF_INIT, filtered = GIT_BUF_INIT;
if (!(error = git_futils_readbuffer_fd(&raw, fd, (size_t)file->size)) &&
!(error = git_filters_apply(&filtered, &raw, &filters)))
{
map->len = git_buf_len(&filtered);
map->data = git_buf_detach(&filtered);
file->flags |= GIT_DIFF_FLAG__FREE_DATA;
}
git_buf_free(&raw);
git_buf_free(&filtered);
}
if (error != 0)
error = get_filtered(map, fd, file, &filters);
close_and_cleanup:
git_filters_free(&filters);
......
......@@ -103,6 +103,7 @@ int giterr_set_regex(const regex_t *regex, int error_code)
void giterr_clear(void)
{
set_error(0, NULL);
GIT_GLOBAL->last_error = NULL;
errno = 0;
......
......@@ -679,37 +679,14 @@ int git_path_apply_relative(git_buf *target, const char *relpath)
int git_path_cmp(
const char *name1, size_t len1, int isdir1,
const char *name2, size_t len2, int isdir2)
const char *name2, size_t len2, int isdir2,
int (*compare)(const char *, const char *, size_t))
{
unsigned char c1, c2;
size_t len = len1 < len2 ? len1 : len2;
int cmp;
cmp = memcmp(name1, name2, len);
if (cmp)
return cmp;
c1 = name1[len];
c2 = name2[len];
if (c1 == '\0' && isdir1)
c1 = '/';
if (c2 == '\0' && isdir2)
c2 = '/';
return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0;
}
int git_path_icmp(
const char *name1, size_t len1, int isdir1,
const char *name2, size_t len2, int isdir2)
{
unsigned char c1, c2;
size_t len = len1 < len2 ? len1 : len2;
int cmp;
cmp = strncasecmp(name1, name2, len);
cmp = compare(name1, name2, len);
if (cmp)
return cmp;
......
......@@ -265,12 +265,8 @@ extern int git_path_direach(
*/
extern int git_path_cmp(
const char *name1, size_t len1, int isdir1,
const char *name2, size_t len2, int isdir2);
/** Path sort function that is case insensitive */
extern int git_path_icmp(
const char *name1, size_t len1, int isdir1,
const char *name2, size_t len2, int isdir2);
const char *name2, size_t len2, int isdir2,
int (*compare)(const char *, const char *, size_t));
/**
* Invoke callback up path directory by directory until the ceiling is
......
......@@ -10,6 +10,11 @@ struct git_pool_page {
char data[GIT_FLEX_ARRAY];
};
typedef struct git_pool_freelist_item git_pool_freelist_item;
struct git_pool_freelist_item {
git_pool_freelist_item *next;
};
#define GIT_POOL_MIN_USABLE 4
#define GIT_POOL_MIN_PAGESZ 2 * sizeof(void*)
......@@ -150,7 +155,7 @@ void *git_pool_malloc(git_pool *pool, uint32_t items)
pool->has_multi_item_alloc = 1;
else if (pool->free_list != NULL) {
ptr = pool->free_list;
pool->free_list = *((void **)pool->free_list);
pool->free_list = ((git_pool_freelist_item *)pool->free_list)->next;
return ptr;
}
......@@ -235,10 +240,31 @@ char *git_pool_strcat(git_pool *pool, const char *a, const char *b)
void git_pool_free(git_pool *pool, void *ptr)
{
assert(pool && ptr && pool->item_size >= sizeof(void*));
git_pool_freelist_item *item = ptr;
assert(pool && pool->item_size >= sizeof(void*));
if (item) {
item->next = pool->free_list;
pool->free_list = item;
}
}
void git_pool_free_array(git_pool *pool, size_t count, void **ptrs)
{
git_pool_freelist_item **items = (git_pool_freelist_item **)ptrs;
size_t i;
assert(pool && ptrs && pool->item_size >= sizeof(void*));
if (!count)
return;
for (i = count - 1; i > 0; --i)
items[i]->next = items[i - 1];
*((void **)ptr) = pool->free_list;
pool->free_list = ptr;
items[i]->next = pool->free_list;
pool->free_list = items[count - 1];
}
uint32_t git_pool__open_pages(git_pool *pool)
......
......@@ -126,6 +126,13 @@ extern char *git_pool_strcat(git_pool *pool, const char *a, const char *b);
*/
extern void git_pool_free(git_pool *pool, void *ptr);
/**
* Push an array of pool allocated blocks efficiently onto the free list.
*
* This has the same constraints as `git_pool_free()` above.
*/
extern void git_pool_free_array(git_pool *pool, size_t count, void **ptrs);
/*
* Misc utilities
*/
......
......@@ -55,23 +55,28 @@ static int valid_entry_name(const char *filename)
strcmp(filename, DOT_GIT) != 0));
}
int git_tree_entry_cmp(const git_tree_entry *e1, const git_tree_entry *e2)
static int entry_sort_cmp(const void *a, const void *b)
{
const git_tree_entry *e1 = (const git_tree_entry *)a;
const git_tree_entry *e2 = (const git_tree_entry *)b;
return git_path_cmp(
e1->filename, e1->filename_len, git_tree_entry__is_tree(e1),
e2->filename, e2->filename_len, git_tree_entry__is_tree(e2));
e2->filename, e2->filename_len, git_tree_entry__is_tree(e2),
git__strncmp);
}
int git_tree_entry_icmp(const git_tree_entry *e1, const git_tree_entry *e2)
int git_tree_entry_cmp(const git_tree_entry *e1, const git_tree_entry *e2)
{
return git_path_icmp(
e1->filename, e1->filename_len, git_tree_entry__is_tree(e1),
e2->filename, e2->filename_len, git_tree_entry__is_tree(e2));
return entry_sort_cmp(e1, e2);
}
static int entry_sort_cmp(const void *a, const void *b)
int git_tree_entry_icmp(const git_tree_entry *e1, const git_tree_entry *e2)
{
return git_tree_entry_cmp((const git_tree_entry *)a, (const git_tree_entry *)b);
return git_path_cmp(
e1->filename, e1->filename_len, git_tree_entry__is_tree(e1),
e2->filename, e2->filename_len, git_tree_entry__is_tree(e2),
git__strncasecmp);
}
static git_tree_entry *alloc_entry(const char *filename)
......
......@@ -83,3 +83,53 @@ void test_core_pool__2(void)
git_pool_clear(&p);
}
void test_core_pool__free_list(void)
{
int i;
git_pool p;
void *ptr, *ptrs[50];
cl_git_pass(git_pool_init(&p, 100, 100));
for (i = 0; i < 10; ++i) {
ptr = git_pool_malloc(&p, 1);
cl_assert(ptr != NULL);
}
cl_assert_equal_i(10, (int)p.items);
for (i = 0; i < 50; ++i) {
ptrs[i] = git_pool_malloc(&p, 1);
cl_assert(ptrs[i] != NULL);
}
cl_assert_equal_i(60, (int)p.items);
git_pool_free(&p, ptr);
cl_assert_equal_i(60, (int)p.items);
git_pool_free_array(&p, 50, ptrs);
cl_assert_equal_i(60, (int)p.items);
for (i = 0; i < 50; ++i) {
ptrs[i] = git_pool_malloc(&p, 1);
cl_assert(ptrs[i] != NULL);
}
cl_assert_equal_i(60, (int)p.items);
for (i = 0; i < 111; ++i) {
ptr = git_pool_malloc(&p, 1);
cl_assert(ptr != NULL);
}
cl_assert_equal_i(170, (int)p.items);
git_pool_free_array(&p, 50, ptrs);
cl_assert_equal_i(170, (int)p.items);
for (i = 0; i < 50; ++i) {
ptrs[i] = git_pool_malloc(&p, 1);
cl_assert(ptrs[i] != NULL);
}
cl_assert_equal_i(170, (int)p.items);
git_pool_clear(&p);
}
......@@ -337,6 +337,8 @@ void test_repo_iterator__tree_icase(void)
&i, head, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "k", "k/Z"));
expect_iterator_items(i, 1, NULL, 6, NULL);
git_iterator_free(i);
git_tree_free(head);
}
void test_repo_iterator__tree_more(void)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment