Commit 68642bce by Russell Belfer

Merge pull request #1841 from libgit2/ntk/fix/loose_ambiguous

Make odb_loose return EAMBIGUOUS when required
parents 38859f29 209f9b67
...@@ -869,6 +869,7 @@ typedef struct { ...@@ -869,6 +869,7 @@ typedef struct {
uint32_t flags; uint32_t flags;
uint32_t mkdir_flags; uint32_t mkdir_flags;
mode_t dirmode; mode_t dirmode;
int error;
} cp_r_info; } cp_r_info;
#define GIT_CPDIR__MKDIR_DONE_FOR_TO_ROOT (1u << 10) #define GIT_CPDIR__MKDIR_DONE_FOR_TO_ROOT (1u << 10)
...@@ -907,20 +908,23 @@ static int _cp_r_callback(void *ref, git_buf *from) ...@@ -907,20 +908,23 @@ static int _cp_r_callback(void *ref, git_buf *from)
return 0; return 0;
if (git_buf_joinpath( if (git_buf_joinpath(
&info->to, info->to_root, from->ptr + info->from_prefix) < 0) &info->to, info->to_root, from->ptr + info->from_prefix) < 0) {
return -1; error = -1;
goto exit;
}
if (p_lstat(info->to.ptr, &to_st) < 0) { if (p_lstat(info->to.ptr, &to_st) < 0) {
if (errno != ENOENT && errno != ENOTDIR) { if (errno != ENOENT && errno != ENOTDIR) {
giterr_set(GITERR_OS, giterr_set(GITERR_OS,
"Could not access %s while copying files", info->to.ptr); "Could not access %s while copying files", info->to.ptr);
return -1; error = -1;
goto exit;
} }
} else } else
exists = true; exists = true;
if ((error = git_path_lstat(from->ptr, &from_st)) < 0) if ((error = git_path_lstat(from->ptr, &from_st)) < 0)
return error; goto exit;
if (S_ISDIR(from_st.st_mode)) { if (S_ISDIR(from_st.st_mode)) {
mode_t oldmode = info->dirmode; mode_t oldmode = info->dirmode;
...@@ -934,13 +938,14 @@ static int _cp_r_callback(void *ref, git_buf *from) ...@@ -934,13 +938,14 @@ static int _cp_r_callback(void *ref, git_buf *from)
error = _cp_r_mkdir(info, from); error = _cp_r_mkdir(info, from);
/* recurse onto target directory */ /* recurse onto target directory */
if (!error && (!exists || S_ISDIR(to_st.st_mode))) if (!error && (!exists || S_ISDIR(to_st.st_mode)) &&
error = git_path_direach(from, _cp_r_callback, info); ((error = git_path_direach(from, _cp_r_callback, info)) == GIT_EUSER))
error = info->error;
if (oldmode != 0) if (oldmode != 0)
info->dirmode = oldmode; info->dirmode = oldmode;
return error; goto exit;
} }
if (exists) { if (exists) {
...@@ -950,7 +955,8 @@ static int _cp_r_callback(void *ref, git_buf *from) ...@@ -950,7 +955,8 @@ static int _cp_r_callback(void *ref, git_buf *from)
if (p_unlink(info->to.ptr) < 0) { if (p_unlink(info->to.ptr) < 0) {
giterr_set(GITERR_OS, "Cannot overwrite existing file '%s'", giterr_set(GITERR_OS, "Cannot overwrite existing file '%s'",
info->to.ptr); info->to.ptr);
return -1; error = -1;
goto exit;
} }
} }
...@@ -963,7 +969,7 @@ static int _cp_r_callback(void *ref, git_buf *from) ...@@ -963,7 +969,7 @@ static int _cp_r_callback(void *ref, git_buf *from)
/* Make container directory on demand if needed */ /* Make container directory on demand if needed */
if ((info->flags & GIT_CPDIR_CREATE_EMPTY_DIRS) == 0 && if ((info->flags & GIT_CPDIR_CREATE_EMPTY_DIRS) == 0 &&
(error = _cp_r_mkdir(info, from)) < 0) (error = _cp_r_mkdir(info, from)) < 0)
return error; goto exit;
/* make symlink or regular file */ /* make symlink or regular file */
if (S_ISLNK(from_st.st_mode)) if (S_ISLNK(from_st.st_mode))
...@@ -977,6 +983,8 @@ static int _cp_r_callback(void *ref, git_buf *from) ...@@ -977,6 +983,8 @@ static int _cp_r_callback(void *ref, git_buf *from)
error = git_futils_cp(from->ptr, info->to.ptr, usemode); error = git_futils_cp(from->ptr, info->to.ptr, usemode);
} }
exit:
info->error = error;
return error; return error;
} }
...@@ -997,6 +1005,7 @@ int git_futils_cp_r( ...@@ -997,6 +1005,7 @@ int git_futils_cp_r(
info.flags = flags; info.flags = flags;
info.dirmode = dirmode; info.dirmode = dirmode;
info.from_prefix = path.size; info.from_prefix = path.size;
info.error = 0;
git_buf_init(&info.to, 0); git_buf_init(&info.to, 0);
/* precalculate mkdir flags */ /* precalculate mkdir flags */
...@@ -1018,6 +1027,9 @@ int git_futils_cp_r( ...@@ -1018,6 +1027,9 @@ int git_futils_cp_r(
git_buf_free(&path); git_buf_free(&path);
git_buf_free(&info.to); git_buf_free(&info.to);
if (error == GIT_EUSER)
error = info.error;
return error; return error;
} }
......
...@@ -499,7 +499,7 @@ static int fn_locate_object_short_oid(void *state, git_buf *pathbuf) { ...@@ -499,7 +499,7 @@ static int fn_locate_object_short_oid(void *state, git_buf *pathbuf) {
} }
if (sstate->found > 1) if (sstate->found > 1)
return git_odb__error_ambiguous("multiple matches in loose objects"); return GIT_EAMBIGUOUS;
return 0; return 0;
} }
...@@ -545,12 +545,16 @@ static int locate_object_short_oid( ...@@ -545,12 +545,16 @@ static int locate_object_short_oid(
/* Explore directory to find a unique object matching short_oid */ /* Explore directory to find a unique object matching short_oid */
error = git_path_direach( error = git_path_direach(
object_location, fn_locate_object_short_oid, &state); object_location, fn_locate_object_short_oid, &state);
if (error)
if (error && error != GIT_EUSER)
return error; return error;
if (!state.found) if (!state.found)
return git_odb__error_notfound("no matching loose object for prefix", short_oid); return git_odb__error_notfound("no matching loose object for prefix", short_oid);
if (state.found > 1)
return git_odb__error_ambiguous("multiple matches in loose objects");
/* Convert obtained hex formatted oid to raw */ /* Convert obtained hex formatted oid to raw */
error = git_oid_fromstr(res_oid, (char *)state.res_oid); error = git_oid_fromstr(res_oid, (char *)state.res_oid);
if (error) if (error)
......
...@@ -336,7 +336,7 @@ static int pack_backend__refresh(git_odb_backend *_backend) ...@@ -336,7 +336,7 @@ static int pack_backend__refresh(git_odb_backend *_backend)
git_buf_free(&path); git_buf_free(&path);
if (error < 0) if (error < 0)
return error; return -1;
git_vector_sort(&backend->packs); git_vector_sort(&backend->packs);
return 0; return 0;
......
...@@ -765,10 +765,10 @@ int git_path_direach( ...@@ -765,10 +765,10 @@ int git_path_direach(
git_buf_truncate(path, wd_len); /* restore path */ git_buf_truncate(path, wd_len); /* restore path */
if (result < 0) { if (result) {
closedir(dir); closedir(dir);
git__free(de_buf); git__free(de_buf);
return -1; return GIT_EUSER;
} }
} }
......
...@@ -299,7 +299,7 @@ static int packed_loadloose(refdb_fs_backend *backend) ...@@ -299,7 +299,7 @@ static int packed_loadloose(refdb_fs_backend *backend)
git_buf_free(&refs_path); git_buf_free(&refs_path);
return error; return (error == GIT_EUSER) ? -1 : error;
} }
static int refdb_fs_backend__exists( static int refdb_fs_backend__exists(
......
...@@ -544,6 +544,37 @@ void test_refs_revparse__a_too_short_objectid_returns_EAMBIGUOUS(void) ...@@ -544,6 +544,37 @@ void test_refs_revparse__a_too_short_objectid_returns_EAMBIGUOUS(void)
GIT_EAMBIGUOUS, git_revparse_single(&g_obj, g_repo, "e90")); GIT_EAMBIGUOUS, git_revparse_single(&g_obj, g_repo, "e90"));
} }
/*
* $ echo "aabqhq" | git hash-object -t blob --stdin
* dea509d0b3cb8ee0650f6ca210bc83f4678851ba
*
* $ echo "aaazvc" | git hash-object -t blob --stdin
* dea509d097ce692e167dfc6a48a7a280cc5e877e
*/
void test_refs_revparse__a_not_precise_enough_objectid_returns_EAMBIGUOUS(void)
{
git_repository *repo;
git_index *index;
git_object *obj;
repo = cl_git_sandbox_init("testrepo");
cl_git_mkfile("testrepo/one.txt", "aabqhq\n");
cl_git_mkfile("testrepo/two.txt", "aaazvc\n");
cl_git_pass(git_repository_index(&index, repo));
cl_git_pass(git_index_add_bypath(index, "one.txt"));
cl_git_pass(git_index_add_bypath(index, "two.txt"));
cl_git_fail_with(git_revparse_single(&obj, repo, "dea509d0"), GIT_EAMBIGUOUS);
cl_git_pass(git_revparse_single(&obj, repo, "dea509d09"));
git_object_free(obj);
git_index_free(index);
cl_git_sandbox_cleanup();
}
void test_refs_revparse__issue_994(void) void test_refs_revparse__issue_994(void)
{ {
git_repository *repo; git_repository *repo;
......
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