Skip to content

Commit d93e25e

Browse files
committed
[blame] implement functions
1 parent b474be8 commit d93e25e

File tree

7 files changed

+181
-12
lines changed

7 files changed

+181
-12
lines changed

blame.c

+127-7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,105 @@
22
#include "php_git2_priv.h"
33
#include "blame.h"
44

5+
static void php_git2_array_to_git_blame_options(git_blame_options *options, zval *array TSRMLS_DC)
6+
{
7+
zval *tmp;
8+
9+
options->version = php_git2_read_arrval_long(array, ZEND_STRS("version") TSRMLS_CC);
10+
options->flags = php_git2_read_arrval_long(array, ZEND_STRS("flags") TSRMLS_CC);
11+
options->min_match_characters = php_git2_read_arrval_long(array, ZEND_STRS("min_match_characters") TSRMLS_CC);
12+
tmp = php_git2_read_arrval(array, ZEND_STRS("newest_commit") TSRMLS_CC);
13+
if (Z_TYPE_P(tmp) != NULL) {
14+
if (Z_TYPE_P(tmp) != IS_STRING) {
15+
convert_to_string(tmp);
16+
}
17+
if (git_oid_fromstrn(&options->newest_commit, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp)) != GIT_OK) {
18+
return;
19+
}
20+
}
21+
22+
tmp = php_git2_read_arrval(array, ZEND_STRS("oldest_commit") TSRMLS_CC);
23+
if (Z_TYPE_P(tmp) != NULL) {
24+
if (Z_TYPE_P(tmp) != IS_STRING) {
25+
convert_to_string(tmp);
26+
}
27+
if (git_oid_fromstrn(&options->newest_commit, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp)) != GIT_OK) {
28+
return;
29+
}
30+
}
31+
32+
options->min_line = php_git2_read_arrval_long(array, ZEND_STRS("min_line") TSRMLS_CC);
33+
options->max_line = php_git2_read_arrval_long(array, ZEND_STRS("max_line") TSRMLS_CC);
34+
35+
}
36+
37+
static void php_git2_git_blame_options_to_array(git_blame_options *options, zval **out TSRMLS_DC)
38+
{
39+
zval *result = NULL;
40+
char buf[41] = {0};
41+
42+
MAKE_STD_ZVAL(result);
43+
array_init(result);
44+
45+
add_assoc_long_ex(result, ZEND_STRS("version"), options->version);
46+
add_assoc_long_ex(result, ZEND_STRS("flags"), options->flags);
47+
add_assoc_long_ex(result, ZEND_STRS("min_match_characters"), options->min_match_characters);
48+
49+
if (git_oid_iszero(&options->newest_commit) != 1) {
50+
git_oid_fmt(buf, &options->newest_commit);
51+
add_assoc_string_ex(result, ZEND_STRS("newest_commit"), out, 1);
52+
} else {
53+
add_assoc_null_ex(result, ZEND_STRS("newest_commit"));
54+
}
55+
56+
if (git_oid_iszero(&options->oldest_commit) != 1) {
57+
git_oid_fmt(buf, &options->oldest_commit);
58+
add_assoc_string_ex(result, ZEND_STRS("oldest_commit"), out, 1);
59+
} else {
60+
add_assoc_null_ex(result, ZEND_STRS("oldest_commit"));
61+
}
62+
63+
add_assoc_long_ex(result, ZEND_STRS("min_line"), options->min_line);
64+
add_assoc_long_ex(result, ZEND_STRS("max_line"), options->max_line);
65+
*out = result;
66+
}
67+
68+
static void php_git2_git_blame_hunk_to_array(git_blame_hunk *hunk, zval **out TSRMLS_DC)
69+
{
70+
zval *result = NULL, *final = NULL, *orig = NULL;
71+
char buf[41] = {0};
72+
73+
MAKE_STD_ZVAL(result);
74+
array_init(result);
75+
76+
add_assoc_long_ex(result, ZEND_STRS("lines_in_hunk"), hunk->lines_in_hunk);
77+
78+
git_oid_fmt(buf, &hunk->final_commit_id);
79+
add_assoc_string_ex(result, ZEND_STRS("final_commit_id"), buf, 1);
80+
81+
php_git2_signature_to_array(hunk->final_signature, &final TSRMLS_CC);
82+
add_assoc_zval_ex(result, ZEND_STRS("final_signature"), final);
83+
84+
add_assoc_long_ex(result, ZEND_STRS("final_start_line_number"), hunk->final_start_line_number);
85+
86+
git_oid_fmt(buf, &hunk->orig_commit_id);
87+
add_assoc_string_ex(result, ZEND_STRS("orig_commit_id"), buf, 1);
88+
add_assoc_string_ex(result, ZEND_STRS("orig_path"), hunk->orig_path, 1);
89+
90+
add_assoc_long_ex(result, ZEND_STRS("orig_start_line_number"), hunk->orig_start_line_number);
91+
if (hunk->orig_signature) {
92+
php_git2_signature_to_array(hunk->orig_signature, &orig TSRMLS_CC);
93+
} else {
94+
MAKE_STD_ZVAL(orig);
95+
ZVAL_NULL(orig);
96+
}
97+
add_assoc_zval_ex(result, ZEND_STRS("orig_signature"), orig);
98+
99+
add_assoc_stringl_ex(result, ZEND_STRS("boundary"), &hunk->boundary, 1, 1);
100+
101+
*out = result;
102+
}
103+
5104
/* {{{ proto long git_blame_get_hunk_count(resource $blame)
6105
*/
7106
PHP_FUNCTION(git_blame_get_hunk_count)
@@ -26,7 +125,7 @@ PHP_FUNCTION(git_blame_get_hunk_count)
26125
PHP_FUNCTION(git_blame_get_hunk_byindex)
27126
{
28127
const git_blame_hunk *result = NULL;
29-
zval *blame = NULL;
128+
zval *blame = NULL, *array = NULL;
30129
php_git2_t *_blame = NULL;
31130
long index = 0;
32131

@@ -37,7 +136,11 @@ PHP_FUNCTION(git_blame_get_hunk_byindex)
37136

38137
ZEND_FETCH_RESOURCE(_blame, php_git2_t*, &blame, -1, PHP_GIT2_RESOURCE_NAME, git2_resource_handle);
39138
result = git_blame_get_hunk_byindex(PHP_GIT2_V(_blame, blame), index);
40-
/* TODO(chobie): implement this */
139+
if (result == NULL) {
140+
RETURN_FALSE;
141+
}
142+
php_git2_git_blame_hunk_to_array(result, &array TSRMLS_CC);
143+
RETURN_ZVAL(array, 0, 1);
41144
}
42145
/* }}} */
43146

