diff options
Diffstat (limited to 'src/diff_stats.c')
-rw-r--r-- | src/diff_stats.c | 365 |
1 files changed, 0 insertions, 365 deletions
diff --git a/src/diff_stats.c b/src/diff_stats.c deleted file mode 100644 index 41a25bf8a..000000000 --- a/src/diff_stats.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (C) the libgit2 contributors. All rights reserved. - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ - -#include "common.h" - -#include "vector.h" -#include "diff.h" -#include "patch_generate.h" - -#define DIFF_RENAME_FILE_SEPARATOR " => " -#define STATS_FULL_MIN_SCALE 7 - -typedef struct { - size_t insertions; - size_t deletions; -} diff_file_stats; - -struct git_diff_stats { - git_diff *diff; - diff_file_stats *filestats; - - size_t files_changed; - size_t insertions; - size_t deletions; - size_t renames; - - size_t max_name; - size_t max_filestat; - int max_digits; -}; - -static int digits_for_value(size_t val) -{ - int count = 1; - size_t placevalue = 10; - - while (val >= placevalue) { - ++count; - placevalue *= 10; - } - - return count; -} - -static int diff_file_stats_full_to_buf( - git_buf *out, - const git_diff_delta *delta, - const diff_file_stats *filestat, - const git_diff_stats *stats, - size_t width) -{ - const char *old_path = NULL, *new_path = NULL, *adddel_path = NULL; - size_t padding; - git_object_size_t old_size, new_size; - - old_path = delta->old_file.path; - new_path = delta->new_file.path; - old_size = delta->old_file.size; - new_size = delta->new_file.size; - - if (old_path && new_path && strcmp(old_path, new_path) != 0) { - size_t common_dirlen; - int error; - - padding = stats->max_name - strlen(old_path) - strlen(new_path); - - if ((common_dirlen = git_path_common_dirlen(old_path, new_path)) && - common_dirlen <= INT_MAX) { - error = git_buf_printf(out, " %.*s{%s"DIFF_RENAME_FILE_SEPARATOR"%s}", - (int) common_dirlen, old_path, - old_path + common_dirlen, - new_path + common_dirlen); - } else { - error = git_buf_printf(out, " %s" DIFF_RENAME_FILE_SEPARATOR "%s", - old_path, new_path); - } - - if (error < 0) - goto on_error; - } else { - adddel_path = new_path ? new_path : old_path; - if (git_buf_printf(out, " %s", adddel_path) < 0) - goto on_error; - - padding = stats->max_name - strlen(adddel_path); - - if (stats->renames > 0) - padding += strlen(DIFF_RENAME_FILE_SEPARATOR); - } - - if (git_buf_putcn(out, ' ', padding) < 0 || - git_buf_puts(out, " | ") < 0) - goto on_error; - - if (delta->flags & GIT_DIFF_FLAG_BINARY) { - if (git_buf_printf(out, - "Bin %" PRId64 " -> %" PRId64 " bytes", old_size, new_size) < 0) - goto on_error; - } - else { - if (git_buf_printf(out, - "%*" PRIuZ, stats->max_digits, - filestat->insertions + filestat->deletions) < 0) - goto on_error; - - if (filestat->insertions || filestat->deletions) { - if (git_buf_putc(out, ' ') < 0) - goto on_error; - - if (!width) { - if (git_buf_putcn(out, '+', filestat->insertions) < 0 || - git_buf_putcn(out, '-', filestat->deletions) < 0) - goto on_error; - } else { - size_t total = filestat->insertions + filestat->deletions; - size_t full = (total * width + stats->max_filestat / 2) / - stats->max_filestat; - size_t plus = full * filestat->insertions / total; - size_t minus = full - plus; - - if (git_buf_putcn(out, '+', max(plus, 1)) < 0 || - git_buf_putcn(out, '-', max(minus, 1)) < 0) - goto on_error; - } - } - } - - git_buf_putc(out, '\n'); - -on_error: - return (git_buf_oom(out) ? -1 : 0); -} - -static int diff_file_stats_number_to_buf( - git_buf *out, - const git_diff_delta *delta, - const diff_file_stats *filestats) -{ - int error; - const char *path = delta->new_file.path; - - if (delta->flags & GIT_DIFF_FLAG_BINARY) - error = git_buf_printf(out, "%-8c" "%-8c" "%s\n", '-', '-', path); - else - error = git_buf_printf(out, "%-8" PRIuZ "%-8" PRIuZ "%s\n", - filestats->insertions, filestats->deletions, path); - - return error; -} - -static int diff_file_stats_summary_to_buf( - git_buf *out, - const git_diff_delta *delta) -{ - if (delta->old_file.mode != delta->new_file.mode) { - if (delta->old_file.mode == 0) { - git_buf_printf(out, " create mode %06o %s\n", - delta->new_file.mode, delta->new_file.path); - } - else if (delta->new_file.mode == 0) { - git_buf_printf(out, " delete mode %06o %s\n", - delta->old_file.mode, delta->old_file.path); - } - else { - git_buf_printf(out, " mode change %06o => %06o %s\n", - delta->old_file.mode, delta->new_file.mode, delta->new_file.path); - } - } - - return 0; -} - -int git_diff_get_stats( - git_diff_stats **out, - git_diff *diff) -{ - size_t i, deltas; - size_t total_insertions = 0, total_deletions = 0; - git_diff_stats *stats = NULL; - int error = 0; - - GIT_ASSERT_ARG(out); - GIT_ASSERT_ARG(diff); - - stats = git__calloc(1, sizeof(git_diff_stats)); - GIT_ERROR_CHECK_ALLOC(stats); - - deltas = git_diff_num_deltas(diff); - - stats->filestats = git__calloc(deltas, sizeof(diff_file_stats)); - if (!stats->filestats) { - git__free(stats); - return -1; - } - - stats->diff = diff; - GIT_REFCOUNT_INC(diff); - - for (i = 0; i < deltas && !error; ++i) { - git_patch *patch = NULL; - size_t add = 0, remove = 0, namelen; - const git_diff_delta *delta; - - if ((error = git_patch_from_diff(&patch, diff, i)) < 0) - break; - - /* keep a count of renames because it will affect formatting */ - delta = patch->delta; - - /* TODO ugh */ - namelen = strlen(delta->new_file.path); - if (delta->old_file.path && strcmp(delta->old_file.path, delta->new_file.path) != 0) { - namelen += strlen(delta->old_file.path); - stats->renames++; - } - - /* and, of course, count the line stats */ - error = git_patch_line_stats(NULL, &add, &remove, patch); - - git_patch_free(patch); - - stats->filestats[i].insertions = add; - stats->filestats[i].deletions = remove; - - total_insertions += add; - total_deletions += remove; - - if (stats->max_name < namelen) - stats->max_name = namelen; - if (stats->max_filestat < add + remove) - stats->max_filestat = add + remove; - } - - stats->files_changed = deltas; - stats->insertions = total_insertions; - stats->deletions = total_deletions; - stats->max_digits = digits_for_value(stats->max_filestat + 1); - - if (error < 0) { - git_diff_stats_free(stats); - stats = NULL; - } - - *out = stats; - return error; -} - -size_t git_diff_stats_files_changed( - const git_diff_stats *stats) -{ - GIT_ASSERT_ARG(stats); - - return stats->files_changed; -} - -size_t git_diff_stats_insertions( - const git_diff_stats *stats) -{ - GIT_ASSERT_ARG(stats); - - return stats->insertions; -} - -size_t git_diff_stats_deletions( - const git_diff_stats *stats) -{ - GIT_ASSERT_ARG(stats); - - return stats->deletions; -} - -int git_diff_stats_to_buf( - git_buf *out, - const git_diff_stats *stats, - git_diff_stats_format_t format, - size_t width) -{ - int error = 0; - size_t i; - const git_diff_delta *delta; - - GIT_ASSERT_ARG(out); - GIT_ASSERT_ARG(stats); - - if (format & GIT_DIFF_STATS_NUMBER) { - for (i = 0; i < stats->files_changed; ++i) { - if ((delta = git_diff_get_delta(stats->diff, i)) == NULL) - continue; - - error = diff_file_stats_number_to_buf( - out, delta, &stats->filestats[i]); - if (error < 0) - return error; - } - } - - if (format & GIT_DIFF_STATS_FULL) { - if (width > 0) { - if (width > stats->max_name + stats->max_digits + 5) - width -= (stats->max_name + stats->max_digits + 5); - if (width < STATS_FULL_MIN_SCALE) - width = STATS_FULL_MIN_SCALE; - } - if (width > stats->max_filestat) - width = 0; - - for (i = 0; i < stats->files_changed; ++i) { - if ((delta = git_diff_get_delta(stats->diff, i)) == NULL) - continue; - - error = diff_file_stats_full_to_buf( - out, delta, &stats->filestats[i], stats, width); - if (error < 0) - return error; - } - } - - if (format & GIT_DIFF_STATS_FULL || format & GIT_DIFF_STATS_SHORT) { - git_buf_printf( - out, " %" PRIuZ " file%s changed", - stats->files_changed, stats->files_changed != 1 ? "s" : ""); - - if (stats->insertions || stats->deletions == 0) - git_buf_printf( - out, ", %" PRIuZ " insertion%s(+)", - stats->insertions, stats->insertions != 1 ? "s" : ""); - - if (stats->deletions || stats->insertions == 0) - git_buf_printf( - out, ", %" PRIuZ " deletion%s(-)", - stats->deletions, stats->deletions != 1 ? "s" : ""); - - git_buf_putc(out, '\n'); - - if (git_buf_oom(out)) - return -1; - } - - if (format & GIT_DIFF_STATS_INCLUDE_SUMMARY) { - for (i = 0; i < stats->files_changed; ++i) { - if ((delta = git_diff_get_delta(stats->diff, i)) == NULL) - continue; - - error = diff_file_stats_summary_to_buf(out, delta); - if (error < 0) - return error; - } - } - - return error; -} - -void git_diff_stats_free(git_diff_stats *stats) -{ - if (stats == NULL) - return; - - git_diff_free(stats->diff); /* bumped refcount in constructor */ - git__free(stats->filestats); - git__free(stats); -} |