Skip to content

Commit 516fe0a

Browse files
committed
[status] implement git_status
1 parent b79c301 commit 516fe0a

File tree

6 files changed

+196
-8
lines changed

6 files changed

+196
-8
lines changed

example/status.php

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
$repo = git_repository_open(".");
3+
$list = git_status_list_new($repo, array(
4+
));
5+
6+
$payload = array();
7+
printf("# Changes to be committed:\n");
8+
printf("# (use \"git reset HEAD <file>...\" to unstage)\n");
9+
printf("#\n");
10+
11+
$cnt = git_status_list_entrycount($list);
12+
for ($i = 0; $i < $cnt; $i++) {
13+
$entry = git_status_byindex($list, $i);
14+
$flags = $entry['status'];
15+
$stat = getStat($flags);
16+
17+
if (is_array($entry['head_to_index'])) {
18+
printf("# %15s %s\n", $stat, $entry['head_to_index']['new_file']['path']);
19+
}
20+
}
21+
22+
printf("#\n");
23+
printf("# Changes not staged for commit:\n");
24+
printf("# (use \"git add <file>...\" to update what will be committed)\n");
25+
printf("# (use \"git checkout -- <file>...\" to discard changes in working directory)\n");
26+
printf("#\n");
27+
28+
for ($i = 0; $i < $cnt; $i++) {
29+
$entry = git_status_byindex($list, $i);
30+
$flags = $entry['status'];
31+
$stat = getStat($flags);
32+
33+
if (is_array($entry['index_to_workdir'])) {
34+
printf("# %15s %s\n", $stat, $entry['index_to_workdir']['new_file']['path']);
35+
}
36+
}
37+
printf("#\n");
38+
39+
40+
function getStat($flags)
41+
{
42+
$stat = "";
43+
if ($flags & GIT_STATUS_IGNORED) {
44+
return;
45+
}
46+
if ($flags == GIT_STATUS_CURRENT) {
47+
return;
48+
}
49+
if ($flags & GIT_STATUS_INDEX_NEW){
50+
$stat = "new file:";
51+
}
52+
if ($flags & GIT_STATUS_WT_NEW) {
53+
$stat = "untracked:";
54+
}
55+
if ($flags & GIT_STATUS_INDEX_MODIFIED ||$flags & GIT_STATUS_WT_MODIFIED) {
56+
$stat = "modified:";
57+
}
58+
if ($flags & GIT_STATUS_INDEX_DELETED || $flags & GIT_STATUS_WT_DELETED) {
59+
$stat = "deleted:";
60+
}
61+
if ($flags & GIT_STATUS_INDEX_RENAMED || $flags & GIT_STATUS_WT_RENAMED) {
62+
$stat = "renamed:";
63+
}
64+
if ($flags & GIT_STATUS_INDEX_TYPECHANGE || $flags & GIT_STATUS_WT_TYPECHANGE) {
65+
$stat = "typechange:";
66+
}
67+
return $stat;
68+
}

helper.c

+13
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,19 @@ zval* php_git2_read_arrval(zval *array, char *name, size_t name_len TSRMLS_DC)
4343
return result;
4444
}
4545

