summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti <vicent@github.com>2014-09-17 15:39:57 +0200
committerVicent Marti <vicent@github.com>2014-09-17 15:39:57 +0200
commit276d9ea3a664b1c1a75a72a05744fd7fc078538e (patch)
treeae900f0dbde48f21a95482af14e2f2af851730e5
parent5c22c4a20519b066e00a25b57c2266e829d905a5 (diff)
parent74240afb9c3394d35dfb3fe59dc38dbff70c0368 (diff)
downloadlibgit2-276d9ea3a664b1c1a75a72a05744fd7fc078538e.tar.gz
Merge pull request #2571 from libgit2/vmg/walk-up-path
Fix `git_path_walk_up` to work with non-rooted paths
-rw-r--r--src/attr.c16
-rw-r--r--src/fileops.c8
-rw-r--r--src/ignore.c4
-rw-r--r--src/path.c19
-rw-r--r--src/path.h2
-rw-r--r--src/repository.c16
-rw-r--r--tests/attr/repo.c7
-rw-r--r--tests/core/path.c53
-rw-r--r--tests/path/core.c2
9 files changed, 86 insertions, 41 deletions
diff --git a/src/attr.c b/src/attr.c
index dee84b0ab..a02172689 100644
--- a/src/attr.c
+++ b/src/attr.c
@@ -377,7 +377,7 @@ static int push_attr_file(
return error;
}
-static int push_one_attr(void *ref, git_buf *path)
+static int push_one_attr(void *ref, const char *path)
{
int error = 0, n_src, i;
attr_walk_up_info *info = (attr_walk_up_info *)ref;
@@ -388,7 +388,7 @@ static int push_one_attr(void *ref, git_buf *path)
for (i = 0; !error && i < n_src; ++i)
error = push_attr_file(
- info->repo, info->files, src[i], path->ptr, GIT_ATTR_FILE);
+ info->repo, info->files, src[i], path, GIT_ATTR_FILE);
return error;
}
@@ -422,10 +422,8 @@ static int collect_attr_files(
/* Resolve path in a non-bare repo */
if (workdir != NULL)
error = git_path_find_dir(&dir, path, workdir);
- /* when in a bare repo, find the containing folder if the given
- * path is a subfolder (if not, the containing folder is the root) */
- else if (strchr(path, '/') != NULL)
- error = git_path_dirname_r(&dir, path);
+ else
+ error = git_path_dirname_r(&dir, path);
if (error < 0)
goto cleanup;
@@ -449,7 +447,11 @@ static int collect_attr_files(
giterr_clear(); /* no error even if there is no index */
info.files = files;
- error = git_path_walk_up(&dir, workdir, push_one_attr, &info);
+ if (!strcmp(dir.ptr, "."))
+ error = push_one_attr(&info, "");
+ else
+ error = git_path_walk_up(&dir, workdir, push_one_attr, &info);
+
if (error < 0)
goto cleanup;
diff --git a/src/fileops.c b/src/fileops.c
index 34659ad3b..bd9d27c7a 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -505,15 +505,15 @@ static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path)
return error;
}
-static int futils__rmdir_empty_parent(void *opaque, git_buf *path)
+static int futils__rmdir_empty_parent(void *opaque, const char *path)
{
futils__rmdir_data *data = opaque;
int error = 0;
- if (git_buf_len(path) <= data->baselen)
+ if (strlen(path) <= data->baselen)
error = GIT_ITEROVER;
- else if (p_rmdir(git_buf_cstr(path)) < 0) {
+ else if (p_rmdir(path) < 0) {
int en = errno;
if (en == ENOENT || en == ENOTDIR) {
@@ -521,7 +521,7 @@ static int futils__rmdir_empty_parent(void *opaque, git_buf *path)
} else if (en == ENOTEMPTY || en == EEXIST || en == EBUSY) {
error = GIT_ITEROVER;
} else {
- error = git_path_set_error(errno, git_buf_cstr(path), "rmdir");
+ error = git_path_set_error(errno, path, "rmdir");
}
}
diff --git a/src/ignore.c b/src/ignore.c
index 78f01ac44..520bcfe41 100644
--- a/src/ignore.c
+++ b/src/ignore.c
@@ -91,11 +91,11 @@ static int push_ignore_file(
return error;
}
-static int push_one_ignore(void *payload, git_buf *path)
+static int push_one_ignore(void *payload, const char *path)
{
git_ignores *ign = payload;
ign->depth++;
- return push_ignore_file(ign, &ign->ign_path, path->ptr, GIT_IGNORE_FILE);
+ return push_ignore_file(ign, &ign->ign_path, path, GIT_IGNORE_FILE);
}
static int get_internal_ignores(git_attr_file **out, git_repository *repo)
diff --git a/src/path.c b/src/path.c
index 11c022812..67133f97e 100644
--- a/src/path.c
+++ b/src/path.c
@@ -417,7 +417,7 @@ int git_path_fromurl(git_buf *local_path_out, const char *file_url)
int git_path_walk_up(
git_buf *path,
const char *ceiling,
- int (*cb)(void *data, git_buf *),
+ int (*cb)(void *data, const char *),
void *data)
{
int error = 0;
@@ -435,12 +435,20 @@ int git_path_walk_up(
}
scan = git_buf_len(path);
+ /* empty path: yield only once */
+ if (!scan) {
+ error = cb(data, "");
+ if (error)
+ giterr_set_after_callback(error);
+ return error;
+ }
+
iter.ptr = path->ptr;
iter.size = git_buf_len(path);
iter.asize = path->asize;
while (scan >= stop) {
- error = cb(data, &iter);
+ error = cb(data, iter.ptr);
iter.ptr[scan] = oldc;
if (error) {
@@ -460,6 +468,13 @@ int git_path_walk_up(
if (scan >= 0)
iter.ptr[scan] = oldc;
+ /* relative path: yield for the last component */
+ if (!error && stop == 0 && iter.ptr[0] != '/') {
+ error = cb(data, "");
+ if (error)
+ giterr_set_after_callback(error);
+ }
+
return error;
}
diff --git a/src/path.h b/src/path.h
index d0a9de707..11bb6d173 100644
--- a/src/path.h
+++ b/src/path.h
@@ -323,7 +323,7 @@ extern int git_path_cmp(
extern int git_path_walk_up(
git_buf *pathbuf,
const char *ceiling,
- int (*callback)(void *payload, git_buf *path),
+ int (*callback)(void *payload, const char *path),
void *payload);
/**
diff --git a/src/repository.c b/src/repository.c
index 39a4f02b9..51d39eb6d 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -1691,20 +1691,20 @@ int git_repository_set_bare(git_repository *repo)
if (repo->is_bare)
return 0;
- if ((error = git_repository_config__weakptr(&config, repo)) < 0 ||
- (error = git_config_set_bool(config, "core.bare", false)) < 0)
- goto done;
+ if ((error = git_repository_config__weakptr(&config, repo)) < 0)
+ return error;
+
+ if ((error = git_config_set_bool(config, "core.bare", false)) < 0)
+ return error;
- error = git_config__update_entry(config, "core.worktree", NULL, true, true);
+ if ((error = git_config__update_entry(config, "core.worktree", NULL, true, true)) < 0)
+ return error;
git__free(repo->workdir);
repo->workdir = NULL;
-
repo->is_bare = 1;
-done:
- git_config_free(config);
- return error;
+ return 0;
}
int git_repository_head_tree(git_tree **tree, git_repository *repo)
diff --git a/tests/attr/repo.c b/tests/attr/repo.c
index e8b74c08c..8baf50622 100644
--- a/tests/attr/repo.c
+++ b/tests/attr/repo.c
@@ -368,4 +368,11 @@ void test_attr_repo__bare_repo_with_index(void)
cl_assert_equal_s("barfoo", values[1]);
cl_assert(GIT_ATTR_UNSPECIFIED(values[2]));
cl_assert(GIT_ATTR_TRUE(values[3]));
+
+ cl_git_pass(git_attr_get_many(values, g_repo, 0, "sub/sub/subdir.txt", 4, names));
+
+ cl_assert(GIT_ATTR_TRUE(values[0]));
+ cl_assert_equal_s("foobar", values[1]);
+ cl_assert(GIT_ATTR_FALSE(values[2]));
+ cl_assert(GIT_ATTR_UNSPECIFIED(values[3]));
}
diff --git a/tests/core/path.c b/tests/core/path.c
index 471491b87..7d3e4938f 100644
--- a/tests/core/path.c
+++ b/tests/core/path.c
@@ -356,7 +356,7 @@ typedef struct {
#define CANCEL_VALUE 1234
-static int check_one_walkup_step(void *ref, git_buf *path)
+static int check_one_walkup_step(void *ref, const char *path)
{
check_walkup_info *info = (check_walkup_info *)ref;
@@ -367,7 +367,7 @@ static int check_one_walkup_step(void *ref, git_buf *path)
info->cancel_after--;
cl_assert(info->expect[info->expect_idx] != NULL);
- cl_assert_equal_s(info->expect[info->expect_idx], path->ptr);
+ cl_assert_equal_s(info->expect[info->expect_idx], path);
info->expect_idx++;
return 0;
@@ -376,18 +376,42 @@ static int check_one_walkup_step(void *ref, git_buf *path)
void test_core_path__11_walkup(void)
{
git_buf p = GIT_BUF_INIT;
+
char *expect[] = {
- "/a/b/c/d/e/", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
- "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
- "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
- "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
- "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", NULL,
- "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", NULL,
- "this is a path", NULL,
- "///a///b///c///d///e///", "///a///b///c///d///", "///a///b///c///", "///a///b///", "///a///", "///", NULL,
- NULL
+ /* 1 */ "/a/b/c/d/e/", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
+ /* 2 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
+ /* 3 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
+ /* 4 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
+ /* 5 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", NULL,
+ /* 6 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", NULL,
+ /* 7 */ "this_is_a_path", "", NULL,
+ /* 8 */ "this_is_a_path/", "", NULL,
+ /* 9 */ "///a///b///c///d///e///", "///a///b///c///d///", "///a///b///c///", "///a///b///", "///a///", "///", NULL,
+ /* 10 */ "a/b/c/", "a/b/", "a/", "", NULL,
+ /* 11 */ "a/b/c", "a/b/", "a/", "", NULL,
+ /* 12 */ "a/b/c/", "a/b/", "a/", NULL,
+ /* 13 */ "", NULL,
+ /* 14 */ "/", NULL,
+ /* 15 */ NULL
+ };
+
+ char *root[] = {
+ /* 1 */ NULL,
+ /* 2 */ NULL,
+ /* 3 */ "/",
+ /* 4 */ "",
+ /* 5 */ "/a/b",
+ /* 6 */ "/a/b/",
+ /* 7 */ NULL,
+ /* 8 */ NULL,
+ /* 9 */ NULL,
+ /* 10 */ NULL,
+ /* 11 */ NULL,
+ /* 12 */ "a/",
+ /* 13 */ NULL,
+ /* 14 */ NULL,
};
- char *root[] = { NULL, NULL, "/", "", "/a/b", "/a/b/", NULL, NULL, NULL };
+
int i, j;
check_walkup_info info;
@@ -404,9 +428,8 @@ void test_core_path__11_walkup(void)
);
cl_assert_equal_s(p.ptr, expect[i]);
-
- /* skip to next run of expectations */
- while (expect[i] != NULL) i++;
+ cl_assert(expect[info.expect_idx] == NULL);
+ i = info.expect_idx;
}
git_buf_free(&p);
diff --git a/tests/path/core.c b/tests/path/core.c
index be63e309b..45f54df29 100644
--- a/tests/path/core.c
+++ b/tests/path/core.c
@@ -16,8 +16,6 @@ static void test_make_relative(
void test_path_core__make_relative(void)
{
- git_buf buf = GIT_BUF_INIT;
-
test_make_relative("foo.c", "/path/to/foo.c", "/path/to", 0);
test_make_relative("bar/foo.c", "/path/to/bar/foo.c", "/path/to", 0);
test_make_relative("foo.c", "/path/to/foo.c", "/path/to/", 0);