@@ -46,7 +149,7 @@ PHP_FUNCTION(git_blame_get_hunk_byindex)
46149
PHP_FUNCTION(git_blame_get_hunk_byline)
47150
{
48151
const git_blame_hunk *result = NULL;
49-
zval *blame = NULL;
152+
zval *blame = NULL, *array = NULL;
50153
php_git2_t *_blame = NULL;
51154
long lineno = 0;
52155

@@ -57,7 +160,11 @@ PHP_FUNCTION(git_blame_get_hunk_byline)
57160

58161
ZEND_FETCH_RESOURCE(_blame, php_git2_t*, &blame, -1, PHP_GIT2_RESOURCE_NAME, git2_resource_handle);
59162
result = git_blame_get_hunk_byline(PHP_GIT2_V(_blame, blame), lineno);
60-
/* TODO(chobie): implement this */
163+
if (result == NULL) {
164+
RETURN_FALSE;
165+
}
166+
php_git2_git_blame_hunk_to_array(result, &array TSRMLS_CC);
167+
RETURN_ZVAL(array, 0, 1);
61168
}
62169
/* }}} */
63170

@@ -68,16 +175,18 @@ PHP_FUNCTION(git_blame_file)
68175
php_git2_t *result = NULL, *_repo = NULL;
69176
git_blame *out = NULL;
70177
zval *repo = NULL, *options = NULL;
178+
git_blame_options opts = GIT_BLAME_OPTIONS_INIT;
71179
char *path = NULL;
72180
int path_len = 0, error = 0;
73181