46+
long php_git2_read_arrval_long2(zval *array, char *name, size_t name_len, long value TSRMLS_DC)
47+
{
48+
zval *tmp;
49+
long result = value;
50+
51+
tmp = php_git2_read_arrval(array, name, name_len TSRMLS_CC);
52+
if (tmp) {
53+
result = Z_LVAL_P(tmp);
54+
}
55+
56+
return result;
57+
}
58+
4659
long php_git2_read_arrval_long(zval *array, char *name, size_t name_len TSRMLS_DC)
4760
{
4861
zval *tmp;

helper.h

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ int php_git2_check_error(int error_code, const char *action TSRMLS_DC);
3232

3333
zval* php_git2_read_arrval(zval *array, char *name, size_t name_len TSRMLS_DC);
3434

35+
long php_git2_read_arrval_long2(zval *array, char *name, size_t name_len, long value TSRMLS_DC);
36+
3537
long php_git2_read_arrval_long(zval *array, char *name, size_t name_len TSRMLS_DC);
3638

3739
const char* php_git2_read_arrval_string(zval *array, char *name, size_t name_len TSRMLS_DC);

php_git2.c

+1
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,7 @@ static zend_function_entry php_git2_functions[] = {
664664
PHP_FE(git_status_byindex, arginfo_git_status_byindex)
665665
PHP_FE(git_status_list_free, arginfo_git_status_list_free)
666666
PHP_FE(git_status_should_ignore, arginfo_git_status_should_ignore)
667+
PHP_FE(git_status_options_new, NULL)
667668

668669
/* transport */
669670
PHP_FE(git_transport_new, arginfo_git_transport_new)

status.c

+110-8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,86 @@
22
#include "php_git2_priv.h"
33
#include "status.h"
44

5+
static void php_git2_git_status_options_to_array(git_status_options *options, zval **out TSRMLS_DC)
6+
{
7+
zval *result, *pathspec;
8+
9+
MAKE_STD_ZVAL(result);
10+
array_init(result);
11+
12+
add_assoc_long_ex(result, ZEND_STRS("version"), options->version);
13+
add_assoc_long_ex(result, ZEND_STRS("show"), options->show);
14+
add_assoc_long_ex(result, ZEND_STRS("flags"), options->flags);
15+
php_git2_strarray_to_array(&options->pathspec, &pathspec TSRMLS_CC);
16+
add_assoc_zval_ex(result, ZEND_STRS("pathspec"), pathspec);
17+
18+
*out = result;
19+
}
20+
21+
static void php_git2_array_to_git_status_options(git_status_options *options, zval *array TSRMLS_DC)
22+
{
23+
zval *tmp;
24+
options->version = php_git2_read_arrval_long2(array, ZEND_STRS("version"), 1 TSRMLS_CC);
25+
options->show = php_git2_read_arrval_long2(array, ZEND_STRS("version"), 0 TSRMLS_CC);
26+
options->flags = php_git2_read_arrval_long2(array, ZEND_STRS("version"), 0 TSRMLS_CC);
27+
28+
php_git2_array_to_strarray(&options->pathspec, php_git2_read_arrval(array, ZEND_STRS("pathspec") TSRMLS_CC) TSRMLS_CC);
29+
}
30+
31+
static void php_git2_git_status_entry_to_array(git_status_entry *entry, zval **out TSRMLS_DC)
32+
{
33+
zval *result, *head_to_index, *index_to_workdir;
34+
35+
MAKE_STD_ZVAL(result);
36+
array_init(result);
37+
38+
if (entry->head_to_index) {
39+
php_git2_diff_delta_to_array(entry->head_to_index, &head_to_index TSRMLS_CC);
40+
} else {
41+
MAKE_STD_ZVAL(head_to_index);
42+
ZVAL_NULL(head_to_index);
43+
}
44+
45+
if (entry->index_to_workdir) {
46+
php_git2_diff_delta_to_array(entry->index_to_workdir, &index_to_workdir TSRMLS_CC);
47+
} else {
48+
MAKE_STD_ZVAL(index_to_workdir);
49+
ZVAL_NULL(index_to_workdir);
50+
}
51+
52+
add_assoc_long_ex(result, ZEND_STRS("status"), entry->status);
53+
add_assoc_zval_ex(result, ZEND_STRS("head_to_index"), head_to_index);
54+
add_assoc_zval_ex(result, ZEND_STRS("index_to_workdir"), index_to_workdir);
55+
56+
*out = result;
57+
}
58+
59+
static int php_git2_git_status_cb(
60+
const char *path, unsigned int status_flags, void *payload)
61+
{
62+
php_git2_t *result;
63+
zval *param_path, *param_status_flags, *retval_ptr = NULL;
64+
php_git2_cb_t *p = (php_git2_cb_t*)payload;
65+
int i = 0;
66+
long retval = 0;
67+
GIT2_TSRMLS_SET(p->tsrm_ls)
68+
69+
Z_ADDREF_P(p->payload);
70+
MAKE_STD_ZVAL(param_path);
71+
MAKE_STD_ZVAL(param_status_flags);
72+
ZVAL_STRING(param_path, path, 1);
73+
ZVAL_LONG(param_status_flags, status_flags);
74+
75+
if (php_git2_call_function_v(p->fci, p->fcc TSRMLS_CC, &retval_ptr, 3,
76+
&param_path, &param_status_flags, &p->payload)) {
77+
return GIT_EUSER;
78+
}
79+
80+
retval = Z_LVAL_P(retval_ptr);
81+
zval_ptr_dtor(&retval_ptr);
82+
return retval;
83+
}
84+
585
/* {{{ proto long git_status_foreach(resource $repo, Callable $callback, $payload)
686
*/
787
PHP_FUNCTION(git_status_foreach)
@@ -12,7 +92,7 @@ PHP_FUNCTION(git_status_foreach)
1292
zend_fcall_info fci = empty_fcall_info;
1393
zend_fcall_info_cache fcc = empty_fcall_info_cache;
1494
php_git2_cb_t *cb = NULL;
15-
95+
1696
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
1797
"rfz", &repo, &fci, &fcc, &payload) == FAILURE) {
1898
return;
@@ -22,7 +102,7 @@ PHP_FUNCTION(git_status_foreach)
22102
if (php_git2_cb_init(&cb, &fci, &fcc, payload TSRMLS_CC)) {
23103
RETURN_FALSE;
24104
}
25-
//result = git_status_foreach(PHP_GIT2_V(_repo, repository), <CHANGEME>, cb);
105+
result = git_status_foreach(PHP_GIT2_V(_repo, repository), php_git2_git_status_cb, cb);
26106
php_git2_cb_free(cb);
27107
RETURN_LONG(result);
28108
}
@@ -38,18 +118,23 @@ PHP_FUNCTION(git_status_foreach_ext)
38118
zend_fcall_info fci = empty_fcall_info;
39119
zend_fcall_info_cache fcc = empty_fcall_info_cache;
40120
php_git2_cb_t *cb = NULL;
121+
git_status_options options = GIT_STATUS_OPTIONS_INIT;
41122

