Commit 5f4a61ae by Russell Belfer

Working implementation of git_submodule_status

This is a big redesign of the git_submodule_status API and the
implementation of the redesigned API.  It also fixes a number of
bugs that I found in other parts of the submodule API while
writing the tests for the status part.

This also fixes a couple of bugs in the iterators that had not
been noticed before - one with iterating when there is a gitlink
(i.e. separate-work-dir) and one where I was treating anything
even vaguely submodule-like as a submodule, more aggressively
than core git does.
parent 0c8858de
...@@ -391,6 +391,21 @@ GIT_EXTERN(int) git_diff_print_patch( ...@@ -391,6 +391,21 @@ GIT_EXTERN(int) git_diff_print_patch(
void *cb_data, void *cb_data,
git_diff_data_fn print_cb); git_diff_data_fn print_cb);
/**
* Query how many diff records are there in a diff list.
*
* You can optionally pass in a `git_delta_t` value if you want a count
* of just entries that match that delta type, or pass -1 for all delta
* records.
*
* @param diff A git_diff_list generated by one of the above functions
* @param delta_t A git_delta_t value to filter the count, or -1 for all records
* @return Count of number of deltas matching delta_t type
*/
GIT_EXTERN(int) git_diff_entrycount(
git_diff_list *diff,
int delta_t);
/**@}*/ /**@}*/
......
...@@ -185,6 +185,8 @@ GIT_EXTERN(int) git_oid_streq(const git_oid *a, const char *str); ...@@ -185,6 +185,8 @@ GIT_EXTERN(int) git_oid_streq(const git_oid *a, const char *str);
/** /**
* Check is an oid is all zeros. * Check is an oid is all zeros.
*
* @return 1 if all zeros, 0 otherwise.
*/ */
GIT_EXTERN(int) git_oid_iszero(const git_oid *a); GIT_EXTERN(int) git_oid_iszero(const git_oid *a);
......
...@@ -718,6 +718,25 @@ int git_diff_print_patch( ...@@ -718,6 +718,25 @@ int git_diff_print_patch(
return error; return error;
} }
int git_diff_entrycount(git_diff_list *diff, int delta_t)
{
int count = 0;
unsigned int i;
git_diff_delta *delta;
assert(diff);
if (delta_t < 0)
return diff->deltas.length;
git_vector_foreach(&diff->deltas, i, delta) {
if (delta->status == (git_delta_t)delta_t)
count++;
}
return count;
}
int git_diff_blobs( int git_diff_blobs(
git_blob *old_blob, git_blob *old_blob,
git_blob *new_blob, git_blob *new_blob,
......
...@@ -525,7 +525,9 @@ static int workdir_iterator__advance( ...@@ -525,7 +525,9 @@ static int workdir_iterator__advance(
while ((wf = wi->stack) != NULL) { while ((wf = wi->stack) != NULL) {
next = git_vector_get(&wf->entries, ++wf->index); next = git_vector_get(&wf->entries, ++wf->index);
if (next != NULL) { if (next != NULL) {
if (strcmp(next->path, DOT_GIT "/") == 0) /* match git's behavior of ignoring anything named ".git" */
if (strcmp(next->path, DOT_GIT "/") == 0 ||
strcmp(next->path, DOT_GIT) == 0)
continue; continue;
/* else found a good entry */ /* else found a good entry */
break; break;
...@@ -607,8 +609,8 @@ static int workdir_iterator__update_entry(workdir_iterator *wi) ...@@ -607,8 +609,8 @@ static int workdir_iterator__update_entry(workdir_iterator *wi)
wi->entry.path = ps->path; wi->entry.path = ps->path;
/* skip over .git directory */ /* skip over .git entry */
if (strcmp(ps->path, DOT_GIT "/") == 0) if (strcmp(ps->path, DOT_GIT "/") == 0 || strcmp(ps->path, DOT_GIT) == 0)
return workdir_iterator__advance((git_iterator *)wi, NULL); return workdir_iterator__advance((git_iterator *)wi, NULL);
/* if there is an error processing the entry, treat as ignored */ /* if there is an error processing the entry, treat as ignored */
...@@ -629,15 +631,10 @@ static int workdir_iterator__update_entry(workdir_iterator *wi) ...@@ -629,15 +631,10 @@ static int workdir_iterator__update_entry(workdir_iterator *wi)
/* detect submodules */ /* detect submodules */
if (S_ISDIR(wi->entry.mode)) { if (S_ISDIR(wi->entry.mode)) {
bool is_submodule = git_path_contains(&wi->path, DOT_GIT); int res = git_submodule_lookup(NULL, wi->repo, wi->entry.path);
bool is_submodule = (res == 0);
/* if there is no .git, still check submodules data */ if (res == GIT_ENOTFOUND)
if (!is_submodule) { giterr_clear();
int res = git_submodule_lookup(NULL, wi->repo, wi->entry.path);
is_submodule = (res == 0);
if (res == GIT_ENOTFOUND)
giterr_clear();
}
/* if submodule, mark as GITLINK and remove trailing slash */ /* if submodule, mark as GITLINK and remove trailing slash */
if (is_submodule) { if (is_submodule) {
......
...@@ -146,8 +146,13 @@ static int load_workdir(git_repository *repo, git_buf *parent_path) ...@@ -146,8 +146,13 @@ static int load_workdir(git_repository *repo, git_buf *parent_path)
return -1; return -1;
error = git_config_get_string(&worktree, config, "core.worktree"); error = git_config_get_string(&worktree, config, "core.worktree");
if (!error && worktree != NULL) if (!error && worktree != NULL) {
repo->workdir = git__strdup(worktree); error = git_path_prettify_dir(
&worktree_buf, worktree, repo->path_repository);
if (error < 0)
return error;
repo->workdir = git_buf_detach(&worktree_buf);
}
else if (error != GIT_ENOTFOUND) else if (error != GIT_ENOTFOUND)
return error; return error;
else { else {
......
...@@ -85,10 +85,18 @@ struct git_submodule { ...@@ -85,10 +85,18 @@ struct git_submodule {
}; };
/* Additional flags on top of public GIT_SUBMODULE_STATUS values */ /* Additional flags on top of public GIT_SUBMODULE_STATUS values */
#define GIT_SUBMODULE_STATUS__WD_SCANNED (1u << 15) enum {
#define GIT_SUBMODULE_STATUS__HEAD_OID_VALID (1u << 16) GIT_SUBMODULE_STATUS__WD_SCANNED = (1u << 20),
#define GIT_SUBMODULE_STATUS__INDEX_OID_VALID (1u << 17) GIT_SUBMODULE_STATUS__HEAD_OID_VALID = (1u << 21),
#define GIT_SUBMODULE_STATUS__WD_OID_VALID (1u << 18) GIT_SUBMODULE_STATUS__INDEX_OID_VALID = (1u << 22),
#define GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES (1u << 19) GIT_SUBMODULE_STATUS__WD_OID_VALID = (1u << 23),
GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE = (1u << 24),
GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE = (1u << 25),
GIT_SUBMODULE_STATUS__WD_NOT_SUBMODULE = (1u << 26),
GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES = (1u << 27),
};
#define GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(S) \
((S) & ~(0xFFFFFFFFu << 20))
#endif #endif
...@@ -50,7 +50,7 @@ void test_status_submodules__0(void) ...@@ -50,7 +50,7 @@ void test_status_submodules__0(void)
git_status_foreach(g_repo, cb_status__count, &counts) git_status_foreach(g_repo, cb_status__count, &counts)
); );
cl_assert(counts == 6); cl_assert_equal_i(6, counts);
} }
static const char *expected_files[] = { static const char *expected_files[] = {
...@@ -95,12 +95,12 @@ void test_status_submodules__1(void) ...@@ -95,12 +95,12 @@ void test_status_submodules__1(void)
git_status_foreach(g_repo, cb_status__match, &index) git_status_foreach(g_repo, cb_status__match, &index)
); );
cl_assert(index == 6); cl_assert_equal_i(6, index);
} }
void test_status_submodules__single_file(void) void test_status_submodules__single_file(void)
{ {
unsigned int status; unsigned int status = 0;
cl_git_pass( git_status_file(&status, g_repo, "testrepo") ); cl_git_pass( git_status_file(&status, g_repo, "testrepo") );
cl_assert(status == 0); cl_assert(!status);
} }
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