mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-28 00:25:29 +00:00
Merge branch 'tagging' of https://github.com/nulltoken/libgit2 into development
Conflicts: include/git2/tag.h src/tag.c
This commit is contained in:
commit
3e3e4631a0
@ -140,7 +140,8 @@ GIT_EXTERN(const char *) git_tag_message(git_tag *t);
|
||||
* @param repo Repository where to store the tag
|
||||
*
|
||||
* @param tag_name Name for the tag; this name is validated
|
||||
* for consistency
|
||||
* for consistency. It should also not conflict with an
|
||||
* already existing tag name
|
||||
*
|
||||
* @param target OID to which this tag points; note that no
|
||||
* validation is done on this OID. Use the _o version of this
|
||||
@ -202,6 +203,78 @@ GIT_EXTERN(int) git_tag_create_frombuffer(
|
||||
git_repository *repo,
|
||||
const char *buffer);
|
||||
|
||||
/**
|
||||
* Create a new tag in the repository from an OID
|
||||
* and overwrite an already existing tag reference, if any.
|
||||
*
|
||||
* @param oid Pointer where to store the OID of the
|
||||
* newly created tag
|
||||
*
|
||||
* @param repo Repository where to store the tag
|
||||
*
|
||||
* @param tag_name Name for the tag; this name is validated
|
||||
* for consistency.
|
||||
*
|
||||
* @param target OID to which this tag points; note that no
|
||||
* validation is done on this OID. Use the _fo version of this
|
||||
* method to assure a proper object is being tagged
|
||||
*
|
||||
* @param target_type Type of the tagged OID; note that no
|
||||
* validation is performed here either
|
||||
*
|
||||
* @param tagger Signature of the tagger for this tag, and
|
||||
* of the tagging time
|
||||
*
|
||||
* @param message Full message for this tag
|
||||
*
|
||||
* @return 0 on success; error code otherwise.
|
||||
* A tag object is written to the ODB, and a proper reference
|
||||
* is written in the /refs/tags folder, pointing to it
|
||||
*/
|
||||
GIT_EXTERN(int) git_tag_create_f(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *tag_name,
|
||||
const git_oid *target,
|
||||
git_otype target_type,
|
||||
const git_signature *tagger,
|
||||
const char *message);
|
||||
|
||||
/**
|
||||
* Create a new tag in the repository from an existing
|
||||
* `git_object` instance and overwrite an already existing
|
||||
* tag reference, if any.
|
||||
*
|
||||
* This method replaces the `target` and `target_type`
|
||||
* paremeters of `git_tag_create_f` by a single instance
|
||||
* of a `const git_object *`, which is assured to be
|
||||
* a proper object in the ODB and hence will create
|
||||
* a valid tag
|
||||
*
|
||||
* @see git_tag_create_f
|
||||
*/
|
||||
GIT_EXTERN(int) git_tag_create_fo(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *tag_name,
|
||||
const git_object *target,
|
||||
const git_signature *tagger,
|
||||
const char *message);
|
||||
|
||||
/**
|
||||
* Delete an existing tag reference.
|
||||
*
|
||||
* @param repo Repository where lives the tag
|
||||
*
|
||||
* @param tag_name Name of the tag to be deleted;
|
||||
* this name is validated for consistency.
|
||||
*
|
||||
* @return 0 on success; error code otherwise.
|
||||
*/
|
||||
GIT_EXTERN(int) git_tag_delete(
|
||||
git_repository *repo,
|
||||
const char *tag_name);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
#endif
|
||||
|
141
src/tag.c
141
src/tag.c
@ -153,38 +153,61 @@ static int parse_tag_buffer(git_tag *tag, const char *buffer, const char *buffer
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
int git_tag_create_o(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *tag_name,
|
||||
const git_object *target,
|
||||
const git_signature *tagger,
|
||||
const char *message)
|
||||
static int retreive_tag_reference(git_reference **tag_reference_out, char *ref_name_out, git_repository *repo, const char *tag_name)
|
||||
{
|
||||
return git_tag_create(
|
||||
oid, repo, tag_name,
|
||||
git_object_id(target),
|
||||
git_object_type(target),
|
||||
tagger, message);
|
||||
git_reference *tag_ref;
|
||||
int error;
|
||||
|
||||
git__joinpath(ref_name_out, GIT_REFS_TAGS_DIR, tag_name);
|
||||
error = git_reference_lookup(&tag_ref, repo, ref_name_out);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
*tag_reference_out = tag_ref;
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
int git_tag_create(
|
||||
static int tag_create(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *tag_name,
|
||||
const git_oid *target,
|
||||
git_otype target_type,
|
||||
const git_signature *tagger,
|
||||
const char *message)
|
||||
const char *message,
|
||||
int allow_ref_overwrite)
|
||||
{
|
||||
size_t final_size = 0;
|
||||
git_odb_stream *stream;
|
||||
|
||||
const char *type_str;
|
||||
char *tagger_str;
|
||||
git_reference *new_ref;
|
||||
|
||||
char ref_name[MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH];
|
||||
|
||||
int type_str_len, tag_name_len, tagger_str_len, message_len;
|
||||
int error;
|
||||
int error, should_update_ref = 0;
|
||||
|
||||
/** Ensure the tag name doesn't conflict with an already existing
|
||||
reference unless overwriting has explictly been requested **/
|
||||
error = retreive_tag_reference(&new_ref, ref_name, repo, tag_name);
|
||||
|
||||
switch (error) {
|
||||
case GIT_SUCCESS:
|
||||
if (!allow_ref_overwrite)
|
||||
return GIT_EEXISTS;
|
||||
should_update_ref = 1;
|
||||
|
||||
/* Fall trough */
|
||||
|
||||
case GIT_ENOTFOUND:
|
||||
break;
|
||||
|
||||
default:
|
||||
return error;
|
||||
}
|
||||
|
||||
type_str = git_object_type2string(target_type);
|
||||
|
||||
@ -222,13 +245,14 @@ int git_tag_create(
|
||||
error = stream->finalize_write(oid, stream);
|
||||
stream->free(stream);
|
||||
|
||||
if (error == GIT_SUCCESS) {
|
||||
char ref_name[512];
|
||||
git_reference *new_ref;
|
||||
git__joinpath(ref_name, GIT_REFS_TAGS_DIR, tag_name);
|
||||
error = git_reference_create_oid(&new_ref, repo, ref_name, oid);
|
||||
}
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
if (!should_update_ref)
|
||||
error = git_reference_create_oid(&new_ref, repo, ref_name, oid);
|
||||
else
|
||||
error = git_reference_set_oid(new_ref, oid);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -261,6 +285,81 @@ cleanup:
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_tag_create_o(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *tag_name,
|
||||
const git_object *target,
|
||||
const git_signature *tagger,
|
||||
const char *message)
|
||||
{
|
||||
return tag_create(
|
||||
oid, repo, tag_name,
|
||||
git_object_id(target),
|
||||
git_object_type(target),
|
||||
tagger, message, 0);
|
||||
}
|
||||
|
||||
int git_tag_create(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *tag_name,
|
||||
const git_oid *target,
|
||||
git_otype target_type,
|
||||
const git_signature *tagger,
|
||||
const char *message)
|
||||
{
|
||||
return tag_create(
|
||||
oid, repo, tag_name,
|
||||
target,
|
||||
target_type,
|
||||
tagger, message, 0);
|
||||
}
|
||||
|
||||
int git_tag_create_fo(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *tag_name,
|
||||
const git_object *target,
|
||||
const git_signature *tagger,
|
||||
const char *message)
|
||||
{
|
||||
return tag_create(
|
||||
oid, repo, tag_name,
|
||||
git_object_id(target),
|
||||
git_object_type(target),
|
||||
tagger, message, 1);
|
||||
}
|
||||
|
||||
int git_tag_create_f(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *tag_name,
|
||||
const git_oid *target,
|
||||
git_otype target_type,
|
||||
const git_signature *tagger,
|
||||
const char *message)
|
||||
{
|
||||
return tag_create(
|
||||
oid, repo, tag_name,
|
||||
target,
|
||||
target_type,
|
||||
tagger, message, 1);
|
||||
}
|
||||
|
||||
int git_tag_delete(git_repository *repo, const char *tag_name)
|
||||
{
|
||||
int error;
|
||||
git_reference *tag_ref;
|
||||
char ref_name[MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH];
|
||||
|
||||
error = retreive_tag_reference(&tag_ref, ref_name, repo, tag_name);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
return git_reference_delete(tag_ref);
|
||||
}
|
||||
|
||||
int git_tag__parse(git_tag *tag, git_odb_object *obj)
|
||||
{
|
||||
assert(tag);
|
||||
|
135
tests/t08-tag.c
135
tests/t08-tag.c
@ -58,6 +58,9 @@ BEGIN_TEST(read0, "read and parse a tag from the repository")
|
||||
|
||||
must_be_true(git_oid_cmp(&id_commit, git_commit_id(commit)) == 0);
|
||||
|
||||
git_tag_close(tag1);
|
||||
git_tag_close(tag2);
|
||||
git_commit_close(commit);
|
||||
git_repository_free(repo);
|
||||
END_TEST
|
||||
|
||||
@ -72,20 +75,19 @@ BEGIN_TEST(write0, "write a tag to the repository and read it again")
|
||||
git_oid target_id, tag_id;
|
||||
const git_signature *tagger;
|
||||
git_reference *ref_tag;
|
||||
/* char hex_oid[41]; */
|
||||
|
||||
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
|
||||
|
||||
git_oid_mkstr(&target_id, tagged_commit);
|
||||
|
||||
/* create signatures */
|
||||
/* create signature */
|
||||
tagger = git_signature_new(TAGGER_NAME, TAGGER_EMAIL, 123456789, 60);
|
||||
must_be_true(tagger != NULL);
|
||||
|
||||
must_pass(git_tag_create(
|
||||
&tag_id, /* out id */
|
||||
repo,
|
||||
"the-tag", /* do not update the HEAD */
|
||||
"the-tag",
|
||||
&target_id,
|
||||
GIT_OBJ_COMMIT,
|
||||
tagger,
|
||||
@ -94,6 +96,7 @@ BEGIN_TEST(write0, "write a tag to the repository and read it again")
|
||||
git_signature_free((git_signature *)tagger);
|
||||
|
||||
must_pass(git_tag_lookup(&tag, repo, &tag_id));
|
||||
must_be_true(git_oid_cmp(git_tag_target_oid(tag), &target_id) == 0);
|
||||
|
||||
/* Check attributes were set correctly */
|
||||
tagger = git_tag_tagger(tag);
|
||||
@ -111,12 +114,136 @@ BEGIN_TEST(write0, "write a tag to the repository and read it again")
|
||||
|
||||
must_pass(remove_loose_object(REPOSITORY_FOLDER, (git_object *)tag));
|
||||
|
||||
git_tag_close(tag);
|
||||
git_repository_free(repo);
|
||||
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST(write1, "write a tag to the repository which points to an unknown oid and read it again")
|
||||
git_repository *repo;
|
||||
git_tag *tag;
|
||||
git_oid target_id, tag_id;
|
||||
const git_signature *tagger;
|
||||
git_reference *ref_tag;
|
||||
git_object *zombie;
|
||||
|
||||
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
|
||||
|
||||
git_oid_mkstr(&target_id, "deadbeef1b46c854b31185ea97743be6a8774479");
|
||||
|
||||
/* create signature */
|
||||
tagger = git_signature_new(TAGGER_NAME, TAGGER_EMAIL, 123456789, 60);
|
||||
must_be_true(tagger != NULL);
|
||||
|
||||
must_pass(git_tag_create(
|
||||
&tag_id, /* out id */
|
||||
repo,
|
||||
"the-zombie-tag",
|
||||
&target_id,
|
||||
GIT_OBJ_COMMIT,
|
||||
tagger,
|
||||
TAGGER_MESSAGE));
|
||||
|
||||
git_signature_free((git_signature *)tagger);
|
||||
|
||||
must_pass(git_tag_lookup(&tag, repo, &tag_id));
|
||||
|
||||
/* The non existent target can not be looked up */
|
||||
must_fail(git_tag_target(&zombie, tag));
|
||||
|
||||
must_pass(git_reference_lookup(&ref_tag, repo, "refs/tags/the-zombie-tag"));
|
||||
|
||||
must_pass(git_reference_delete(ref_tag));
|
||||
must_pass(remove_loose_object(REPOSITORY_FOLDER, (git_object *)tag));
|
||||
|
||||
git_tag_close(tag);
|
||||
git_repository_free(repo);
|
||||
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST(write2, "Attempt to write a tag bearing the same name than an already existing tag")
|
||||
git_repository *repo;
|
||||
git_oid target_id, tag_id;
|
||||
const git_signature *tagger;
|
||||
|
||||
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
|
||||
|
||||
git_oid_mkstr(&target_id, tagged_commit);
|
||||
|
||||
/* create signature */
|
||||
tagger = git_signature_new(TAGGER_NAME, TAGGER_EMAIL, 123456789, 60);
|
||||
must_be_true(tagger != NULL);
|
||||
|
||||
must_fail(git_tag_create(
|
||||
&tag_id, /* out id */
|
||||
repo,
|
||||
"very-simple",
|
||||
&target_id,
|
||||
GIT_OBJ_COMMIT,
|
||||
tagger,
|
||||
TAGGER_MESSAGE));
|
||||
|
||||
git_signature_free((git_signature *)tagger);
|
||||
|
||||
git_repository_free(repo);
|
||||
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST(write3, "Replace an already existing tag")
|
||||
git_repository *repo;
|
||||
git_oid target_id, tag_id, old_tag_id;
|
||||
const git_signature *tagger;
|
||||
git_reference *ref_tag;
|
||||
|
||||
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
|
||||
|
||||
git_oid_mkstr(&target_id, tagged_commit);
|
||||
|
||||
must_pass(git_reference_lookup(&ref_tag, repo, "refs/tags/very-simple"));
|
||||
git_oid_cpy(&old_tag_id, git_reference_oid(ref_tag));
|
||||
|
||||
/* create signature */
|
||||
tagger = git_signature_new(TAGGER_NAME, TAGGER_EMAIL, 123456789, 60);
|
||||
must_be_true(tagger != NULL);
|
||||
|
||||
must_pass(git_tag_create_f(
|
||||
&tag_id, /* out id */
|
||||
repo,
|
||||
"very-simple",
|
||||
&target_id,
|
||||
GIT_OBJ_COMMIT,
|
||||
tagger,
|
||||
TAGGER_MESSAGE));
|
||||
|
||||
git_signature_free((git_signature *)tagger);
|
||||
|
||||
must_pass(git_reference_lookup(&ref_tag, repo, "refs/tags/very-simple"));
|
||||
must_be_true(git_oid_cmp(git_reference_oid(ref_tag), &tag_id) == 0);
|
||||
must_be_true(git_oid_cmp(git_reference_oid(ref_tag), &old_tag_id) != 0);
|
||||
|
||||
close_temp_repo(repo);
|
||||
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST(write4, "Delete an already existing tag")
|
||||
git_repository *repo;
|
||||
git_reference *ref_tag;
|
||||
|
||||
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
|
||||
|
||||
must_pass(git_tag_delete(repo,"very-simple"));
|
||||
|
||||
must_fail(git_reference_lookup(&ref_tag, repo, "refs/tags/very-simple"));
|
||||
|
||||
close_temp_repo(repo);
|
||||
|
||||
END_TEST
|
||||
|
||||
BEGIN_SUITE(tag)
|
||||
ADD_TEST(read0);
|
||||
ADD_TEST(write0);
|
||||
ADD_TEST(write0);
|
||||
ADD_TEST(write1);
|
||||
ADD_TEST(write2);
|
||||
ADD_TEST(write3);
|
||||
ADD_TEST(write4);
|
||||
END_SUITE
|
||||
|
@ -227,9 +227,8 @@ BEGIN_TEST(create0, "create a new symbolic reference")
|
||||
must_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
|
||||
must_be_true(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
|
||||
|
||||
git_reference_delete(looked_up_ref);
|
||||
git_repository_free(repo);
|
||||
|
||||
must_pass(gitfo_unlink(ref_path)); /* TODO: replace with git_reference_delete() when available */
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST(create1, "create a deep symbolic reference")
|
||||
@ -250,9 +249,8 @@ BEGIN_TEST(create1, "create a deep symbolic reference")
|
||||
must_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
|
||||
must_be_true(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
|
||||
|
||||
git_reference_delete(looked_up_ref);
|
||||
git_repository_free(repo);
|
||||
|
||||
must_pass(gitfo_unlink(ref_path)); /* TODO: replace with git_reference_delete() when available */
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST(create2, "create a new OID reference")
|
||||
@ -290,9 +288,28 @@ BEGIN_TEST(create2, "create a new OID reference")
|
||||
must_pass(git_reference_lookup(&looked_up_ref, repo, new_head));
|
||||
must_be_true(git_oid_cmp(&id, git_reference_oid(looked_up_ref)) == 0);
|
||||
|
||||
git_reference_delete(looked_up_ref);
|
||||
git_repository_free(repo);
|
||||
END_TEST
|
||||
|
||||
must_pass(gitfo_unlink(ref_path)); /* TODO: replace with git_reference_delete() when available */
|
||||
BEGIN_TEST(create3, "Can not create a new OID reference which targets at an unknown id")
|
||||
git_reference *new_reference, *looked_up_ref;
|
||||
git_repository *repo;
|
||||
git_oid id;
|
||||
|
||||
const char *new_head = "refs/heads/new-head";
|
||||
|
||||
git_oid_mkstr(&id, "deadbeef3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
|
||||
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
|
||||
|
||||
/* Create and write the new object id reference */
|
||||
must_fail(git_reference_create_oid(&new_reference, repo, new_head, &id));
|
||||
|
||||
/* Ensure the reference can't be looked-up... */
|
||||
must_fail(git_reference_lookup(&looked_up_ref, repo, new_head));
|
||||
|
||||
git_repository_free(repo);
|
||||
END_TEST
|
||||
|
||||
static const char *ref_name = "refs/heads/other";
|
||||
@ -892,6 +909,7 @@ BEGIN_SUITE(refs)
|
||||
ADD_TEST(create0);
|
||||
ADD_TEST(create1);
|
||||
ADD_TEST(create2);
|
||||
ADD_TEST(create3);
|
||||
|
||||
ADD_TEST(overwrite0);
|
||||
ADD_TEST(overwrite1);
|
||||
|
Loading…
Reference in New Issue
Block a user