/*
* The MIT License
*
* Copyright (c) 2013 GitHub, Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "rugged.h"
extern VALUE rb_mRugged;
extern VALUE rb_cRuggedObject;
extern VALUE rb_cRuggedRepo;
VALUE rb_cRuggedTag;
/*
* call-seq:
* tag.target -> object
*
* Return the +object+ pointed at by this tag, as a Rugged::Object
* instance.
*
* tag.target #=> #
*/
static VALUE rb_git_tag_target_GET(VALUE self)
{
git_tag *tag;
git_object *target;
int error;
VALUE owner;
Data_Get_Struct(self, git_tag, tag);
owner = rugged_owner(self);
error = git_tag_target(&target, tag);
rugged_exception_check(error);
return rugged_object_new(owner, target);
}
/*
* call-seq:
* tag.target_oid -> oid
* tag.target_id -> oid
*
* Return the oid pointed at by this tag, as a String
* instance.
*
* tag.target_id #=> "2cb831a8aea28b2c1b9c63385585b864e4d3bad1"
*/
static VALUE rb_git_tag_target_id_GET(VALUE self)
{
git_tag *tag;
const git_oid *target_oid;
Data_Get_Struct(self, git_tag, tag);
target_oid = git_tag_target_id(tag);
return rugged_create_oid(target_oid);
}
/*
* call-seq:
* tag.type -> t
*
* Return a symbol representing the type of the objeced pointed at by
* this +tag+. Possible values are +:blob+, +:commit+, +:tree+ and +:tag+.
*
* This is always the same as the +type+ of the returned tag.target
*
* tag.type #=> :commit
* tag.target.type == tag.type #=> true
*/
static VALUE rb_git_tag_target_type_GET(VALUE self)
{
git_tag *tag;
Data_Get_Struct(self, git_tag, tag);
return rugged_otype_new(git_tag_target_type(tag));
}
/*
* call-seq:
* tag.name -> name
*
* Return a string with the name of this +tag+.
*
* tag.name #=> "v0.16.0"
*/
static VALUE rb_git_tag_name_GET(VALUE self)
{
git_tag *tag;
Data_Get_Struct(self, git_tag, tag);
return rugged_str_new2(git_tag_name(tag), NULL);
}
/*
* call-seq:
* tag.tagger -> signature
*
* Return the signature for the author of this +tag+. The signature
* is returned as a +Hash+ containing +:name+, +:email+ of the author
* and +:time+ of the tagging.
*
* tag.tagger #=> {:email=>"tanoku@gmail.com", :time=>Tue Jan 24 05:42:45 UTC 2012, :name=>"Vicent Mart\303\255"}
*/
static VALUE rb_git_tag_tagger_GET(VALUE self)
{
git_tag *tag;
const git_signature *tagger;
Data_Get_Struct(self, git_tag, tag);
tagger = git_tag_tagger(tag);
if (!tagger)
return Qnil;
return rugged_signature_new(tagger, NULL);
}
/*
* call-seq:
* tag.message -> msg
*
* Return the message of this +tag+. This includes the full body of the
* message and any optional footers or signatures after it.
*
* tag.message #=> "Release v0.16.0, codename 'broken stuff'"
*/
static VALUE rb_git_tag_message_GET(VALUE self)
{
git_tag *tag;
const char *message;
Data_Get_Struct(self, git_tag, tag);
message = git_tag_message(tag);
if (!message)
return Qnil;
return rugged_str_new2(message, NULL);
}
static VALUE rb_git_tag_create(VALUE self, VALUE rb_repo, VALUE rb_data)
{
git_oid tag_oid;
git_repository *repo = NULL;
int error, force = 0;
VALUE rb_name, rb_target, rb_tagger, rb_message, rb_force;
if (!rb_obj_is_kind_of(rb_repo, rb_cRuggedRepo))
rb_raise(rb_eTypeError, "Expecting a Rugged::Repository instance");
Data_Get_Struct(rb_repo, git_repository, repo);
if (TYPE(rb_data) == T_STRING) {
error = git_tag_create_frombuffer(
&tag_oid,
repo,
StringValueCStr(rb_data),
force
);
} else if (TYPE(rb_data) == T_HASH) {
git_object *target = NULL;
rb_name = rb_hash_aref(rb_data, CSTR2SYM("name"));
Check_Type(rb_name, T_STRING);
rb_force = rb_hash_aref(rb_data, CSTR2SYM("force"));
if (!NIL_P(rb_force))
force = rugged_parse_bool(rb_force);
/* only for heavy tags */
rb_tagger = rb_hash_aref(rb_data, CSTR2SYM("tagger"));
rb_message = rb_hash_aref(rb_data, CSTR2SYM("message"));
if (!NIL_P(rb_message))
Check_Type(rb_message, T_STRING);
rb_target = rb_hash_aref(rb_data, CSTR2SYM("target"));
target = rugged_object_get(repo, rb_target, GIT_OBJ_ANY);
if (!NIL_P(rb_tagger) && !NIL_P(rb_message)) {
git_signature *tagger = NULL;
tagger = rugged_signature_get(rb_tagger);
error = git_tag_create(
&tag_oid,
repo,
StringValueCStr(rb_name),
target,
tagger,
StringValueCStr(rb_message),
force
);
git_signature_free(tagger);
} else {
error = git_tag_create_lightweight(
&tag_oid,
repo,
StringValueCStr(rb_name),
target,
force
);
}
git_object_free(target);
} else {
rb_raise(rb_eTypeError, "Invalid tag data: expected a String or a Hash");
}
rugged_exception_check(error);
return rugged_create_oid(&tag_oid);
}
static VALUE rb_git_tag_each(int argc, VALUE *argv, VALUE self)
{
git_repository *repo;
git_strarray tags;
size_t i;
int error;
VALUE rb_repo, rb_pattern;
const char *pattern = NULL;
rb_scan_args(argc, argv, "11", &rb_repo, &rb_pattern);
if (!rb_block_given_p())
return rb_funcall(self, rb_intern("to_enum"), 3, CSTR2SYM("each"), rb_repo, rb_pattern);
if (!NIL_P(rb_pattern)) {
Check_Type(rb_pattern, T_STRING);
pattern = StringValueCStr(rb_pattern);
}
if (!rb_obj_is_kind_of(rb_repo, rb_cRuggedRepo))
rb_raise(rb_eTypeError, "Expecting a Rugged::Repository instance");
Data_Get_Struct(rb_repo, git_repository, repo);
error = git_tag_list_match(&tags, pattern ? pattern : "", repo);
rugged_exception_check(error);
for (i = 0; i < tags.count; ++i)
rb_yield(rugged_str_new2(tags.strings[i], NULL));
git_strarray_free(&tags);
return Qnil;
}
static VALUE rb_git_tag_delete(VALUE self, VALUE rb_repo, VALUE rb_name)
{
git_repository *repo;
int error;
if (!rb_obj_is_kind_of(rb_repo, rb_cRuggedRepo))
rb_raise(rb_eTypeError, "Expecting a Rugged::Repository instance");
Data_Get_Struct(rb_repo, git_repository, repo);
Check_Type(rb_name, T_STRING);
error = git_tag_delete(repo, StringValueCStr(rb_name));
rugged_exception_check(error);
return Qnil;
}
void Init_rugged_tag()
{
rb_cRuggedTag = rb_define_class_under(rb_mRugged, "Tag", rb_cRuggedObject);
rb_define_singleton_method(rb_cRuggedTag, "create", rb_git_tag_create, 2);
rb_define_singleton_method(rb_cRuggedTag, "each", rb_git_tag_each, -1);
rb_define_singleton_method(rb_cRuggedTag, "delete", rb_git_tag_delete, 2);
rb_define_method(rb_cRuggedTag, "message", rb_git_tag_message_GET, 0);
rb_define_method(rb_cRuggedTag, "name", rb_git_tag_name_GET, 0);
rb_define_method(rb_cRuggedTag, "target", rb_git_tag_target_GET, 0);
rb_define_method(rb_cRuggedTag, "target_oid", rb_git_tag_target_id_GET, 0);
rb_define_method(rb_cRuggedTag, "target_id", rb_git_tag_target_id_GET, 0);
rb_define_method(rb_cRuggedTag, "target_type", rb_git_tag_target_type_GET, 0);
rb_define_method(rb_cRuggedTag, "tagger", rb_git_tag_tagger_GET, 0);
}