Skip to content

Commit 05e05c3

Browse files
committed
[checkout] WIP: callback
1 parent f527c2d commit 05e05c3

File tree

4 files changed

+276
-9
lines changed

4 files changed

+276
-9
lines changed

Diff for: checkout.c

+31-9
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,28 @@ PHP_FUNCTION(git_checkout_head)
1010
zval *repo = NULL;
1111
php_git2_t *_repo = NULL;
1212
zval *opts = NULL;
13-
int error = 0;
13+
int error = 0, shoud_free = 0;
14+
git_checkout_opts *options;
1415

15-
/* TODO(chobie): generate converter */
1616
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
17-
"ra", &repo, &opts) == FAILURE) {
17+
"r|a", &repo, &opts) == FAILURE) {
1818
return;
1919
}
2020

21+
if (opts != NULL) {
22+
if (php_git2_array_to_git_checkout_opts(&options, opts TSRMLS_CC)) {
23+
RETURN_FALSE;
24+
}
25+
shoud_free = 1;
26+
} else {
27+
//memset(&options, '\0', sizeof(git_checkout_opts));
28+
}
29+
2130
ZEND_FETCH_RESOURCE(_repo, php_git2_t*, &repo, -1, PHP_GIT2_RESOURCE_NAME, git2_resource_handle);
22-
result = git_checkout_head(PHP_GIT2_V(_repo, repository), opts);
31+
result = git_checkout_head(PHP_GIT2_V(_repo, repository), options);
32+
if (shoud_free) {
33+
php_git_git_checkout_opts_free(options TSRMLS_CC);
34+
}
2335
RETURN_LONG(result);
2436
}
2537
/* }}} */
@@ -50,7 +62,6 @@ PHP_FUNCTION(git_checkout_index)
5062
}
5163
/* }}} */
5264

53-
5465
/* {{{ proto long git_checkout_tree(resource $repo, resource $treeish, $opts)
5566
*/
5667
PHP_FUNCTION(git_checkout_tree)
@@ -62,16 +73,27 @@ PHP_FUNCTION(git_checkout_tree)
6273
php_git2_t *_treeish = NULL;
6374
zval *opts = NULL;
6475
int error = 0;
76+
git_checkout_opts options = GIT_CHECKOUT_OPTS_INIT;
77+
git_object *__treeish = NULL;
6578

66-
/* TODO(chobie): generate converter */
6779
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
68-
"rra", &repo, &treeish, &opts) == FAILURE) {
80+
"r|ra", &repo, &treeish, &opts) == FAILURE) {
6981
return;
7082
}
7183

84+
if (opts != NULL && php_git2_array_to_git_checkout_opts(&options, opts TSRMLS_CC)) {
85+
RETURN_FALSE;
86+
} else {
87+
memset(&options, '\0', sizeof(git_checkout_opts));
88+
}
89+
90+
if (treeish != NULL) {
91+
ZEND_FETCH_RESOURCE(_treeish, php_git2_t*, &treeish, -1, PHP_GIT2_RESOURCE_NAME, git2_resource_handle);
92+
treeish = PHP_GIT2_V(_treeish, object);
93+
}
94+
7295
ZEND_FETCH_RESOURCE(_repo, php_git2_t*, &repo, -1, PHP_GIT2_RESOURCE_NAME, git2_resource_handle);
73-
ZEND_FETCH_RESOURCE(_treeish, php_git2_t*, &treeish, -1, PHP_GIT2_RESOURCE_NAME, git2_resource_handle);
74-
result = git_checkout_tree(PHP_GIT2_V(_repo, repository), PHP_GIT2_V(_treeish, object), opts);
96+
result = git_checkout_tree(PHP_GIT2_V(_repo, repository), __treeish, &options);
7597
RETURN_LONG(result);
7698
}
7799
/* }}} */

Diff for: helper.c

