Skip to content

Commit 34d4a4a

Browse files
committed
testing callbacks~
1 parent 1c7b702 commit 34d4a4a

4 files changed

Lines changed: 197 additions & 6 deletions

File tree

config.m4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ if test $PHP_GIT2 != "no"; then
2323
PHP_ADD_LIBRARY(http_parser,, GIT2_SHARED_LIBADD)
2424
fi
2525

26-
PHP_NEW_EXTENSION(git2, php_git2.c git2_exception.c git2_repository.c git2_config.c git2_config_entry.c git2_reference.c git2_commit.c git2_remote.c git2_tree.c, $ext_shared)
26+
PHP_NEW_EXTENSION(git2, php_git2.c git2_exception.c git2_repository.c git2_config.c git2_config_entry.c git2_reference.c git2_commit.c git2_remote.c git2_tree.c git2_tree_entry.c, $ext_shared)
2727
fi

git2_tree.c

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "git2_exception.h"
33
#include "git2_repository.h"
44
#include "git2_tree.h"
5+
#include "git2_tree_entry.h"
56

67
static zend_class_entry *php_git2_tree_ce;
78
static zend_object_handlers php_git2_tree_handler;
@@ -79,6 +80,78 @@ static PHP_METHOD(Tree, lookup_oid) {
7980
GIT2_TREE_GET_OID(id)
8081
GIT2_TREE_GET_LONG(entrycount)
8182

83+
struct git2_treewalk_payload {
84+
zval *this;
85+
zval **callback_data;
86+
zend_fcall_info callback_i;
87+
zend_fcall_info_cache callback_ic;
88+
};
89+
90+
static int git2_treewalk_cb(const char *root, const git_tree_entry *entry, void *payload) {
91+
int error;
92+
zval argv[3]; // root, entry, callback_data
93+
zval retval;
94+
struct git2_treewalk_payload *p = payload;
95+
96+
ZVAL_STRING(&argv[0], root);
97+
git2_tree_entry_spawn(&argv[1], entry);
98+
ZVAL_COPY_VALUE(&argv[2], *p->callback_data);
99+
100+
p->callback_i.retval = &retval;
101+
p->callback_i.param_count = 3;
102+
p->callback_i.params = argv;
103+
104+
// TODO HERE
105+
error = zend_call_function(&p->callback_i, &p->callback_ic);
106+
if (error == FAILURE) {
107+
return -1; // causes end of walk
108+
} else if (!Z_ISUNDEF(retval)) {
109+
convert_to_long(&retval);
110+
error = Z_LVAL(retval);
111+
zval_ptr_dtor(&retval);
112+
}
113+
114+
zval_ptr_dtor(&argv[0]);
115+
zval_ptr_dtor(&argv[1]);
116+
zval_ptr_dtor(&argv[2]); // ?
117+
}
118+
119+
ZEND_BEGIN_ARG_INFO_EX(arginfo_tree_walk, 0, 0, 2)
120+
ZEND_ARG_INFO(0, mode)
121+
ZEND_ARG_INFO(0, callback)
122+
ZEND_ARG_INFO(1, callback_data)
123+
ZEND_END_ARG_INFO()
124+
125+
static PHP_METHOD(Tree, walk) {
126+
long mode;
127+
zval **callback_data;
128+
struct git2_treewalk_payload p;
129+
p.this = getThis();
130+
131+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lfZ", &mode, &p.callback_i, &p.callback_ic, &callback_data) != SUCCESS) {
132+
return;
133+
}
134+
135+
GIT2_TREE_FETCH();
136+
137+
switch(mode) {
138+
case GIT_TREEWALK_PRE: case GIT_TREEWALK_POST:
139+
break;
140+
default:
141+
git2_throw_exception(0 TSRMLS_CC, "Invalid mode provided, should be Git2::TREEWALK_PRE or Git2::TREEWALK_POST");
142+
return;
143+
}
144+
145+
int res = git_tree_walk(intern->tree, mode, git2_treewalk_cb, &p);
146+
147+
if (res != 0) {
148+
git2_throw_last_error();
149+
return;
150+
}
151+
152+
RETURN_TRUE;
153+
}
154+
82155
void git2_tree_spawn(zval **return_value, git_tree *tree TSRMLS_DC) {
83156
git2_tree_object_t *intern;
84157

@@ -118,6 +191,7 @@ static zend_function_entry git2_tree_methods[] = {
118191
PHP_ME(Tree, lookup_oid, arginfo_tree_id, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
119192
PHP_ME(Tree, id, arginfo_tree_id, ZEND_ACC_PUBLIC)
120193
PHP_ME(Tree, entrycount, arginfo_tree_entrycount, ZEND_ACC_PUBLIC)
194+
PHP_ME(Tree, walk, arginfo_tree_walk, ZEND_ACC_PUBLIC)
121195
/* PHP_ME(Tree, __construct, arginfo___construct, ZEND_ACC_PUBLIC) */
122196
{ NULL, NULL, NULL }
123197
};
@@ -134,10 +208,9 @@ void git2_tree_init(TSRMLS_DC) {
134208
php_git2_tree_handler.free_obj = php_git2_tree_free_object;
135209

136210
// normalize
137-
#define GIT2_REF_CONST(_x) zend_declare_class_constant_long(php_git2_tree_ce, ZEND_STRL(#_x), GIT_REF_ ## _x TSRMLS_CC)
138-
GIT2_REF_CONST(FORMAT_NORMAL);
139-
GIT2_REF_CONST(FORMAT_ALLOW_ONELEVEL);
140-
GIT2_REF_CONST(FORMAT_REFSPEC_PATTERN);
141-
GIT2_REF_CONST(FORMAT_REFSPEC_SHORTHAND);
211+
#define GIT2_TREE_CONST(_x, _y) zend_declare_class_constant_long(php_git2_tree_ce, ZEND_STRL(#_x), _y TSRMLS_CC)
212+
213+
GIT2_TREE_CONST(WALK_PRE, GIT_TREEWALK_PRE);
214+
GIT2_TREE_CONST(WALK_POST, GIT_TREEWALK_POST);
142215
}
143216

git2_tree_entry.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#include "php_git2.h"
2+
#include "git2_tree_entry.h"
3+
4+
static zend_class_entry *php_git2_tree_entry_ce;
5+
static zend_object_handlers php_git2_tree_entry_handler;
6+
7+
typedef struct _git2_tree_entry_object {
8+
zend_object std;
9+
git_tree_entry *e;
10+
} git2_tree_entry_object_t;
11+
12+
#define GIT2_TREE_ENTRY_FETCH() git2_tree_entry_object_t *intern = (git2_tree_entry_object_t*)Z_OBJ_P(getThis()); \
13+
if (intern->e == NULL) { \
14+
git2_throw_exception(0 TSRMLS_CC, "Git2\\Tree\\Entry object in invalid state"); \
15+
return; \
16+
}
17+
18+
#define GIT2_TREE_ENTRY_GET_STRING(_x) ZEND_BEGIN_ARG_INFO_EX(arginfo_tree_entry_ ## _x, 0, 0, 0) \
19+
ZEND_END_ARG_INFO() \
20+
static PHP_METHOD(Entry, _x) { \
21+
if (zend_parse_parameters_none() == FAILURE) return; \
22+
GIT2_TREE_ENTRY_FETCH(); \
23+
const char *res = git_tree_entry_ ## _x(intern->e); \
24+
if (res == NULL) { RETURN_NULL(); } \
25+
RETURN_STRING(res); \
26+
}
27+
28+
#define GIT2_TREE_ENTRY_GET_OID(_x) ZEND_BEGIN_ARG_INFO_EX(arginfo_tree_entry_ ## _x, 0, 0, 0) \
29+
ZEND_END_ARG_INFO() \
30+
static PHP_METHOD(Entry, _x) { \
31+
if (zend_parse_parameters_none() == FAILURE) return; \
32+
GIT2_TREE_ENTRY_FETCH(); \
33+
const git_oid *res = git_tree_entry_ ## _x(intern->e); \
34+
if (res == NULL) { RETURN_NULL(); } \
35+
RETURN_STRINGL((const char*)(res->id), GIT_OID_RAWSZ); \
36+
}
37+
38+
#define GIT2_TREE_ENTRY_GET_LONG(_x) ZEND_BEGIN_ARG_INFO_EX(arginfo_tree_entry_ ## _x, 0, 0, 0) \
39+
ZEND_END_ARG_INFO() \
40+
static PHP_METHOD(Entry, _x) { \
41+
if (zend_parse_parameters_none() == FAILURE) return; \
42+
GIT2_TREE_ENTRY_FETCH(); \
43+
RETURN_LONG(git_tree_entry_ ## _x(intern->e)); \
44+
}
45+
46+
GIT2_TREE_ENTRY_GET_STRING(name)
47+
GIT2_TREE_ENTRY_GET_OID(id)
48+
GIT2_TREE_ENTRY_GET_LONG(type)
49+
GIT2_TREE_ENTRY_GET_LONG(filemode)
50+
GIT2_TREE_ENTRY_GET_LONG(filemode_raw)
51+
52+
53+
void git2_tree_entry_spawn(zval *return_value, git_tree_entry *e TSRMLS_DC) {
54+
git2_tree_entry_object_t *intern;
55+
56+
object_init_ex(return_value, php_git2_tree_entry_ce);
57+
intern = (git2_tree_entry_object_t*)Z_OBJ_P(return_value);
58+
intern->e = e;
59+
}
60+
61+
zend_object *php_git2_tree_entry_create_object(zend_class_entry *class_type TSRMLS_DC) {
62+
git2_tree_entry_object_t *intern = NULL;
63+
64+
intern = emalloc(sizeof(git2_tree_entry_object_t));
65+
memset(intern, 0, sizeof(git2_tree_entry_object_t));
66+
67+
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
68+
object_properties_init(&intern->std, class_type);
69+
70+
intern->std.handlers = &php_git2_tree_entry_handler;
71+
72+
return &intern->std;
73+
}
74+
75+
static void php_git2_tree_entry_free_object(zend_object *object TSRMLS_DC) {
76+
git2_tree_entry_object_t *intern = (git2_tree_entry_object_t*)object;
77+
78+
zend_object_std_dtor(&intern->std TSRMLS_CC);
79+
80+
if (intern->e) {
81+
git_tree_entry_free(intern->e);
82+
intern->e = NULL;
83+
}
84+
85+
// no need with PHP7 to free intern
86+
}
87+
88+
#define PHP_GIT2_TREE_ENTRY_ME(_x) PHP_ME(Entry, _x, arginfo_tree_entry_##_x, ZEND_ACC_PUBLIC)
89+
static zend_function_entry git2_tree_entry_methods[] = {
90+
PHP_GIT2_TREE_ENTRY_ME(name)
91+
PHP_GIT2_TREE_ENTRY_ME(id)
92+
PHP_GIT2_TREE_ENTRY_ME(type)
93+
PHP_GIT2_TREE_ENTRY_ME(filemode)
94+
PHP_GIT2_TREE_ENTRY_ME(filemode_raw)
95+
/* PHP_ME(Entry, __construct, arginfo___construct, ZEND_ACC_PUBLIC) */
96+
{ NULL, NULL, NULL }
97+
};
98+
99+
void git2_tree_entry_init(TSRMLS_DC) {
100+
zend_class_entry ce;
101+
102+
INIT_NS_CLASS_ENTRY(ce, "Git2\\Tree", "Entry", git2_tree_entry_methods);
103+
php_git2_tree_entry_ce = zend_register_internal_class(&ce TSRMLS_CC);
104+
php_git2_tree_entry_ce->create_object = php_git2_tree_entry_create_object;
105+
106+
memcpy(&php_git2_tree_entry_handler, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
107+
php_git2_tree_entry_handler.clone_obj = NULL;
108+
php_git2_tree_entry_handler.free_obj = php_git2_tree_entry_free_object;
109+
}
110+

git2_tree_entry.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#ifndef GIT2_TREE_ENTRY_H
2+
#define GIT2_TREE_ENTRY_H
3+
4+
void git2_tree_entry_init(TSRMLS_DC);
5+
6+
void git2_tree_entry_spawn(zval *return_value, git_tree_entry *e TSRMLS_DC);
7+
8+
#endif /* GIT2_TREE_ENTRY_H */

0 commit comments

Comments
 (0)