mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-06 15:29:22 +00:00
Merge pull request #1815 from libgit2/ntk/topic/stream_write/check_before_overwriting
Ask the odbbackend if the object exists before overwriting it
This commit is contained in:
commit
97affdf213
@ -92,6 +92,10 @@ struct git_odb_stream {
|
|||||||
/**
|
/**
|
||||||
* Store the contents of the stream as an object with the id
|
* Store the contents of the stream as an object with the id
|
||||||
* specified in `oid`.
|
* specified in `oid`.
|
||||||
|
*
|
||||||
|
* This method will *not* be invoked by libgit2 if the object pointed at
|
||||||
|
* by `oid` already exists in any backend. Libgit2 will however take care
|
||||||
|
* of properly disposing the stream through a call to `free()`.
|
||||||
*/
|
*/
|
||||||
int (*finalize_write)(git_odb_stream *stream, const git_oid *oid);
|
int (*finalize_write)(git_odb_stream *stream, const git_oid *oid);
|
||||||
|
|
||||||
|
@ -900,6 +900,10 @@ int git_odb_stream_write(git_odb_stream *stream, const char *buffer, size_t len)
|
|||||||
int git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stream)
|
int git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stream)
|
||||||
{
|
{
|
||||||
git_hash_final(out, stream->hash_ctx);
|
git_hash_final(out, stream->hash_ctx);
|
||||||
|
|
||||||
|
if (git_odb_exists(stream->backend->odb, out))
|
||||||
|
return 0;
|
||||||
|
|
||||||
return stream->finalize_write(stream, out);
|
return stream->finalize_write(stream, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -781,13 +781,6 @@ static int loose_backend__stream_fwrite(git_odb_stream *_stream, const git_oid *
|
|||||||
if (object_file_name(&final_path, backend, oid) < 0 ||
|
if (object_file_name(&final_path, backend, oid) < 0 ||
|
||||||
object_mkdir(&final_path, backend) < 0)
|
object_mkdir(&final_path, backend) < 0)
|
||||||
error = -1;
|
error = -1;
|
||||||
/*
|
|
||||||
* Don't try to add an existing object to the repository. This
|
|
||||||
* is what git does and allows us to sidestep the fact that
|
|
||||||
* we're not allowed to overwrite a read-only file on Windows.
|
|
||||||
*/
|
|
||||||
else if (git_path_exists(final_path.ptr) == true)
|
|
||||||
git_filebuf_cleanup(&stream->fbuf);
|
|
||||||
else
|
else
|
||||||
error = git_filebuf_commit_at(
|
error = git_filebuf_commit_at(
|
||||||
&stream->fbuf, final_path.ptr, GIT_OBJECT_FILE_MODE);
|
&stream->fbuf, final_path.ptr, GIT_OBJECT_FILE_MODE);
|
||||||
|
@ -41,14 +41,46 @@ void test_object_blob_fromchunks__can_create_a_blob_from_a_in_memory_chunk_provi
|
|||||||
|
|
||||||
cl_git_pass(git_oid_fromstr(&expected_oid, "321cbdf08803c744082332332838df6bd160f8f9"));
|
cl_git_pass(git_oid_fromstr(&expected_oid, "321cbdf08803c744082332332838df6bd160f8f9"));
|
||||||
|
|
||||||
cl_git_fail(git_object_lookup(&blob, repo, &expected_oid, GIT_OBJ_ANY));
|
cl_git_fail_with(
|
||||||
|
git_object_lookup(&blob, repo, &expected_oid, GIT_OBJ_ANY),
|
||||||
|
GIT_ENOTFOUND);
|
||||||
|
|
||||||
cl_git_pass(git_blob_create_fromchunks(&oid, repo, NULL, text_chunked_source_cb, &howmany));
|
cl_git_pass(git_blob_create_fromchunks(&oid, repo, NULL, text_chunked_source_cb, &howmany));
|
||||||
|
|
||||||
cl_git_pass(git_object_lookup(&blob, repo, &expected_oid, GIT_OBJ_ANY));
|
cl_git_pass(git_object_lookup(&blob, repo, &expected_oid, GIT_OBJ_ANY));
|
||||||
|
cl_assert(git_oid_cmp(&expected_oid, git_object_id(blob)) == 0);
|
||||||
|
|
||||||
git_object_free(blob);
|
git_object_free(blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_object_blob_fromchunks__doesnot_overwrite_an_already_existing_object(void)
|
||||||
|
{
|
||||||
|
git_buf path = GIT_BUF_INIT;
|
||||||
|
git_buf content = GIT_BUF_INIT;
|
||||||
|
git_oid expected_oid, oid;
|
||||||
|
int howmany = 7;
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&expected_oid, "321cbdf08803c744082332332838df6bd160f8f9"));
|
||||||
|
|
||||||
|
cl_git_pass(git_blob_create_fromchunks(&oid, repo, NULL, text_chunked_source_cb, &howmany));
|
||||||
|
|
||||||
|
/* Let's replace the content of the blob file storage with something else... */
|
||||||
|
cl_git_pass(git_buf_joinpath(&path, git_repository_path(repo), "objects/32/1cbdf08803c744082332332838df6bd160f8f9"));
|
||||||
|
cl_git_pass(p_unlink(git_buf_cstr(&path)));
|
||||||
|
cl_git_mkfile(git_buf_cstr(&path), "boom");
|
||||||
|
|
||||||
|
/* ...request a creation of the same blob... */
|
||||||
|
howmany = 7;
|
||||||
|
cl_git_pass(git_blob_create_fromchunks(&oid, repo, NULL, text_chunked_source_cb, &howmany));
|
||||||
|
|
||||||
|
/* ...and ensure the content of the faked blob file hasn't been altered */
|
||||||
|
cl_git_pass(git_futils_readbuffer(&content, git_buf_cstr(&path)));
|
||||||
|
cl_assert(!git__strcmp("boom", git_buf_cstr(&content)));
|
||||||
|
|
||||||
|
git_buf_free(&path);
|
||||||
|
git_buf_free(&content);
|
||||||
|
}
|
||||||
|
|
||||||
#define GITATTR "* text=auto\n" \
|
#define GITATTR "* text=auto\n" \
|
||||||
"*.txt text\n" \
|
"*.txt text\n" \
|
||||||
"*.data binary\n"
|
"*.data binary\n"
|
||||||
|
Loading…
Reference in New Issue
Block a user