74182
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
75-
"rs<git_blame_options>", &repo, &path, &path_len, &options) == FAILURE) {
183+
"rsa", &repo, &path, &path_len, &options) == FAILURE) {
76184
return;
77185
}
78-
186+
79187
ZEND_FETCH_RESOURCE(_repo, php_git2_t*, &repo, -1, PHP_GIT2_RESOURCE_NAME, git2_resource_handle);
80-
error = git_blame_file(&out, PHP_GIT2_V(_repo, repository), path, options);
188+
php_git2_array_to_git_blame_options(&opts, options TSRMLS_CC);
189+
error = git_blame_file(&out, PHP_GIT2_V(_repo, repository), path, &opts);
81190
if (php_git2_check_error(error, "git_blame_file" TSRMLS_CC)) {
82191
RETURN_FALSE;
83192
}
@@ -136,3 +245,14 @@ PHP_FUNCTION(git_blame_free)
136245
}
137246
/* }}} */
138247

248+
/* {{{ proto void git_blame_options_new()
249+
*/
250+
PHP_FUNCTION(git_blame_options_new)
251+
{
252+
zval *result;
253+
git_blame_options options = GIT_BLAME_OPTIONS_INIT;
254+
255+
php_git2_git_blame_options_to_array(&options, &result TSRMLS_CC);
256+
RETURN_ZVAL(result, 0, 1);
257+
}
258+
/* }}} */

blame.h

+7
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_git_blame_free, 0, 0, 1)
5656
ZEND_ARG_INFO(0, blame)
5757
ZEND_END_ARG_INFO()
5858

59+
ZEND_BEGIN_ARG_INFO_EX(arginfo_git_blame_options_new, 0, 0, 0)
60+
ZEND_END_ARG_INFO()
61+
5962
/* {{{ proto resource git_blame_get_hunk_count(blame)
6063
*/
6164
PHP_FUNCTION(git_blame_get_hunk_count);
@@ -80,4 +83,8 @@ PHP_FUNCTION(git_blame_buffer);
8083
*/
8184
PHP_FUNCTION(git_blame_free);
8285

86+
/* {{{ proto void git_blame_options_new()
87+
*/
88+
PHP_FUNCTION(git_blame_options_new);
89+
8390
#endif