42123
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
43-
"r<git_status_options>fz", &repo, &opts, &fci, &fcc, &payload) == FAILURE) {
124+
"rafz", &repo, &opts, &fci, &fcc, &payload) == FAILURE) {
44125
return;
45126
}
46127

47128
ZEND_FETCH_RESOURCE(_repo, php_git2_t*, &repo, -1, PHP_GIT2_RESOURCE_NAME, git2_resource_handle);
129+
php_git2_array_to_git_status_options(&options, opts TSRMLS_CC);
48130
if (php_git2_cb_init(&cb, &fci, &fcc, payload TSRMLS_CC)) {
49131
RETURN_FALSE;
50132
}
51-
//result = git_status_foreach_ext(PHP_GIT2_V(_repo, repository), opts, <CHANGEME>, cb);
133+
result = git_status_foreach_ext(PHP_GIT2_V(_repo, repository), &options, php_git2_git_status_cb, cb);
52134
php_git2_cb_free(cb);
135+
if (options.pathspec.count > 0) {
136+
php_git2_strarray_free(&options.pathspec);
137+
}
53138
RETURN_LONG(result);
54139
}
55140
/* }}} */
@@ -82,15 +167,20 @@ PHP_FUNCTION(git_status_list_new)
82167
php_git2_t *result = NULL, *_repo = NULL;
83168
git_status_list *out = NULL;
84169
zval *repo = NULL, *opts = NULL;
170+
git_status_options options = GIT_STATUS_OPTIONS_INIT;
85171
int error = 0;
86172

87173
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
88-
"r<git_status_options>", &repo, &opts) == FAILURE) {
174+
"ra", &repo, &opts) == FAILURE) {
89175
return;
90176
}
91177

92178
ZEND_FETCH_RESOURCE(_repo, php_git2_t*, &repo, -1, PHP_GIT2_RESOURCE_NAME, git2_resource_handle);
93-
error = git_status_list_new(&out, PHP_GIT2_V(_repo, repository), opts);
179+
php_git2_array_to_git_status_options(&options, opts TSRMLS_CC);
180+
error = git_status_list_new(&out, PHP_GIT2_V(_repo, repository), &options);
181+
if (options.pathspec.count > 0) {
182+
php_git2_strarray_free(&options.pathspec);
183+
}
94184
if (php_git2_check_error(error, "git_status_list_new" TSRMLS_CC)) {
95185
RETURN_FALSE;
96186
}
@@ -125,7 +215,7 @@ PHP_FUNCTION(git_status_list_entrycount)
125215
PHP_FUNCTION(git_status_byindex)
126216
{
127217
const git_status_entry *result = NULL;
128-
zval *statuslist = NULL;
218+
zval *statuslist = NULL, *out;
129219
php_git2_t *_statuslist = NULL;
130220
long idx = 0;
131221

@@ -136,7 +226,11 @@ PHP_FUNCTION(git_status_byindex)
136226

137227
ZEND_FETCH_RESOURCE(_statuslist, php_git2_t*, &statuslist, -1, PHP_GIT2_RESOURCE_NAME, git2_resource_handle);
138228
result = git_status_byindex(PHP_GIT2_V(_statuslist, status_list), idx);
139-
/* TODO(chobie): implement this */
229+
if (result == NULL) {
230+
RETURN_FALSE;
231+
}
232+
php_git2_git_status_entry_to_array(result, &out TSRMLS_CC);
233+
RETURN_ZVAL(out, 0, 1);
140234
}
141235
/* }}} */
142236

@@ -182,3 +276,11 @@ PHP_FUNCTION(git_status_should_ignore)
182276
}
183277
/* }}} */
184278

279+
PHP_FUNCTION(git_status_options_new)
280+
{
281+
git_status_options options = GIT_STATUS_OPTIONS_INIT;
282+
zval *result;
283+
284+
php_git2_git_status_options_to_array(&options, &result TSRMLS_CC);
285+
RETURN_ZVAL(result, 0, 1);
286+
}

status.h

+2
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,6 @@ PHP_FUNCTION(git_status_list_free);
101101
*/
102102
PHP_FUNCTION(git_status_should_ignore);
103103

104+
PHP_FUNCTION(git_status_options_new);
105+
104106
#endif

0 commit comments

Comments
 (0)