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( ...@@ -330,6 +330,33 @@ static int get_workdir_sm_content(
return 0; 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( static int get_workdir_content(
diff_context *ctxt, diff_context *ctxt,
git_diff_delta *delta, git_diff_delta *delta,
...@@ -381,8 +408,8 @@ static int get_workdir_content( ...@@ -381,8 +408,8 @@ static int get_workdir_content(
goto cleanup; goto cleanup;
} }
if (!file->size) if (!file->size && !(file->size = git_futils_filesize(fd)))
file->size = git_futils_filesize(fd); goto close_and_cleanup;
if ((error = diff_delta_is_binary_by_size(ctxt, delta, file)) < 0 || if ((error = diff_delta_is_binary_by_size(ctxt, delta, file)) < 0 ||
(delta->flags & GIT_DIFF_FLAG_BINARY) != 0) (delta->flags & GIT_DIFF_FLAG_BINARY) != 0)
...@@ -394,26 +421,12 @@ static int get_workdir_content( ...@@ -394,26 +421,12 @@ static int get_workdir_content(
goto close_and_cleanup; goto close_and_cleanup;
if (error == 0) { /* note: git_filters_load returns filter count */ 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); error = git_futils_mmap_ro(map, fd, 0, (size_t)file->size);
if (!error)
file->flags |= GIT_DIFF_FLAG__UNMAP_DATA; 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: close_and_cleanup:
git_filters_free(&filters); git_filters_free(&filters);
......
...@@ -103,6 +103,7 @@ int giterr_set_regex(const regex_t *regex, int error_code) ...@@ -103,6 +103,7 @@ int giterr_set_regex(const regex_t *regex, int error_code)
void giterr_clear(void) void giterr_clear(void)
{ {
set_error(0, NULL);
GIT_GLOBAL->last_error = NULL; GIT_GLOBAL->last_error = NULL;
errno = 0; errno = 0;
......
...@@ -679,37 +679,14 @@ int git_path_apply_relative(git_buf *target, const char *relpath) ...@@ -679,37 +679,14 @@ int git_path_apply_relative(git_buf *target, const char *relpath)
int git_path_cmp( int git_path_cmp(
const char *name1, size_t len1, int isdir1, 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; unsigned char c1, c2;
size_t len = len1 < len2 ? len1 : len2; size_t len = len1 < len2 ? len1 : len2;
int cmp; int cmp;
cmp = memcmp(name1, name2, len); cmp = compare(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);
if (cmp) if (cmp)
return cmp; return cmp;
......
...@@ -265,12 +265,8 @@ extern int git_path_direach( ...@@ -265,12 +265,8 @@ extern int git_path_direach(
*/ */
extern int git_path_cmp( extern int git_path_cmp(
const char *name1, size_t len1, int isdir1, 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));
/** 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);
/** /**
* Invoke callback up path directory by directory until the ceiling is * Invoke callback up path directory by directory until the ceiling is
......
...@@ -10,6 +10,11 @@ struct git_pool_page { ...@@ -10,6 +10,11 @@ struct git_pool_page {
char data[GIT_FLEX_ARRAY]; 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_USABLE 4
#define GIT_POOL_MIN_PAGESZ 2 * sizeof(void*) #define GIT_POOL_MIN_PAGESZ 2 * sizeof(void*)
...@@ -150,7 +155,7 @@ void *git_pool_malloc(git_pool *pool, uint32_t items) ...@@ -150,7 +155,7 @@ void *git_pool_malloc(git_pool *pool, uint32_t items)
pool->has_multi_item_alloc = 1; pool->has_multi_item_alloc = 1;
else if (pool->free_list != NULL) { else if (pool->free_list != NULL) {
ptr = pool->free_list; ptr = pool->free_list;
pool->free_list = *((void **)pool->free_list); pool->free_list = ((git_pool_freelist_item *)pool->free_list)->next;
return ptr; return ptr;
} }
...@@ -235,10 +240,31 @@ char *git_pool_strcat(git_pool *pool, const char *a, const char *b) ...@@ -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) 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; items[i]->next = pool->free_list;
pool->free_list = ptr; pool->free_list = items[count - 1];
} }
uint32_t git_pool__open_pages(git_pool *pool) 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); ...@@ -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); 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 * Misc utilities
*/ */
......
...@@ -55,23 +55,28 @@ static int valid_entry_name(const char *filename) ...@@ -55,23 +55,28 @@ static int valid_entry_name(const char *filename)
strcmp(filename, DOT_GIT) != 0)); 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( return git_path_cmp(
e1->filename, e1->filename_len, git_tree_entry__is_tree(e1), 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( return entry_sort_cmp(e1, e2);
e1->filename, e1->filename_len, git_tree_entry__is_tree(e1),
e2->filename, e2->filename_len, git_tree_entry__is_tree(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) static git_tree_entry *alloc_entry(const char *filename)
......
...@@ -83,3 +83,53 @@ void test_core_pool__2(void) ...@@ -83,3 +83,53 @@ void test_core_pool__2(void)
git_pool_clear(&p); 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) ...@@ -337,6 +337,8 @@ void test_repo_iterator__tree_icase(void)
&i, head, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "k", "k/Z")); &i, head, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "k", "k/Z"));
expect_iterator_items(i, 1, NULL, 6, NULL); expect_iterator_items(i, 1, NULL, 6, NULL);
git_iterator_free(i); git_iterator_free(i);
git_tree_free(head);
} }
void test_repo_iterator__tree_more(void) 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