+228
Original file line numberDiff line numberDiff line change
@@ -235,3 +235,231 @@ void php_git2_strarray_free(git_strarray *out)
235235
}
236236
efree(out->strings);
237237
}
238+
239+
void php_git2_git_checkout_opts_to_array(git_checkout_opts *opts, zval **out TSRMLS_DC)
240+
{
241+
zval *result;
242+
git_checkout_opts tmp = GIT_CHECKOUT_OPTS_INIT;
243+
opts = &tmp;
244+
245+
MAKE_STD_ZVAL(result);
246+
array_init(result);
247+
248+
add_assoc_long_ex(result, ZEND_STRS("version"), opts->version);
249+
add_assoc_long_ex(result, ZEND_STRS("checkout_strategy"), opts->checkout_strategy);
250+
add_assoc_long_ex(result, ZEND_STRS("disable_filters"), opts->disable_filters);
251+
add_assoc_long_ex(result, ZEND_STRS("dir_mode"), opts->dir_mode);
252+
add_assoc_long_ex(result, ZEND_STRS("file_mode"), opts->file_mode);
253+
add_assoc_long_ex(result, ZEND_STRS("file_open_flags"), opts->file_open_flags);
254+
add_assoc_long_ex(result, ZEND_STRS("notify_flags"), opts->notify_flags);
255+
256+
if (opts->notify_payload != NULL) {
257+
258+
} else {
259+
add_assoc_null_ex(result, ZEND_STRS("notify_cb"));
260+
}
261+
262+
if (opts->notify_payload != NULL) {
263+
264+
} else {
265+
add_assoc_null_ex(result, ZEND_STRS("notify_payload"));
266+
}
267+
268+
if (opts->progress_cb != NULL) {
269+
270+
} else {
271+
add_assoc_null_ex(result, ZEND_STRS("progress_cb"));
272+
}
273+
274+
if (opts->progress_payload != NULL) {
275+
276+
} else {
277+
add_assoc_null_ex(result, ZEND_STRS("progress_payload"));
278+
}
279+
280+
if (opts->paths.count > 0) {
281+
zval *paths;
282+
php_git2_strarray_to_array(&opts->paths, &paths TSRMLS_CC);
283+
add_assoc_zval_ex(result, ZEND_STRS("paths"), paths);
284+
} else {
285+
zval *paths;
286+
MAKE_STD_ZVAL(paths);
287+
array_init(paths);
288+
add_assoc_zval_ex(result, ZEND_STRS("paths"), paths);
289+
}
290+
291+
if (opts->baseline != NULL) {
292+
// git_tree
293+
294+
} else {
295+
add_assoc_null_ex(result, ZEND_STRS("baseline"));
296+
}
297+
add_assoc_string_ex(result, ZEND_STRS("target_directory"), (opts->target_directory) ? opts->target_directory : "", 1);
298+
add_assoc_string_ex(result, ZEND_STRS("our_label"), (opts->our_label) ? opts->our_label : "", 1);
299+
add_assoc_string_ex(result, ZEND_STRS("their_label"), (opts->their_label) ? opts->their_label : "", 1);
300+
301+
*out = result;
302+
}
303+
304+
void php_git_git_checkout_opts_free(git_checkout_opts *target TSRMLS_DC)
305+
{
306+
php_git2_cb_t *tmp;
307+
308+
if (target->notify_payload) {
309+
tmp = (php_git2_cb_t*)target->notify_payload;
310+
if (tmp->fci) {
311+
efree(tmp->fci);
312+
}
313+
if (tmp->fcc) {
314+
efree(tmp->fcc);
315+
}
316+
efree(target->notify_payload);
317+
}
318+
if (target->progress_payload) {
319+
tmp = (php_git2_cb_t*)target->progress_payload;
320+
if (tmp->fci) {
321+
efree(tmp->fci);
322+
}
323+
if (tmp->fcc) {
324+
efree(tmp->fcc);
325+
}
326+
efree(target->progress_payload);
327+
}
328+
329+
php_git2_strarray_free(&target->paths);
330+
efree(target);
331+
}
332+
333+
334+
static int php_git2_git_checkout_notify_cb(git_checkout_notify_t why,
335+
const char *path,
336+
const git_diff_file *baseline,
337+
const git_diff_file *target,
338+
const git_diff_file *workdir,
339+
void *payload)
340+
{
341+
/* TODO(chobie): implement callback */
342+
}
343+
344+
void php_git2_git_checkout_progress_cb(const char *path,
345+
size_t completed_steps,
346+
size_t total_steps,
347+
void *payload)
348+
{
349+
php_git2_t *result;
350+
zval *param_path, *param_completed_steps, *param_total_steps, *retval_ptr = NULL;
351+
php_git2_cb_t *p = (php_git2_cb_t*)payload;
352+
GIT2_TSRMLS_SET(p->tsrm_ls);
353+
354+
MAKE_STD_ZVAL(param_path);
355+
MAKE_STD_ZVAL(param_completed_steps);
356+
MAKE_STD_ZVAL(param_total_steps);
357+
ZVAL_NULL(param_path);
358+
if (path != NULL) {
359+
ZVAL_STRING(param_path, path, 1);
360+
}
361+
ZVAL_LONG(param_completed_steps, completed_steps);
362+
ZVAL_LONG(param_total_steps, total_steps);
363+
364+
if (php_git2_call_function_v(p->fci, p->fcc TSRMLS_CC, &retval_ptr, 4, &param_path, &param_completed_steps, &param_total_steps, &p->payload)) {
365+
return;
366+
}
367+
368+
zval_ptr_dtor(&retval_ptr);
369+
}
370+
371+
372+
static void php_git2_fcall_info_wrapper(zval *target, zend_fcall_info **out_fci, zend_fcall_info_cache **out_fcc TSRMLS_DC)
373+
{
374+
char *is_callable_error = NULL;
375+
zend_fcall_info *fci = NULL;
376+
zend_fcall_info_cache *fcc = NULL;
377+
378+
fci = (zend_fcall_info*)emalloc(sizeof(zend_fcall_info));
379+
fcc = (zend_fcall_info_cache*)emalloc(sizeof(zend_fcall_info_cache));
380+
memcpy(fci, &empty_fcall_info, sizeof(zend_fcall_info));
381+
memcpy(fcc, &empty_fcall_info_cache, sizeof(zend_fcall_info_cache));
382+
383+
if (zend_fcall_info_init(target, 0, fci, fcc, NULL, &is_callable_error TSRMLS_CC) == SUCCESS) {
384+
if (is_callable_error) {
385+
efree(is_callable_error);
386+
}
387+
} else {
388+
fprintf(stderr, "FAILED");
389+
efree(fci);
390+
efree(fcc);
391+
return;
392+
}
393+
394+
*out_fci = fci;
395+
*out_fcc = fcc;
396+
}
397+
398+
int php_git2_array_to_git_checkout_opts(git_checkout_opts **out, zval *array TSRMLS_DC)
399+
{
400+
const char *target_directory, *our_label, *their_label;
401+
git_checkout_opts *opts = NULL, def = GIT_CHECKOUT_OPTS_INIT;
402+
php_git2_cb_t *notify_payload = NULL, *progress_payload= NULL;
403+
zval *notify_cb = NULL, *progress_cb = NULL;
404+
char *tmp;
405+
406+
opts = (git_checkout_opts*)emalloc(sizeof(struct git_checkout_opts));
407+
memcpy(opts, &def, sizeof(git_checkout_opts));
408+
409+
notify_cb = php_git2_read_arrval(array, ZEND_STRS("notify_cb") TSRMLS_CC);
410+
progress_cb = php_git2_read_arrval(array, ZEND_STRS("progress_cb") TSRMLS_CC);
411+
412+
413+
opts->notify_cb = php_git2_git_checkout_notify_cb;
414+
opts->progress_cb = php_git2_git_checkout_progress_cb;
415+
opts->version = php_git2_read_arrval_long(array, ZEND_STRS("version") TSRMLS_CC);
416+
opts->checkout_strategy = php_git2_read_arrval_long(array, ZEND_STRS("checkout_strategy") TSRMLS_CC);
417+
opts->disable_filters = php_git2_read_arrval_long(array, ZEND_STRS("disable_filters") TSRMLS_CC);
418+
opts->dir_mode = php_git2_read_arrval_long(array, ZEND_STRS("dir_mode") TSRMLS_CC);
419+
opts->file_mode = php_git2_read_arrval_long(array, ZEND_STRS("file_mode") TSRMLS_CC);
420+
opts->file_open_flags = php_git2_read_arrval_long(array, ZEND_STRS("file_open_flags") TSRMLS_CC);
421+
opts->notify_flags = php_git2_read_arrval_long(array, ZEND_STRS("notify_flags") TSRMLS_CC);
422+
423+
//notify_cb
424+
if (Z_TYPE_P(notify_cb) != IS_NULL) {
425+
zend_fcall_info *fci;
426+
zend_fcall_info_cache *fcc;
427+
428+
php_git2_fcall_info_wrapper(notify_cb, &fci, &fcc TSRMLS_CC);
429+
if (php_git2_cb_init(&notify_payload, fci, fcc,
430+
php_git2_read_arrval(array, ZEND_STRS("notify_payload") TSRMLS_CC) TSRMLS_CC)) {
431+
}
432+
opts->notify_payload = notify_payload;
433+
} else {
434+
opts->notify_cb = NULL;
435+
}
436+
437+
//progress_cb
438+
if (Z_TYPE_P(progress_cb) != IS_NULL) {
439+
zend_fcall_info *fci;
440+
zend_fcall_info_cache *fcc;
441+
442+
php_git2_fcall_info_wrapper(progress_cb, &fci, &fcc TSRMLS_CC);
443+
if (php_git2_cb_init(&progress_payload, fci, fcc,
444+
php_git2_read_arrval(array, ZEND_STRS("progress_payload") TSRMLS_CC) TSRMLS_CC)) {
445+
}
446+
opts->progress_payload = progress_payload;
447+
} else {
448+
opts->progress_cb = NULL;
449+
}
450+
451+
452+
php_git2_array_to_strarray(&opts->paths, php_git2_read_arrval(array, ZEND_STRS("paths") TSRMLS_CC) TSRMLS_CC);
453+
454+
// TODO: assign baseline(git_tree)
455+
456+
target_directory = php_git2_read_arrval_string(array, ZEND_STRS("target_directory") TSRMLS_CC);
457+
our_label = php_git2_read_arrval_string(array, ZEND_STRS("our_label") TSRMLS_CC);
458+
their_label = php_git2_read_arrval_string(array, ZEND_STRS("their_label") TSRMLS_CC);
459+
opts->target_directory = target_directory;
460+
opts->our_label = our_label;
461+
opts->their_label = their_label;
462+
463+
*out = opts;
464+
return 0;
465+
}

