/*
* The MIT License
*
* Copyright (c) 2010 - 2011 Shuhei Tanuma
*
* 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 "php_git.h"
#include
#include
#include
#include
extern void create_tree_entry_from_entry(zval **object, git_tree_entry *entry, git_repository *repository);
extern zend_object_value php_git_repository_new(zend_class_entry *ce TSRMLS_DC);
PHPAPI zend_class_entry *git_commit_class_entry;
ZEND_BEGIN_ARG_INFO_EX(arginfo_git_commit__construct, 0, 0, 1)
ZEND_ARG_INFO(0, repository)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_git_commit_get_parent, 0, 0, 1)
ZEND_ARG_INFO(0, offset)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_git_commit_set_author, 0, 0, 1)
ZEND_ARG_INFO(0, author)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_git_commit_set_committer, 0, 0, 1)
ZEND_ARG_INFO(0, committer)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_git_commit_set_parents, 0, 0, 1)
ZEND_ARG_INFO(0, parents)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_git_commit_set_message, 0, 0, 1)
ZEND_ARG_INFO(0, message)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_git_commit_set_tree, 0, 0, 1)
ZEND_ARG_INFO(0, tree)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_git_commit_write, 0, 0, 1)
ZEND_ARG_INFO(0, update_ref)
ZEND_END_ARG_INFO()
static void php_git_commit_free_storage(php_git_commit_t *obj TSRMLS_DC)
{
zend_object_std_dtor(&obj->zo TSRMLS_CC);
obj->object = NULL;
obj->repository = NULL;
efree(obj);
}
zend_object_value php_git_commit_new(zend_class_entry *ce TSRMLS_DC)
{
zend_object_value retval;
php_git_commit_t *obj;
zval *tmp;
obj = ecalloc(1, sizeof(*obj));
zend_object_std_init( &obj->zo, ce TSRMLS_CC );
zend_hash_copy(obj->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
retval.handle = zend_objects_store_put(obj,
(zend_objects_store_dtor_t)zend_objects_destroy_object,
(zend_objects_free_object_storage_t)php_git_commit_free_storage,
NULL TSRMLS_CC);
retval.handlers = zend_get_std_object_handlers();
return retval;
}
PHP_METHOD(git_commit, __construct)
{
zval *object = getThis();
zval *z_repository;
git_commit *commit;
git_repository *repository;
int ret;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"z", &z_repository) == FAILURE){
return;
}
object_init_ex(object, git_commit_class_entry);
php_git_commit_t *cobj = (php_git_commit_t *) zend_object_store_get_object(object TSRMLS_CC);
php_git_repository_t *myobj = (php_git_repository_t *) zend_object_store_get_object(z_repository TSRMLS_CC);
cobj->repository = myobj->repository;
}
PHP_METHOD(git_commit, getCommitter)
{
zval *object = getThis();
zval *signature = zend_read_property(git_commit_class_entry, object,"committer",9, 0 TSRMLS_CC);
zval_copy_ctor(signature);
RETURN_ZVAL(signature,0, 0);
}
PHP_METHOD(git_commit, getMessage)
{
php_git_commit_t *this = (php_git_commit_t *) zend_object_store_get_object(getThis() TSRMLS_CC);
const char *message;
message = git_commit_message(this->object);
RETURN_STRING(message,1);
}
PHP_METHOD(git_commit, getShortMessage)
{
php_git_commit_t *this = (php_git_commit_t *) zend_object_store_get_object(getThis() TSRMLS_CC);
const char *message;
message = git_commit_message_short(this->object);
RETURN_STRING(message,1);
}
PHP_METHOD(git_commit, getTree)
{
php_git_commit_t *this = (php_git_commit_t *) zend_object_store_get_object(getThis() TSRMLS_CC);
git_tree *ref_tree, *tree;
git_oid *tree_oid;
zval *git_tree, *entry;
const git_oid *oid;
git_commit_tree(&ref_tree, this->object);
oid = git_object_id((git_object*)ref_tree);
int ret = git_object_lookup((git_object **)&tree, git_object_owner((git_object*)this->object),oid, GIT_OBJ_TREE);
if(ret != GIT_SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "specified tree not found.");
return;
}
MAKE_STD_ZVAL(git_tree);
object_init_ex(git_tree, git_tree_class_entry);
php_git_tree_t *tobj = (php_git_tree_t *) zend_object_store_get_object(git_tree TSRMLS_CC);
tobj->object = tree;
tobj->repository = this->repository;
RETURN_ZVAL(git_tree,0,1);
}
PHP_METHOD(git_commit, setAuthor)
{
php_git_commit_t *this = (php_git_commit_t *) zend_object_store_get_object(getThis() TSRMLS_CC);
zval *author;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"z", &author) == FAILURE){
return;
}
if(!instanceof_function(Z_OBJCE_P(author), git_signature_class_entry TSRMLS_CC)){
fprintf(stderr,"Git\\Commit::setAuthor() requires Git\\Signature");
return;
}
add_property_zval(getThis(),"author", author);
}
PHP_METHOD(git_commit, setCommitter)
{
php_git_commit_t *this = (php_git_commit_t *) zend_object_store_get_object(getThis() TSRMLS_CC);
zval *committer;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"z", &committer) == FAILURE){
return;
}
if(!instanceof_function(Z_OBJCE_P(committer), git_signature_class_entry TSRMLS_CC)){
fprintf(stderr,"Git\\Commit::setCommitter() requires Git\\Signature");
return;
}
add_property_zval(getThis(),"committer", committer);
}
PHP_METHOD(git_commit, setTree)
{
php_git_commit_t *this = (php_git_commit_t *) zend_object_store_get_object(getThis() TSRMLS_CC);
char *tree;
int tree_len;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"s", &tree,&tree_len) == FAILURE){
return;
}
add_property_string(getThis(),"tree", tree,1);
}
PHP_METHOD(git_commit, setParents)
{
php_git_commit_t *this = (php_git_commit_t *) zend_object_store_get_object(getThis() TSRMLS_CC);
zval *parents;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"z", &parents) == FAILURE){
return;
}
add_property_zval(getThis(),"parents", parents);
}
PHP_METHOD(git_commit, write)
{
php_git_commit_t *this = (php_git_commit_t *) zend_object_store_get_object(getThis() TSRMLS_CC);
git_oid oid, tree_oid, **parents, **p, *tmp;
php_git_signature_t *author, *committer;
zval *z_author, *z_committer, *z_parents, **data;
char *update_ref, *message, *tree_oid_str = NULL;
char out[GIT_OID_HEXSZ+1];
int count, i, update_ref_len = 0;
git_reference *ref;
HashTable *array_hash;
HashPosition pointer;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"|s", &update_ref,&update_ref_len) == FAILURE){
return;
}
if(ZEND_NUM_ARGS() == 0) {
if(git_reference_lookup(&ref,this->repository,"HEAD")==GIT_SUCCESS){
if (git_reference_type(ref) == GIT_REF_SYMBOLIC) {
git_reference *ref2;
git_reference_resolve(&ref2,ref);
update_ref = (char *)git_reference_name(ref2);
} else {
update_ref = (char *)git_reference_name(ref);
}
}
}
tree_oid_str = Z_STRVAL_P(zend_read_property(git_commit_class_entry, getThis(),"tree",sizeof("tree")-1, 0 TSRMLS_CC));
git_oid_fromstr(&tree_oid, tree_oid_str);
z_author = zend_read_property(git_commit_class_entry, getThis(),"author",sizeof("author")-1, 0 TSRMLS_CC);
author = (php_git_signature_t *) zend_object_store_get_object(z_author TSRMLS_CC);
z_committer = zend_read_property(git_commit_class_entry, getThis(),"committer",sizeof("committer")-1, 0 TSRMLS_CC);
committer = (php_git_signature_t *) zend_object_store_get_object(z_committer TSRMLS_CC);
z_parents = zend_read_property(git_commit_class_entry, getThis(),"parents",sizeof("parents")-1, 0 TSRMLS_CC);
count = zend_hash_num_elements(Z_ARRVAL_P(z_parents));
array_hash = Z_ARRVAL_P(z_parents);
parents = (git_oid**)calloc(count,sizeof(git_oid));
p = parents;
for (zend_hash_internal_pointer_reset_ex(array_hash, &pointer);
zend_hash_has_more_elements_ex(array_hash,&pointer) == SUCCESS;
zend_hash_move_forward_ex(array_hash,&pointer)
) {
tmp = (git_oid *)malloc(sizeof(git_oid));
zend_hash_get_current_data_ex(array_hash, (void **)&data, &pointer);
git_oid_fromstr(tmp,Z_STRVAL_PP(data));
*p = tmp;
p++;
}
message = Z_STRVAL_P(zend_read_property(git_commit_class_entry, getThis(),"message",sizeof("message")-1, 0 TSRMLS_CC));
git_commit_create(&oid,
this->repository,
update_ref,
author->signature,
committer->signature,
NULL, // Message encoding (Should probably fix this at some point)
message,
&tree_oid,
count,
parents
);
git_oid_to_string(out,GIT_OID_HEXSZ+1,&oid);
for(i = 0; i < count;i++){
free(parents[i]);
}
free(parents);
RETVAL_STRING(out,1);
}
PHP_METHOD(git_commit, setMessage)
{
php_git_commit_t *this = (php_git_commit_t *) zend_object_store_get_object(getThis() TSRMLS_CC);
char *message;
int message_len;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"s", &message,&message_len) == FAILURE){
return;
}
add_property_string(getThis(),"message", message, 1);
}
PHP_METHOD(git_commit, getAuthor)
{
zval *object = getThis();
zval *signature = zend_read_property(git_commit_class_entry, object,"author",6, 0 TSRMLS_CC);
zval_copy_ctor(signature);
RETURN_ZVAL(signature,0, 0);
}
PHP_METHOD(git_commit, getParent)
{
php_git_commit_t *this = (php_git_commit_t *) zend_object_store_get_object(getThis() TSRMLS_CC);
php_git_commit_t *obj;
git_commit *commit;
zval *zcommit;
int offset = 0;
int ret = 0;
zval *author;
zval *committer;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"|l", &offset) == FAILURE){
return;
}
ret = git_commit_parent(&commit, this->object,offset);
if(ret != GIT_SUCCESS){
//zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "specified offset not found");
RETURN_FALSE;
}
php_git_commit_init(&zcommit, commit, this->repository TSRMLS_CC);
RETURN_ZVAL(zcommit,0,1);
}
PHP_METHOD(git_commit, getId)
{
php_git_commit_t *this = (php_git_commit_t *) zend_object_store_get_object(getThis() TSRMLS_CC);
git_oid *oid = git_commit_id(this->object);
char id[GIT_OID_HEXSZ+1] = {0};
git_oid_to_string(id,GIT_OID_HEXSZ+1,oid);
RETURN_STRING(id,1);
}
static zend_function_entry php_git_commit_methods[] = {
PHP_ME(git_commit, __construct, arginfo_git_commit__construct, ZEND_ACC_PUBLIC)
PHP_ME(git_commit, getId, NULL, ZEND_ACC_PUBLIC)
PHP_ME(git_commit, setAuthor, arginfo_git_commit_set_author, ZEND_ACC_PUBLIC)
PHP_ME(git_commit, setCommitter, arginfo_git_commit_set_committer,ZEND_ACC_PUBLIC)
PHP_ME(git_commit, setParents, arginfo_git_commit_set_parents, ZEND_ACC_PUBLIC)
PHP_ME(git_commit, setMessage, arginfo_git_commit_set_message, ZEND_ACC_PUBLIC)
PHP_ME(git_commit, setTree, arginfo_git_commit_set_tree, ZEND_ACC_PUBLIC)
PHP_ME(git_commit, write, NULL, ZEND_ACC_PUBLIC)
PHP_ME(git_commit, getTree, NULL, ZEND_ACC_PUBLIC)
PHP_ME(git_commit, getAuthor, NULL, ZEND_ACC_PUBLIC)
PHP_ME(git_commit, getCommitter, NULL, ZEND_ACC_PUBLIC)
PHP_ME(git_commit, getMessage, NULL, ZEND_ACC_PUBLIC)
PHP_ME(git_commit, getShortMessage, NULL, ZEND_ACC_PUBLIC)
PHP_ME(git_commit, getParent, arginfo_git_commit_get_parent, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
void git_init_commit(TSRMLS_D)
{
zend_class_entry ce;
INIT_NS_CLASS_ENTRY(ce, PHP_GIT_NS,"Commit", php_git_commit_methods);
git_commit_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
git_commit_class_entry->create_object = php_git_commit_new;
zend_declare_property_null(git_commit_class_entry, "author", sizeof("author")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
zend_declare_property_null(git_commit_class_entry, "committer",sizeof("committer")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
zend_declare_property_null(git_commit_class_entry, "parents", sizeof("parents")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
zend_declare_property_null(git_commit_class_entry, "message", sizeof("message")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
zend_declare_property_null(git_commit_class_entry, "tree", sizeof("tree")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
}