diff options
author | Russell Belfer <rb@github.com> | 2014-04-22 23:33:27 +0400 |
---|---|---|
committer | Russell Belfer <rb@github.com> | 2014-04-22 23:33:27 +0400 |
commit | 8d09efa24ee01e9e4b14672978bfd1bb1ca2436a (patch) | |
tree | d68210d412062a84d73a60ddb01a7a2501af0b29 /examples | |
parent | 12e422a0562de2aebb05f5f414dbcde7caf85886 (diff) |
Use git_diff_get_stats in example/diff + refactor
This takes the `--stat` and related example options in the example
diff.c program and converts them to use the `git_diff_get_stats`
API which nicely formats stats for you.
I went to add bar-graph scaling to the stats formatter and noticed
that the `git_diff_stats` structure was holding on to all of the
`git_patch` objects. Unfortunately, each of these objects keeps
the full text of the diff in memory, so this is very expensive. I
ended up modifying `git_diff_stats` to keep just the data that it
needs to keep and allowed it to release the patches. Then, I added
width scaling to the output on top of that.
In making the diff example program match 'git diff' output, I ended
up removing an newline from the sumamry output which I then had to
compensate for in the email formatting to match the expectations.
Lastly, I went through and refactored the tests to use a couple of
helper functions and reduce the overall amount of code there.
Diffstat (limited to 'examples')
-rw-r--r-- | examples/diff.c | 103 |
1 files changed, 37 insertions, 66 deletions
diff --git a/examples/diff.c b/examples/diff.c index 1dbf85f61..76ac2f311 100644 --- a/examples/diff.c +++ b/examples/diff.c @@ -34,10 +34,11 @@ static const char *colors[] = { }; enum { - OUTPUT_DIFF = 0, - OUTPUT_STAT = 1, - OUTPUT_SHORTSTAT = 2, - OUTPUT_NUMSTAT = 3 + OUTPUT_DIFF = (1 << 0), + OUTPUT_STAT = (1 << 1), + OUTPUT_SHORTSTAT = (1 << 2), + OUTPUT_NUMSTAT = (1 << 3), + OUTPUT_SUMMARY = (1 << 4) }; enum { @@ -137,14 +138,13 @@ int main(int argc, char *argv[]) /** Generate simple output using libgit2 display helper. */ - switch (o.output) { - case OUTPUT_STAT: - case OUTPUT_NUMSTAT: - case OUTPUT_SHORTSTAT: + if (!o.output) + o.output = OUTPUT_DIFF; + + if (o.output != OUTPUT_DIFF) diff_print_stats(diff, &o); - break; - case OUTPUT_DIFF: + if ((o.output & OUTPUT_DIFF) != 0) { if (o.color >= 0) fputs(colors[0], stdout); @@ -154,10 +154,6 @@ int main(int argc, char *argv[]) if (o.color >= 0) fputs(colors[0], stdout); - break; - - default: - usage("Unknown output format", "programmer error"); } /** Cleanup before exiting. */ @@ -233,8 +229,10 @@ static void parse_opts(struct opts *o, int argc, char *argv[]) usage("Only one or two tree identifiers can be provided", NULL); } else if (!strcmp(a, "-p") || !strcmp(a, "-u") || - !strcmp(a, "--patch")) + !strcmp(a, "--patch")) { + o->output |= OUTPUT_DIFF; o->format = GIT_DIFF_FORMAT_PATCH; + } else if (!strcmp(a, "--cached")) o->cache = CACHE_ONLY; else if (!strcmp(a, "--nocache")) @@ -273,11 +271,13 @@ static void parse_opts(struct opts *o, int argc, char *argv[]) else if (!strcmp(a, "--minimal")) o->diffopts.flags |= GIT_DIFF_MINIMAL; else if (!strcmp(a, "--stat")) - o->output = OUTPUT_STAT; + o->output |= OUTPUT_STAT; else if (!strcmp(a, "--numstat")) - o->output = OUTPUT_NUMSTAT; + o->output |= OUTPUT_NUMSTAT; else if (!strcmp(a, "--shortstat")) - o->output = OUTPUT_SHORTSTAT; + o->output |= OUTPUT_SHORTSTAT; + else if (!strcmp(a, "--summary")) + o->output |= OUTPUT_SUMMARY; else if (match_uint16_arg( &o->findopts.rename_threshold, &args, "-M") || match_uint16_arg( @@ -308,59 +308,30 @@ static void parse_opts(struct opts *o, int argc, char *argv[]) } } -/** Display diff output with "--numstat" or "--shortstat" */ +/** Display diff output with "--stat", "--numstat", or "--shortstat" */ static void diff_print_stats(git_diff *diff, struct opts *o) { - git_patch *patch; - size_t d, ndeltas = git_diff_num_deltas(diff); - size_t nadditions, ndeletions; - long nadditions_sum, ndeletions_sum; - - nadditions_sum = 0; - ndeletions_sum = 0; + git_diff_stats *stats; + git_buf b = GIT_BUF_INIT_CONST(NULL, 0); + git_diff_stats_format_t format = 0; - for (d = 0; d < ndeltas; d++){ - check_lg2( - git_patch_from_diff(&patch, diff, d), - "generating patch from diff", NULL); + check_lg2( + git_diff_get_stats(&stats, diff), "generating stats for diff", NULL); - check_lg2( - git_patch_line_stats(NULL, &nadditions, &ndeletions, patch), - "generating the number of additions and deletions", NULL); + if (o->output & OUTPUT_STAT) + format |= GIT_DIFF_STATS_FULL; + if (o->output & OUTPUT_SHORTSTAT) + format |= GIT_DIFF_STATS_SHORT; + if (o->output & OUTPUT_NUMSTAT) + format |= GIT_DIFF_STATS_NUMBER; + if (o->output & OUTPUT_SUMMARY) + format |= GIT_DIFF_STATS_INCLUDE_SUMMARY; - if (o->output == OUTPUT_NUMSTAT) { - const git_diff_delta *delta = git_patch_get_delta(patch); - printf("%ld\t%ld\t%s\n", - (long)nadditions, (long)ndeletions, delta->new_file.path); - } - else if (o->output == OUTPUT_STAT) { - const git_diff_delta *delta = git_patch_get_delta(patch); - printf(" %s\t| %ld\t(%ld+ %ld-)\n", - delta->new_file.path, (long)nadditions + (long)ndeletions, - (long)nadditions, (long)ndeletions); - } + check_lg2( + git_diff_stats_to_buf(&b, stats, format, 80), "formatting stats", NULL); - nadditions_sum += nadditions; - ndeletions_sum += ndeletions; + fputs(b.ptr, stdout); - git_patch_free(patch); - } - - if (o->output != OUTPUT_NUMSTAT && ndeltas > 0) { - printf(" %ld %s", (long)ndeltas, - 1 == ndeltas ? "file changed" : "files changed"); - - if (nadditions_sum) { - printf(", %ld ",nadditions_sum); - printf("%s", 1 == nadditions_sum ? "insertion(+)" : "insertions(+)"); - } - - if (ndeletions_sum) { - printf(", %ld ",ndeletions_sum); - printf("%s", 1 == ndeletions_sum ? "deletion(-)" : "deletions(-)"); - } - - printf("\n"); - } + git_buf_free(&b); + git_diff_stats_free(stats); } - |