ext/rugged/rugged_patch.c in rugged-0.25.0b6 vs ext/rugged/rugged_patch.c in rugged-0.25.0b7
- old
+ new
@@ -171,10 +171,17 @@
git_patch_line_stats(NULL, &additions, &deletions, patch);
return rb_ary_new3(2, INT2FIX(additions), INT2FIX(deletions));
}
+enum {
+ EXCLUDE_CONTEXT = (1u << 0),
+ EXCLUDE_ADDITIONS = (1u << 1),
+ EXCLUDE_DELETIONS = (1u << 2),
+ EXCLUDE_EOFNL = (1u << 3)
+};
+
/*
* call-seq:
* patch.lines(options = {}) -> int
*
* The following options can be passed in the +options+ Hash:
@@ -189,46 +196,88 @@
*
* :exclude_deletions ::
* Boolean value specifying that deletion line counts should be excluded from
* the returned total.
*
+ * :exclude_eofnl ::
+ * Boolean value specifying that end-of-file newline change lines should
+ * be excluded from the returned total.
+ *
* Returns the total number of lines in the patch, depending on the options
* specified.
*/
static VALUE rb_git_diff_patch_lines(int argc, VALUE *argv, VALUE self)
{
git_patch *patch;
- size_t context_lines, additions, deletions;
- size_t total_out;
+ size_t lines = 0;
VALUE rb_options;
Data_Get_Struct(self, git_patch, patch);
- context_lines = 0;
- additions = 0;
- deletions = 0;
+ int options = 0;
- git_patch_line_stats(&context_lines, &additions, &deletions, patch);
-
- total_out = context_lines + additions + deletions;
-
rb_scan_args(argc, argv, "0:", &rb_options);
if (!NIL_P(rb_options)) {
if (RTEST(rb_hash_aref(rb_options, CSTR2SYM("exclude_context")))) {
- total_out -= context_lines;
+ options |= EXCLUDE_CONTEXT;
}
if (RTEST(rb_hash_aref(rb_options, CSTR2SYM("exclude_additions")))) {
- total_out -= additions;
+ options |= EXCLUDE_ADDITIONS;
}
if (RTEST(rb_hash_aref(rb_options, CSTR2SYM("exclude_deletions")))) {
- total_out -= deletions;
+ options |= EXCLUDE_DELETIONS;
}
+
+ if (RTEST(rb_hash_aref(rb_options, CSTR2SYM("exclude_eofnl")))) {
+ options |= EXCLUDE_EOFNL;
+ }
}
- return INT2FIX(total_out);
+ if (options == 0) {
+ size_t i = 0, hunks_count = git_patch_num_hunks(patch);
+ for (i = 0; i < hunks_count; ++i) {
+ lines += git_patch_num_lines_in_hunk(patch, i);
+ }
+ } else {
+ size_t i = 0, hunks_count = git_patch_num_hunks(patch);
+ for (i = 0; i < hunks_count; ++i) {
+ size_t lines_in_hunk = git_patch_num_lines_in_hunk(patch, i), l = 0;
+
+ for (l = 0; l < lines_in_hunk; ++l) {
+ const git_diff_line *line;
+ rugged_exception_check(
+ git_patch_get_line_in_hunk(&line, patch, i, l)
+ );
+
+ switch (line->origin) {
+ case GIT_DIFF_LINE_CONTEXT:
+ if (options & EXCLUDE_CONTEXT) continue;
+ break;
+
+ case GIT_DIFF_LINE_ADDITION:
+ if (options & EXCLUDE_ADDITIONS) continue;
+ break;
+
+ case GIT_DIFF_LINE_DELETION:
+ if (options & EXCLUDE_DELETIONS) continue;
+ break;
+
+ case GIT_DIFF_LINE_ADD_EOFNL:
+ case GIT_DIFF_LINE_DEL_EOFNL:
+ if (options & EXCLUDE_EOFNL) continue;
+ break;
+ }
+
+ lines += 1;
+ }
+ }
+ }
+
+ return INT2FIX(lines);
}
+
/*
* call-seq:
* patch.bytesize(options = {}) -> int
*
* The following options can be passed in the +options+ Hash:
@@ -254,25 +303,23 @@
size_t bytesize;
VALUE rb_options;
int include_context, include_hunk_headers, include_file_headers;
Data_Get_Struct(self, git_patch, patch);
- include_context = 1;
- include_hunk_headers = 1;
- include_file_headers = 1;
+ include_context = include_hunk_headers = include_file_headers = 1;
rb_scan_args(argc, argv, "0:", &rb_options);
if (!NIL_P(rb_options)) {
- if (rb_hash_aref(rb_options, CSTR2SYM("include_context")) == Qfalse) {
+ if (RTEST(rb_hash_aref(rb_options, CSTR2SYM("exclude_context")))) {
include_context = 0;
}
- if (rb_hash_aref(rb_options, CSTR2SYM("include_hunk_headers")) == Qfalse) {
+ if (RTEST(rb_hash_aref(rb_options, CSTR2SYM("exclude_hunk_headers")))) {
include_hunk_headers = 0;
}
- if (rb_hash_aref(rb_options, CSTR2SYM("include_file_headers")) == Qfalse) {
+ if (RTEST(rb_hash_aref(rb_options, CSTR2SYM("exclude_file_headers")))) {
include_file_headers = 0;
}
}
bytesize = git_patch_size(patch, include_context, include_hunk_headers, include_file_headers);
@@ -284,41 +331,78 @@
const git_diff_delta *delta,
const git_diff_hunk *hunk,
const git_diff_line *line,
void *payload)
{
- VALUE rb_str = (VALUE)payload;
+ VALUE rb_buffer = (VALUE)payload;
switch (line->origin) {
case GIT_DIFF_LINE_CONTEXT:
case GIT_DIFF_LINE_ADDITION:
case GIT_DIFF_LINE_DELETION:
- rb_str_cat(rb_str, &line->origin, 1);
+ rb_ary_push(rb_buffer, rb_str_new(&line->origin, 1));
}
- rb_str_cat(rb_str, line->content, line->content_len);
+ rb_ary_push(rb_buffer, rb_str_new(line->content, line->content_len));
return GIT_OK;
}
+static int patch_print_header_cb(
+ const git_diff_delta *delta,
+ const git_diff_hunk *hunk,
+ const git_diff_line *line,
+ void *payload)
+{
+ VALUE rb_buffer = (VALUE)payload;
+
+ if (line->origin == GIT_DIFF_LINE_FILE_HDR) {
+ rb_ary_push(rb_buffer, rb_str_new(line->content, line->content_len));
+ return GIT_OK;
+ } else {
+ return GIT_ITEROVER;
+ }
+}
+
/*
* call-seq:
* patch.to_s -> str
*
* Returns the contents of the patch as a single diff string.
*/
static VALUE rb_git_diff_patch_to_s(VALUE self)
{
git_patch *patch;
- VALUE rb_str = rb_str_new(NULL, 0);
+ VALUE rb_buffer = rb_ary_new();
Data_Get_Struct(self, git_patch, patch);
- rugged_exception_check(git_patch_print(patch, patch_print_cb, (void*)rb_str));
+ rugged_exception_check(git_patch_print(patch, patch_print_cb, (void*)rb_buffer));
- return rb_str;
+ return rb_ary_join(rb_buffer, Qnil);
}
+/*
+ * call-seq:
+ * patch.header -> str
+ *
+ * Returns only the header of the patch as a string.
+ */
+static VALUE rb_git_diff_patch_header(VALUE self)
+{
+ git_patch *patch;
+ int error = 0;
+ VALUE rb_buffer = rb_ary_new();
+ Data_Get_Struct(self, git_patch, patch);
+
+ error = git_patch_print(patch, patch_print_header_cb, (void*)rb_buffer);
+ if (error && error != GIT_ITEROVER)
+ rugged_exception_check(error);
+
+ return rb_ary_join(rb_buffer, Qnil);
+}
+
+
void Init_rugged_patch(void)
{
rb_cRuggedPatch = rb_define_class_under(rb_mRugged, "Patch", rb_cObject);
rb_define_singleton_method(rb_cRuggedPatch, "from_strings", rb_git_patch_from_strings, -1);
@@ -327,9 +411,10 @@
rb_define_method(rb_cRuggedPatch, "lines", rb_git_diff_patch_lines, -1);
rb_define_method(rb_cRuggedPatch, "bytesize", rb_git_diff_patch_bytesize, -1);
rb_define_method(rb_cRuggedPatch, "delta", rb_git_diff_patch_delta, 0);
+ rb_define_method(rb_cRuggedPatch, "header", rb_git_diff_patch_header, 0);
rb_define_method(rb_cRuggedPatch, "to_s", rb_git_diff_patch_to_s, 0);
rb_define_method(rb_cRuggedPatch, "each_hunk", rb_git_diff_patch_each_hunk, 0);
rb_define_method(rb_cRuggedPatch, "hunk_count", rb_git_diff_patch_hunk_count, 0);
}