blob.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ PHP_FUNCTION(git_blob_lookup)
232232
RETURN_FALSE;
233233
}
234234
result = git_blob_lookup(&blob, PHP_GIT2_V(_repo, repository), &__id);
235-
if (php_git2_make_resource(&_result, PHP_GIT2_TYPE_BLOB, result, 0 TSRMLS_CC)) {
235+
if (php_git2_make_resource(&_result, PHP_GIT2_TYPE_BLOB, blob, 0 TSRMLS_CC)) {
236236
RETURN_FALSE;
237237
}
238238
ZVAL_RESOURCE(return_value, GIT2_RVAL_P(_result));

diff.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ static void php_git2_array_to_git_diff_options(git_diff_options *options, zval *
1414
php_git2_array_to_strarray(&options->pathspec, php_git2_read_arrval(array, ZEND_STRS("pathspec") TSRMLS_CC) TSRMLS_CC);
1515
// TODO(chobie): support notify cb
1616

17-
17+
1818
options->context_lines = php_git2_read_arrval_long(array, ZEND_STRS("context_lines") TSRMLS_CC);
1919
options->interhunk_lines = php_git2_read_arrval_long(array, ZEND_STRS("interhunk_lines") TSRMLS_CC);
2020
options->oid_abbrev = php_git2_read_arrval_long(array, ZEND_STRS("oid_abbrev") TSRMLS_CC);
@@ -343,7 +343,6 @@ PHP_FUNCTION(git_diff_find_similar)
343343
int error = 0;
344344
git_diff_options _options = {0};
345345

346-
/* TODO(chobie): generate converter */
347346
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
348347
"ra", &diff, &options) == FAILURE) {
349348
return;

example/blame.php

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
$repo = git_repository_open(".");
3+
$options = git_blame_options_new();
4+
$blame = git_blame_file($repo, "README.md", $options);
5+
$obj = git_revparse_single($repo, "HEAD:README.md");
6+
$id = git_object_id($obj);
7+
$blob = git_blob_lookup($repo, $id);
8+
$raw = git_blob_rawcontent($blob);
9+
10+
$i = 0;
11+
$lines = explode("\n", $raw);
12+
foreach ($lines as $data) {
13+
$hunk = git_blame_get_hunk_byline($blame, $i+1);
14+
if (!$hunk) {
15+
continue;
16+
}
17+
18+
$sig = sprintf("%s <%s>", $hunk['final_signature']['name'], $hunk['final_signature']['email']);
19+
printf("%s ( %-30s, %4d) %s\n", substr($hunk['final_commit_id'], 10),
20+
$sig,
21+
$i+1,
22+
$data
23+
);
24+
$i++;
25+
}

helper.c

+10-2
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,16 @@ void php_git2_signature_to_array(const git_signature *signature, zval **out TSRM
116116
/* TODO(chobie): how do i set offset? */
117117
php_date_initialize(zend_object_store_get_object(datetime TSRMLS_CC), time_str, strlen(time_str), NULL, timezone, 0 TSRMLS_CC);
118118

119-
add_assoc_string_ex(result, ZEND_STRS("name"), signature->name, 1);
120-
add_assoc_string_ex(result, ZEND_STRS("email"), signature->email, 1);
119+
if (signature->name == NULL) {
120+
add_assoc_null_ex(result, ZEND_STRS("name"));
121+
} else {
122+
add_assoc_string_ex(result, ZEND_STRS("name"), signature->name, 1);
123+
}
124+
if (signature->email == NULL) {
125+
add_assoc_null_ex(result, ZEND_STRS("email"));
126+
} else {
127+
add_assoc_string_ex(result, ZEND_STRS("email"), signature->email, 1);
128+
}
121129
add_assoc_zval_ex(result, ZEND_STRS("time"), datetime);
122130

123131
zval_ptr_dtor(&timezone);

php_git2.c

+10
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
#include "push.h"
6767
#include "refspec.h"
6868
#include "graph.h"
69+
#include "blame.h"
6970

7071
int git2_resource_handle;
7172

@@ -944,6 +945,15 @@ static zend_function_entry php_git2_functions[] = {
944945
/* graph */
945946
PHP_FE(git_graph_ahead_behind, arginfo_git_graph_ahead_behind)
946947

948+
/* blame */
949+
PHP_FE(git_blame_get_hunk_count, arginfo_git_blame_get_hunk_count)
950+
PHP_FE(git_blame_get_hunk_byindex, arginfo_git_blame_get_hunk_byindex)
951+
PHP_FE(git_blame_get_hunk_byline, arginfo_git_blame_get_hunk_byline)
952+
PHP_FE(git_blame_file, arginfo_git_blame_file)
953+
PHP_FE(git_blame_buffer, arginfo_git_blame_buffer)
954+
PHP_FE(git_blame_free, arginfo_git_blame_free)
955+
PHP_FE(git_blame_options_new, arginfo_git_blame_options_new)
956+
947957
/* misc */
948958
PHP_FE(git_resource_type, arginfo_git_resource_type)
949959
PHP_FE(git_libgit2_capabilities, NULL)

0 commit comments

Comments
 (0)