Diff for: helper.h

+6
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,10 @@ void php_git2_array_to_strarray(git_strarray *out, zval *array TSRMLS_DC);
5353

5454
void php_git2_strarray_free(git_strarray *out);
5555

56+
void php_git2_git_checkout_opts_to_array(git_checkout_opts *opts, zval **out TSRMLS_DC);
57+
58+
void php_git_git_checkout_opts_free(git_checkout_opts *target TSRMLS_DC);
59+
60+
int php_git2_array_to_git_checkout_opts(git_checkout_opts **out, zval *array TSRMLS_DC);
61+
5662
#endif

Diff for: php_git2.c

+11
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,15 @@ PHP_FUNCTION(git_resource_type)
270270
}
271271
/* }}} */
272272

273+
PHP_FUNCTION(git_checkout_opts_new)
274+
{
275+
zval *tmp;
276+
git_checkout_opts opt = GIT_CHECKOUT_OPTS_INIT;
277+
278+
php_git2_git_checkout_opts_to_array(&opt, &tmp TSRMLS_CC);
279+
RETURN_ZVAL(tmp, 0, 1);
280+
}
281+
273282
static zend_function_entry php_git2_functions[] = {
274283
/* repository */
275284
PHP_FE(git_repository_new, arginfo_git_repository_new)
@@ -626,6 +635,8 @@ static zend_function_entry php_git2_functions[] = {
626635
PHP_FE(git_checkout_index, arginfo_git_checkout_index)
627636
PHP_FE(git_checkout_tree, arginfo_git_checkout_tree)
628637

638+
PHP_FE(git_checkout_opts_new, NULL) /* convention function */
639+
629640
/* filter */
630641
PHP_FE(git_filter_list_load, arginfo_git_filter_list_load)
631642
PHP_FE(git_filter_list_apply_to_data, arginfo_git_filter_list_apply_to_data)

0 commit comments

Comments
 (0)