Hash :
41a82592
Author :
Date :
2012-05-15T14:17:39
Ranged iterators and rewritten git_status_file The goal of this work is to rewrite git_status_file to use the same underlying code as git_status_foreach. This is done in 3 phases: 1. Extend iterators to allow ranged iteration with start and end prefixes for the range of file names to be covered. 2. Improve diff so that when there is a pathspec and there is a common non-wildcard prefix of the pathspec, it will use ranged iterators to minimize excess iteration. 3. Rewrite git_status_file to call git_status_foreach_ext with a pathspec that covers just the one file being checked. Since ranged iterators underlie the status & diff implementation, this is actually fairly efficient. The workdir iterator does end up loading the contents of all the directories down to the single file, which should ideally be avoided, but it is pretty good.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
#include "clar_libgit2.h"
#include "buffer.h"
#include "path.h"
#include "posix.h"
#include "status_helpers.h"
static git_repository *g_repo = NULL;
void test_status_submodules__initialize(void)
{
git_buf modpath = GIT_BUF_INIT;
g_repo = cl_git_sandbox_init("submodules");
cl_fixture_sandbox("testrepo.git");
cl_git_pass(git_buf_sets(&modpath, git_repository_workdir(g_repo)));
cl_assert(git_path_dirname_r(&modpath, modpath.ptr) >= 0);
cl_git_pass(git_buf_joinpath(&modpath, modpath.ptr, "testrepo.git\n"));
p_rename("submodules/gitmodules", "submodules/.gitmodules");
cl_git_append2file("submodules/.gitmodules", modpath.ptr);
git_buf_free(&modpath);
p_rename("submodules/testrepo/.gitted", "submodules/testrepo/.git");
}
void test_status_submodules__cleanup(void)
{
cl_git_sandbox_cleanup();
}
void test_status_submodules__api(void)
{
git_submodule *sm;
cl_assert(git_submodule_lookup(NULL, g_repo, "nonexistent") == GIT_ENOTFOUND);
cl_assert(git_submodule_lookup(NULL, g_repo, "modified") == GIT_ENOTFOUND);
cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo"));
cl_assert(sm != NULL);
cl_assert_equal_s("testrepo", sm->name);
cl_assert_equal_s("testrepo", sm->path);
}
void test_status_submodules__0(void)
{
int counts = 0;
cl_assert(git_path_isdir("submodules/.git"));
cl_assert(git_path_isdir("submodules/testrepo/.git"));
cl_assert(git_path_isfile("submodules/.gitmodules"));
cl_git_pass(
git_status_foreach(g_repo, cb_status__count, &counts)
);
cl_assert(counts == 6);
}
static const char *expected_files[] = {
".gitmodules",
"added",
"deleted",
"ignored",
"modified",
"untracked"
};
static unsigned int expected_status[] = {
GIT_STATUS_WT_MODIFIED,
GIT_STATUS_INDEX_NEW,
GIT_STATUS_INDEX_DELETED,
GIT_STATUS_IGNORED,
GIT_STATUS_WT_MODIFIED,
GIT_STATUS_WT_NEW
};
static int
cb_status__match(const char *p, unsigned int s, void *payload)
{
volatile int *index = (int *)payload;
cl_assert_equal_s(expected_files[*index], p);
cl_assert(expected_status[*index] == s);
(*index)++;
return 0;
}
void test_status_submodules__1(void)
{
int index = 0;
cl_assert(git_path_isdir("submodules/.git"));
cl_assert(git_path_isdir("submodules/testrepo/.git"));
cl_assert(git_path_isfile("submodules/.gitmodules"));
cl_git_pass(
git_status_foreach(g_repo, cb_status__match, &index)
);
cl_assert(index == 6);
}
void test_status_submodules__single_file(void)
{
unsigned int status;
cl_git_pass( git_status_file(&status, g_repo, "testrepo") );
cl_assert(status == 0);
}