mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-07 08:20:14 +00:00
Merge pull request #2261 from jacquesg/format-patch
Support for format-patch
This commit is contained in:
commit
c5cacc4ec2
@ -1072,6 +1072,179 @@ GIT_EXTERN(int) git_diff_buffers(
|
||||
git_diff_line_cb line_cb,
|
||||
void *payload);
|
||||
|
||||
/**
|
||||
* This is an opaque structure which is allocated by `git_diff_get_stats`.
|
||||
* You are responsible for releasing the object memory when done, using the
|
||||
* `git_diff_stats_free()` function.
|
||||
*/
|
||||
typedef struct git_diff_stats git_diff_stats;
|
||||
|
||||
/**
|
||||
* Formatting options for diff stats
|
||||
*/
|
||||
typedef enum {
|
||||
/** No stats*/
|
||||
GIT_DIFF_STATS_NONE = 0,
|
||||
|
||||
/** Full statistics, equivalent of `--stat` */
|
||||
GIT_DIFF_STATS_FULL = (1u << 0),
|
||||
|
||||
/** Short statistics, equivalent of `--shortstat` */
|
||||
GIT_DIFF_STATS_SHORT = (1u << 1),
|
||||
|
||||
/** Number statistics, equivalent of `--numstat` */
|
||||
GIT_DIFF_STATS_NUMBER = (1u << 2),
|
||||
|
||||
/** Extended header information such as creations, renames and mode changes, equivalent of `--summary` */
|
||||
GIT_DIFF_STATS_INCLUDE_SUMMARY = (1u << 3),
|
||||
} git_diff_stats_format_t;
|
||||
|
||||
/**
|
||||
* Accumlate diff statistics for all patches.
|
||||
*
|
||||
* @param out Structure containg the diff statistics.
|
||||
* @param diff A git_diff generated by one of the above functions.
|
||||
* @return 0 on success; non-zero on error
|
||||
*/
|
||||
GIT_EXTERN(int) git_diff_get_stats(
|
||||
git_diff_stats **out,
|
||||
git_diff *diff);
|
||||
|
||||
/**
|
||||
* Get the total number of files changed in a diff
|
||||
*
|
||||
* @param stats A `git_diff_stats` generated by one of the above functions.
|
||||
* @return total number of files changed in the diff
|
||||
*/
|
||||
GIT_EXTERN(size_t) git_diff_stats_files_changed(
|
||||
const git_diff_stats *stats);
|
||||
|
||||
/**
|
||||
* Get the total number of insertions in a diff
|
||||
*
|
||||
* @param stats A `git_diff_stats` generated by one of the above functions.
|
||||
* @return total number of insertions in the diff
|
||||
*/
|
||||
GIT_EXTERN(size_t) git_diff_stats_insertions(
|
||||
const git_diff_stats *stats);
|
||||
|
||||
/**
|
||||
* Get the total number of deletions in a diff
|
||||
*
|
||||
* @param stats A `git_diff_stats` generated by one of the above functions.
|
||||
* @return total number of deletions in the diff
|
||||
*/
|
||||
GIT_EXTERN(size_t) git_diff_stats_deletions(
|
||||
const git_diff_stats *stats);
|
||||
|
||||
/**
|
||||
* Print diff statistics to a `git_buf`.
|
||||
*
|
||||
* @param out buffer to store the formatted diff statistics in.
|
||||
* @param stats A `git_diff_stats` generated by one of the above functions.
|
||||
* @param format Formatting option.
|
||||
* @return 0 on success; non-zero on error
|
||||
*/
|
||||
GIT_EXTERN(int) git_diff_stats_to_buf(
|
||||
git_buf *out,
|
||||
const git_diff_stats *stats,
|
||||
git_diff_stats_format_t format);
|
||||
|
||||
/**
|
||||
* Deallocate a `git_diff_stats`.
|
||||
*
|
||||
* @param stats The previously created statistics object;
|
||||
* cannot be used after free.
|
||||
*/
|
||||
GIT_EXTERN(void) git_diff_stats_free(git_diff_stats *stats);
|
||||
|
||||
/**
|
||||
* Formatting options for diff e-mail generation
|
||||
*/
|
||||
typedef enum {
|
||||
/** Normal patch, the default */
|
||||
GIT_DIFF_FORMAT_EMAIL_NONE = 0,
|
||||
|
||||
/** Don't insert "[PATCH]" in the subject header*/
|
||||
GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER = (1 << 0),
|
||||
|
||||
} git_diff_format_email_flags_t;
|
||||
|
||||
/**
|
||||
* Options for controlling the formatting of the generated e-mail.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int version;
|
||||
|
||||
git_diff_format_email_flags_t flags;
|
||||
|
||||
/** This patch number */
|
||||
size_t patch_no;
|
||||
|
||||
/** Total number of patches in this series */
|
||||
size_t total_patches;
|
||||
|
||||
/** id to use for the commit */
|
||||
const git_oid *id;
|
||||
|
||||
/** Summary of the change */
|
||||
const char *summary;
|
||||
|
||||
/** Author of the change */
|
||||
const git_signature *author;
|
||||
} git_diff_format_email_options;
|
||||
|
||||
#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION 1
|
||||
#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT {GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION, 0, 1, 1, NULL, NULL, NULL}
|
||||
|
||||
/**
|
||||
* Create an e-mail ready patch from a diff.
|
||||
*
|
||||
* @param out buffer to store the e-mail patch in
|
||||
* @param diff containing the commit
|
||||
* @param opts structure with options to influence content and formatting.
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_diff_format_email(
|
||||
git_buf *out,
|
||||
git_diff *diff,
|
||||
const git_diff_format_email_options *opts);
|
||||
|
||||
/**
|
||||
* Create an e-mail ready patch for a commit.
|
||||
*
|
||||
* Does not support creating patches for merge commits (yet).
|
||||
*
|
||||
* @param out buffer to store the e-mail patch in
|
||||
* @param repo containing the commit
|
||||
* @param commit pointer to up commit
|
||||
* @param patch_no patch number of the commit
|
||||
* @param total_patches total number of patches in the patch set
|
||||
* @param flags determines the formatting of the e-mail
|
||||
* @param diff_opts structure with options to influence diff or NULL for defaults.
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_diff_commit_as_email(
|
||||
git_buf *out,
|
||||
git_repository *repo,
|
||||
git_commit *commit,
|
||||
size_t patch_no,
|
||||
size_t total_patches,
|
||||
git_diff_format_email_flags_t flags,
|
||||
const git_diff_options *diff_opts);
|
||||
|
||||
/**
|
||||
* Initializes a `git_diff_format_email_options` with default values. Equivalent to
|
||||
* creating an instance with GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT.
|
||||
*
|
||||
* @param opts the `git_diff_format_email_options` instance to initialize.
|
||||
* @param version the version of the struct; you should pass
|
||||
* `GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION` here.
|
||||
* @return Zero on success; -1 on failure.
|
||||
*/
|
||||
GIT_EXTERN(int) git_diff_format_email_init_options(
|
||||
git_diff_format_email_options *opts,
|
||||
int version);
|
||||
|
||||
GIT_END_DECL
|
||||
|
||||
|
@ -141,12 +141,12 @@ GIT_EXTERN(void) git_patch_free(git_patch *patch);
|
||||
/**
|
||||
* Get the delta associated with a patch
|
||||
*/
|
||||
GIT_EXTERN(const git_diff_delta *) git_patch_get_delta(git_patch *patch);
|
||||
GIT_EXTERN(const git_diff_delta *) git_patch_get_delta(const git_patch *patch);
|
||||
|
||||
/**
|
||||
* Get the number of hunks in a patch
|
||||
*/
|
||||
GIT_EXTERN(size_t) git_patch_num_hunks(git_patch *patch);
|
||||
GIT_EXTERN(size_t) git_patch_num_hunks(const git_patch *patch);
|
||||
|
||||
/**
|
||||
* Get line counts of each type in a patch.
|
||||
@ -197,7 +197,7 @@ GIT_EXTERN(int) git_patch_get_hunk(
|
||||
* @return Number of lines in hunk or -1 if invalid hunk index
|
||||
*/
|
||||
GIT_EXTERN(int) git_patch_num_lines_in_hunk(
|
||||
git_patch *patch,
|
||||
const git_patch *patch,
|
||||
size_t hunk_idx);
|
||||
|
||||
/**
|
||||
|
@ -148,6 +148,15 @@ int git_buf_putc(git_buf *buf, char c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_buf_putcn(git_buf *buf, char c, size_t len)
|
||||
{
|
||||
ENSURE_SIZE(buf, buf->size + len + 1);
|
||||
memset(buf->ptr + buf->size, c, len);
|
||||
buf->size += len;
|
||||
buf->ptr[buf->size] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_buf_put(git_buf *buf, const char *data, size_t len)
|
||||
{
|
||||
ENSURE_SIZE(buf, buf->size + len + 1);
|
||||
|
@ -88,6 +88,7 @@ GIT_INLINE(bool) git_buf_oom(const git_buf *buf)
|
||||
*/
|
||||
int git_buf_sets(git_buf *buf, const char *string);
|
||||
int git_buf_putc(git_buf *buf, char c);
|
||||
int git_buf_putcn(git_buf *buf, char c, size_t len);
|
||||
int git_buf_put(git_buf *buf, const char *data, size_t len);
|
||||
int git_buf_puts(git_buf *buf, const char *string);
|
||||
int git_buf_printf(git_buf *buf, const char *format, ...) GIT_FORMAT_PRINTF(2, 3);
|
||||
|
28
src/date.c
28
src/date.c
@ -874,3 +874,31 @@ int git__date_parse(git_time_t *out, const char *date)
|
||||
*out = approxidate_str(date, time_sec, &error_ret);
|
||||
return error_ret;
|
||||
}
|
||||
|
||||
int git__date_rfc2822_fmt(char *out, size_t len, const git_time *date)
|
||||
{
|
||||
int written;
|
||||
struct tm gmt;
|
||||
time_t t;
|
||||
|
||||
assert(out && date);
|
||||
|
||||
t = (time_t) (date->time + date->offset * 60);
|
||||
|
||||
if (p_gmtime_r (&t, &gmt) == NULL)
|
||||
return -1;
|
||||
|
||||
written = p_snprintf(out, len, "%.3s, %u %.3s %.4u %02u:%02u:%02u %+03d%02d",
|
||||
weekday_names[gmt.tm_wday],
|
||||
gmt.tm_mday,
|
||||
month_names[gmt.tm_mon],
|
||||
gmt.tm_year + 1900,
|
||||
gmt.tm_hour, gmt.tm_min, gmt.tm_sec,
|
||||
date->offset / 60, date->offset % 60);
|
||||
|
||||
if (written < 0 || (written > (int) len - 1))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
222
src/diff.c
222
src/diff.c
@ -1427,6 +1427,216 @@ int git_diff__paired_foreach(
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_diff__commit(
|
||||
git_diff **diff,
|
||||
git_repository *repo,
|
||||
const git_commit *commit,
|
||||
const git_diff_options *opts)
|
||||
{
|
||||
git_commit *parent = NULL;
|
||||
git_diff *commit_diff = NULL;
|
||||
git_tree *old_tree = NULL, *new_tree = NULL;
|
||||
size_t parents;
|
||||
int error = 0;
|
||||
|
||||
if ((parents = git_commit_parentcount(commit)) > 1) {
|
||||
char commit_oidstr[GIT_OID_HEXSZ + 1];
|
||||
|
||||
error = -1;
|
||||
giterr_set(GITERR_INVALID, "Commit %s is a merge commit",
|
||||
git_oid_tostr(commit_oidstr, GIT_OID_HEXSZ + 1, git_commit_id(commit)));
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
if (parents > 0)
|
||||
if ((error = git_commit_parent(&parent, commit, 0)) < 0 ||
|
||||
(error = git_commit_tree(&old_tree, parent)) < 0)
|
||||
goto on_error;
|
||||
|
||||
if ((error = git_commit_tree(&new_tree, commit)) < 0 ||
|
||||
(error = git_diff_tree_to_tree(&commit_diff, repo, old_tree, new_tree, opts)) < 0)
|
||||
goto on_error;
|
||||
|
||||
*diff = commit_diff;
|
||||
|
||||
on_error:
|
||||
git_tree_free(new_tree);
|
||||
git_tree_free(old_tree);
|
||||
git_commit_free(parent);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_diff_format_email__append_header_tobuf(
|
||||
git_buf *out,
|
||||
const git_oid *id,
|
||||
const git_signature *author,
|
||||
const char *summary,
|
||||
size_t patch_no,
|
||||
size_t total_patches,
|
||||
bool exclude_patchno_marker)
|
||||
{
|
||||
char idstr[GIT_OID_HEXSZ + 1];
|
||||
char date_str[GIT_DATE_RFC2822_SZ];
|
||||
int error = 0;
|
||||
|
||||
git_oid_fmt(idstr, id);
|
||||
idstr[GIT_OID_HEXSZ] = '\0';
|
||||
|
||||
if ((error = git__date_rfc2822_fmt(date_str, sizeof(date_str), &author->when)) < 0)
|
||||
return error;
|
||||
|
||||
error = git_buf_printf(out,
|
||||
"From %s Mon Sep 17 00:00:00 2001\n" \
|
||||
"From: %s <%s>\n" \
|
||||
"Date: %s\n" \
|
||||
"Subject: ",
|
||||
idstr,
|
||||
author->name, author->email,
|
||||
date_str);
|
||||
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
if (!exclude_patchno_marker) {
|
||||
if (total_patches == 1) {
|
||||
error = git_buf_puts(out, "[PATCH] ");
|
||||
} else {
|
||||
error = git_buf_printf(out, "[PATCH %"PRIuZ"/%"PRIuZ"] ", patch_no, total_patches);
|
||||
}
|
||||
|
||||
if (error < 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
error = git_buf_printf(out, "%s\n\n", summary);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_diff_format_email__append_patches_tobuf(
|
||||
git_buf *out,
|
||||
git_diff *diff)
|
||||
{
|
||||
size_t i, deltas;
|
||||
int error = 0;
|
||||
|
||||
deltas = git_diff_num_deltas(diff);
|
||||
|
||||
for (i = 0; i < deltas; ++i) {
|
||||
git_patch *patch = NULL;
|
||||
|
||||
if ((error = git_patch_from_diff(&patch, diff, i)) >= 0)
|
||||
error = git_patch_to_buf(out, patch);
|
||||
|
||||
git_patch_free(patch);
|
||||
|
||||
if (error < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_diff_format_email(
|
||||
git_buf *out,
|
||||
git_diff *diff,
|
||||
const git_diff_format_email_options *opts)
|
||||
{
|
||||
git_diff_stats *stats = NULL;
|
||||
char *summary = NULL, *loc = NULL;
|
||||
bool ignore_marker;
|
||||
unsigned int format_flags = 0;
|
||||
int error;
|
||||
|
||||
assert(out && diff && opts);
|
||||
assert(opts->summary && opts->id && opts->author);
|
||||
|
||||
GITERR_CHECK_VERSION(opts, GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION, "git_format_email_options");
|
||||
|
||||
if ((ignore_marker = opts->flags & GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER) == false) {
|
||||
if (opts->patch_no > opts->total_patches) {
|
||||
giterr_set(GITERR_INVALID, "patch %"PRIuZ" out of range. max %"PRIuZ, opts->patch_no, opts->total_patches);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (opts->patch_no == 0) {
|
||||
giterr_set(GITERR_INVALID, "invalid patch no %"PRIuZ". should be >0", opts->patch_no);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* the summary we receive may not be clean.
|
||||
* it could potentially contain new line characters
|
||||
* or not be set, sanitize, */
|
||||
if ((loc = strpbrk(opts->summary, "\r\n")) != NULL) {
|
||||
size_t offset = 0;
|
||||
|
||||
if ((offset = (loc - opts->summary)) == 0) {
|
||||
giterr_set(GITERR_INVALID, "summary is empty");
|
||||
error = -1;
|
||||
}
|
||||
|
||||
summary = git__calloc(offset + 1, sizeof(char));
|
||||
GITERR_CHECK_ALLOC(summary);
|
||||
strncpy(summary, opts->summary, offset);
|
||||
}
|
||||
|
||||
error = git_diff_format_email__append_header_tobuf(out,
|
||||
opts->id, opts->author, summary == NULL ? opts->summary : summary,
|
||||
opts->patch_no, opts->total_patches, ignore_marker);
|
||||
|
||||
if (error < 0)
|
||||
goto on_error;
|
||||
|
||||
format_flags = GIT_DIFF_STATS_FULL | GIT_DIFF_STATS_INCLUDE_SUMMARY;
|
||||
|
||||
if ((error = git_buf_puts(out, "---\n")) < 0 ||
|
||||
(error = git_diff_get_stats(&stats, diff)) < 0 ||
|
||||
(error = git_diff_stats_to_buf(out, stats, format_flags)) < 0 ||
|
||||
(error = git_diff_format_email__append_patches_tobuf(out, diff)) < 0)
|
||||
goto on_error;
|
||||
|
||||
error = git_buf_puts(out, "--\nlibgit2 " LIBGIT2_VERSION "\n\n");
|
||||
|
||||
on_error:
|
||||
git__free(summary);
|
||||
git_diff_stats_free(stats);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_diff_commit_as_email(
|
||||
git_buf *out,
|
||||
git_repository *repo,
|
||||
git_commit *commit,
|
||||
size_t patch_no,
|
||||
size_t total_patches,
|
||||
git_diff_format_email_flags_t flags,
|
||||
const git_diff_options *diff_opts)
|
||||
{
|
||||
git_diff *diff = NULL;
|
||||
git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
|
||||
int error;
|
||||
|
||||
assert (out && repo && commit);
|
||||
|
||||
opts.flags = flags;
|
||||
opts.patch_no = patch_no;
|
||||
opts.total_patches = total_patches;
|
||||
opts.id = git_commit_id(commit);
|
||||
opts.summary = git_commit_summary(commit);
|
||||
opts.author = git_commit_author(commit);
|
||||
|
||||
if ((error = git_diff__commit(&diff, repo, commit, diff_opts)) < 0)
|
||||
return error;
|
||||
|
||||
error = git_diff_format_email(out, diff, &opts);
|
||||
|
||||
git_diff_free(diff);
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_diff_init_options(git_diff_options* opts, int version)
|
||||
{
|
||||
if (version != GIT_DIFF_OPTIONS_VERSION) {
|
||||
@ -1450,3 +1660,15 @@ int git_diff_find_init_options(git_diff_find_options* opts, int version)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int git_diff_format_email_init_options(git_diff_format_email_options* opts, int version)
|
||||
{
|
||||
if (version != GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION) {
|
||||
giterr_set(GITERR_INVALID, "Invalid version %d for git_diff_format_email_options", version);
|
||||
return -1;
|
||||
} else {
|
||||
git_diff_format_email_options o = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
|
||||
memcpy(opts, &o, sizeof(o));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -116,6 +116,9 @@ extern void git_diff_find_similar__hashsig_free(void *sig, void *payload);
|
||||
extern int git_diff_find_similar__calc_similarity(
|
||||
int *score, void *siga, void *sigb, void *payload);
|
||||
|
||||
extern int git_diff__commit(
|
||||
git_diff **diff, git_repository *repo, const git_commit *commit, const git_diff_options *opts);
|
||||
|
||||
/*
|
||||
* Sometimes a git_diff_file will have a zero size; this attempts to
|
||||
* fill in the size without loading the blob if possible. If that is
|
||||
|
@ -631,13 +631,13 @@ void git_patch_free(git_patch *patch)
|
||||
GIT_REFCOUNT_DEC(patch, diff_patch_free);
|
||||
}
|
||||
|
||||
const git_diff_delta *git_patch_get_delta(git_patch *patch)
|
||||
const git_diff_delta *git_patch_get_delta(const git_patch *patch)
|
||||
{
|
||||
assert(patch);
|
||||
return patch->delta;
|
||||
}
|
||||
|
||||
size_t git_patch_num_hunks(git_patch *patch)
|
||||
size_t git_patch_num_hunks(const git_patch *patch)
|
||||
{
|
||||
assert(patch);
|
||||
return git_array_size(patch->hunks);
|
||||
@ -708,7 +708,7 @@ int git_patch_get_hunk(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_patch_num_lines_in_hunk(git_patch *patch, size_t hunk_idx)
|
||||
int git_patch_num_lines_in_hunk(const git_patch *patch, size_t hunk_idx)
|
||||
{
|
||||
diff_patch_hunk *hunk;
|
||||
assert(patch);
|
||||
|
343
src/diff_stats.c
Normal file
343
src/diff_stats.c
Normal file
@ -0,0 +1,343 @@
|
||||
/*
|
||||
* 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 "diff_patch.h"
|
||||
|
||||
#define DIFF_RENAME_FILE_SEPARATOR " => "
|
||||
|
||||
struct git_diff_stats {
|
||||
git_vector patches;
|
||||
|
||||
size_t files_changed;
|
||||
size_t insertions;
|
||||
size_t deletions;
|
||||
};
|
||||
|
||||
static size_t diff_get_filename_padding(
|
||||
int has_renames,
|
||||
const git_diff_stats *stats)
|
||||
{
|
||||
const git_patch *patch = NULL;
|
||||
size_t i, max_padding = 0;
|
||||
|
||||
if (has_renames) {
|
||||
git_vector_foreach(&stats->patches, i, patch) {
|
||||
const git_diff_delta *delta = NULL;
|
||||
size_t len;
|
||||
|
||||
delta = git_patch_get_delta(patch);
|
||||
if (strcmp(delta->old_file.path, delta->new_file.path) == 0)
|
||||
continue;
|
||||
|
||||
if ((len = strlen(delta->old_file.path) + strlen(delta->new_file.path)) > max_padding)
|
||||
max_padding = len;
|
||||
}
|
||||
}
|
||||
|
||||
git_vector_foreach(&stats->patches, i, patch) {
|
||||
const git_diff_delta *delta = NULL;
|
||||
size_t len;
|
||||
|
||||
delta = git_patch_get_delta(patch);
|
||||
len = strlen(delta->new_file.path);
|
||||
|
||||
if (strcmp(delta->old_file.path, delta->new_file.path) != 0)
|
||||
continue;
|
||||
|
||||
if (len > max_padding)
|
||||
max_padding = len;
|
||||
}
|
||||
|
||||
return max_padding;
|
||||
}
|
||||
|
||||
int git_diff_file_stats__full_to_buf(
|
||||
git_buf *out,
|
||||
size_t max_padding,
|
||||
int has_renames,
|
||||
const git_patch *patch)
|
||||
{
|
||||
const char *old_path = NULL, *new_path = NULL;
|
||||
const git_diff_delta *delta = NULL;
|
||||
size_t padding, old_size, new_size;
|
||||
int error;
|
||||
|
||||
delta = git_patch_get_delta(patch);
|
||||
|
||||
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 ((error = git_buf_printf(out, " %s", old_path)) < 0)
|
||||
goto on_error;
|
||||
|
||||
if (strcmp(old_path, new_path) != 0) {
|
||||
padding = max_padding - strlen(old_path) - strlen(new_path);
|
||||
|
||||
if ((error = git_buf_printf(out, DIFF_RENAME_FILE_SEPARATOR "%s", new_path)) < 0)
|
||||
goto on_error;
|
||||
}
|
||||
else {
|
||||
padding = max_padding - strlen(old_path);
|
||||
|
||||
if (has_renames)
|
||||
padding += strlen(DIFF_RENAME_FILE_SEPARATOR);
|
||||
}
|
||||
|
||||
if ((error = git_buf_putcn(out, ' ', padding)) < 0 ||
|
||||
(error = git_buf_puts(out, " | ")) < 0)
|
||||
goto on_error;
|
||||
|
||||
if (delta->flags & GIT_DIFF_FLAG_BINARY) {
|
||||
if ((error = git_buf_printf(out, "Bin %" PRIuZ " -> %" PRIuZ " bytes", old_size, new_size)) < 0)
|
||||
goto on_error;
|
||||
}
|
||||
else {
|
||||
size_t insertions, deletions;
|
||||
|
||||
if ((error = git_patch_line_stats(NULL, &insertions, &deletions, patch)) < 0)
|
||||
goto on_error;
|
||||
|
||||
if ((error = git_buf_printf(out, "%" PRIuZ, insertions + deletions)) < 0)
|
||||
goto on_error;
|
||||
|
||||
if (insertions || deletions) {
|
||||
if ((error = git_buf_putc(out, ' ')) < 0 ||
|
||||
(error = git_buf_putcn(out, '+', insertions)) < 0 ||
|
||||
(error = git_buf_putcn(out, '-', deletions)) < 0)
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
|
||||
error = git_buf_putc(out, '\n');
|
||||
|
||||
on_error:
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_diff_file_stats__number_to_buf(
|
||||
git_buf *out,
|
||||
const git_patch *patch)
|
||||
{
|
||||
const git_diff_delta *delta = NULL;
|
||||
const char *path = NULL;
|
||||
size_t insertions, deletions;
|
||||
int error;
|
||||
|
||||
delta = git_patch_get_delta(patch);
|
||||
path = delta->new_file.path;
|
||||
|
||||
if ((error = git_patch_line_stats(NULL, &insertions, &deletions, patch)) < 0)
|
||||
return error;
|
||||
|
||||
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", insertions, deletions, path);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_diff_file_stats__summary_to_buf(
|
||||
git_buf *out,
|
||||
const git_patch *patch)
|
||||
{
|
||||
const git_diff_delta *delta = NULL;
|
||||
|
||||
delta = git_patch_get_delta(patch);
|
||||
|
||||
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_stats__has_renames(
|
||||
const git_diff_stats *stats)
|
||||
{
|
||||
git_patch *patch = NULL;
|
||||
size_t i;
|
||||
|
||||
git_vector_foreach(&stats->patches, i, patch) {
|
||||
const git_diff_delta *delta = git_patch_get_delta(patch);
|
||||
|
||||
if (strcmp(delta->old_file.path, delta->new_file.path) != 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_diff_stats__add_file_stats(
|
||||
git_diff_stats *stats,
|
||||
git_patch *patch)
|
||||
{
|
||||
const git_diff_delta *delta = NULL;
|
||||
int error = 0;
|
||||
|
||||
if ((delta = git_patch_get_delta(patch)) == NULL)
|
||||
return -1;
|
||||
|
||||
if ((error = git_vector_insert(&stats->patches, patch)) < 0)
|
||||
return error;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
assert(out && diff);
|
||||
|
||||
stats = git__calloc(1, sizeof(git_diff_stats));
|
||||
GITERR_CHECK_ALLOC(stats);
|
||||
|
||||
deltas = git_diff_num_deltas(diff);
|
||||
|
||||
for (i = 0; i < deltas; ++i) {
|
||||
git_patch *patch = NULL;
|
||||
size_t add, remove;
|
||||
|
||||
if ((error = git_patch_from_diff(&patch, diff, i)) < 0)
|
||||
goto on_error;
|
||||
|
||||
if ((error = git_patch_line_stats(NULL, &add, &remove, patch)) < 0 ||
|
||||
(error = git_diff_stats__add_file_stats(stats, patch)) < 0) {
|
||||
git_patch_free(patch);
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
total_insertions += add;
|
||||
total_deletions += remove;
|
||||
}
|
||||
|
||||
stats->files_changed = deltas;
|
||||
stats->insertions = total_insertions;
|
||||
stats->deletions = total_deletions;
|
||||
|
||||
*out = stats;
|
||||
|
||||
goto done;
|
||||
|
||||
on_error:
|
||||
git_diff_stats_free(stats);
|
||||
|
||||
done:
|
||||
return error;
|
||||
}
|
||||
|
||||
size_t git_diff_stats_files_changed(
|
||||
const git_diff_stats *stats)
|
||||
{
|
||||
assert(stats);
|
||||
|
||||
return stats->files_changed;
|
||||
}
|
||||
|
||||
size_t git_diff_stats_insertions(
|
||||
const git_diff_stats *stats)
|
||||
{
|
||||
assert(stats);
|
||||
|
||||
return stats->insertions;
|
||||
}
|
||||
|
||||
size_t git_diff_stats_deletions(
|
||||
const git_diff_stats *stats)
|
||||
{
|
||||
assert(stats);
|
||||
|
||||
return stats->deletions;
|
||||
}
|
||||
|
||||
int git_diff_stats_to_buf(
|
||||
git_buf *out,
|
||||
const git_diff_stats *stats,
|
||||
git_diff_stats_format_t format)
|
||||
{
|
||||
git_patch *patch = NULL;
|
||||
size_t i;
|
||||
int has_renames = 0, error = 0;
|
||||
|
||||
assert(out && stats);
|
||||
|
||||
/* check if we have renames, it affects the padding */
|
||||
has_renames = git_diff_stats__has_renames(stats);
|
||||
|
||||
git_vector_foreach(&stats->patches, i, patch) {
|
||||
if (format & GIT_DIFF_STATS_FULL) {
|
||||
size_t max_padding = diff_get_filename_padding(has_renames, stats);
|
||||
|
||||
error = git_diff_file_stats__full_to_buf(out, max_padding, has_renames, patch);
|
||||
}
|
||||
else if (format & GIT_DIFF_STATS_NUMBER) {
|
||||
error = git_diff_file_stats__number_to_buf(out, patch);
|
||||
}
|
||||
|
||||
if (error < 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
if (format & GIT_DIFF_STATS_FULL || format & GIT_DIFF_STATS_SHORT) {
|
||||
error = git_buf_printf(out, " %" PRIuZ " file%s changed, %" PRIuZ " insertions(+), %" PRIuZ " deletions(-)\n",
|
||||
stats->files_changed, stats->files_changed > 1 ? "s" : "",
|
||||
stats->insertions, stats->deletions);
|
||||
|
||||
if (error < 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
if (format & GIT_DIFF_STATS_INCLUDE_SUMMARY) {
|
||||
git_vector_foreach(&stats->patches, i, patch) {
|
||||
if ((error = git_diff_file_stats__summary_to_buf(out, patch)) < 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
if (git_vector_length(&stats->patches) > 0)
|
||||
git_buf_putc(out, '\n');
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void git_diff_stats_free(git_diff_stats *stats)
|
||||
{
|
||||
size_t i;
|
||||
git_patch *patch;
|
||||
|
||||
if (stats == NULL)
|
||||
return;
|
||||
|
||||
git_vector_foreach(&stats->patches, i, patch)
|
||||
git_patch_free(patch);
|
||||
|
||||
git_vector_free(&stats->patches);
|
||||
git__free(stats);
|
||||
}
|
||||
|
12
src/util.h
12
src/util.h
@ -20,6 +20,8 @@
|
||||
# define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define GIT_DATE_RFC2822_SZ 32
|
||||
|
||||
/*
|
||||
* Custom memory allocation wrappers
|
||||
* that set error code and error message
|
||||
@ -328,6 +330,16 @@ extern int git__parse_bool(int *out, const char *value);
|
||||
*/
|
||||
extern int git__date_parse(git_time_t *out, const char *date);
|
||||
|
||||
/*
|
||||
* Format a git_time as a RFC2822 string
|
||||
*
|
||||
* @param out buffer to store formatted date; a '\\0' terminator will automatically be added.
|
||||
* @param len size of the buffer; should be atleast `GIT_DATE_RFC2822_SZ` in size;
|
||||
* @param date the date to be formatted
|
||||
* @return 0 if successful; -1 on error
|
||||
*/
|
||||
extern int git__date_rfc2822_fmt(char *out, size_t len, const git_time *date);
|
||||
|
||||
/*
|
||||
* Unescapes a string in-place.
|
||||
*
|
||||
|
40
tests/date/rfc2822.c
Normal file
40
tests/date/rfc2822.c
Normal file
@ -0,0 +1,40 @@
|
||||
#include "clar_libgit2.h"
|
||||
|
||||
#include "util.h"
|
||||
|
||||
void test_date_rfc2822__format_rfc2822_no_offset(void)
|
||||
{
|
||||
git_time t = {1397031663, 0};
|
||||
char buf[GIT_DATE_RFC2822_SZ];
|
||||
|
||||
cl_git_pass(git__date_rfc2822_fmt(buf, sizeof(buf), &t));
|
||||
cl_assert(strcmp(buf, "Wed, 9 Apr 2014 08:21:03 +0000") == 0);
|
||||
}
|
||||
|
||||
void test_date_rfc2822__format_rfc2822_positive_offset(void)
|
||||
{
|
||||
git_time t = {1397031663, 120};
|
||||
char buf[GIT_DATE_RFC2822_SZ];
|
||||
|
||||
cl_git_pass(git__date_rfc2822_fmt(buf, sizeof(buf), &t));
|
||||
cl_assert(strcmp(buf, "Wed, 9 Apr 2014 10:21:03 +0200") == 0);
|
||||
}
|
||||
|
||||
void test_date_rfc2822__format_rfc2822_negative_offset(void)
|
||||
{
|
||||
git_time t = {1397031663, -120};
|
||||
char buf[GIT_DATE_RFC2822_SZ];
|
||||
|
||||
cl_git_pass(git__date_rfc2822_fmt(buf, sizeof(buf), &t));
|
||||
cl_assert(strcmp(buf, "Wed, 9 Apr 2014 06:21:03 -0200") == 0);
|
||||
}
|
||||
|
||||
void test_date_rfc2822__format_rfc2822_buffer_too_small(void)
|
||||
{
|
||||
// "Wed, 10 Apr 2014 08:21:03 +0000"
|
||||
git_time t = {1397031663 + 86400, 0};
|
||||
char buf[GIT_DATE_RFC2822_SZ-1];
|
||||
|
||||
cl_git_fail(git__date_rfc2822_fmt(buf, sizeof(buf), &t));
|
||||
}
|
||||
|
556
tests/diff/format_email.c
Normal file
556
tests/diff/format_email.c
Normal file
@ -0,0 +1,556 @@
|
||||
#include "clar.h"
|
||||
#include "clar_libgit2.h"
|
||||
|
||||
#include "buffer.h"
|
||||
#include "commit.h"
|
||||
#include "diff.h"
|
||||
|
||||
static git_repository *repo;
|
||||
|
||||
void test_diff_format_email__initialize(void)
|
||||
{
|
||||
repo = cl_git_sandbox_init("diff_format_email");
|
||||
}
|
||||
|
||||
void test_diff_format_email__cleanup(void)
|
||||
{
|
||||
cl_git_sandbox_cleanup();
|
||||
}
|
||||
|
||||
void test_diff_format_email__simple(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *email =
|
||||
"From 9264b96c6d104d0e07ae33d3007b6a48246c6f92 Mon Sep 17 00:00:00 2001\n" \
|
||||
"From: Jacques Germishuys <jacquesg@striata.com>\n" \
|
||||
"Date: Wed, 9 Apr 2014 20:57:01 +0200\n" \
|
||||
"Subject: [PATCH] Modify some content\n" \
|
||||
"\n" \
|
||||
"---\n" \
|
||||
" file1.txt | 8 +++++---\n" \
|
||||
" 1 file changed, 5 insertions(+), 3 deletions(-)\n" \
|
||||
"\n" \
|
||||
"diff --git a/file1.txt b/file1.txt\n" \
|
||||
"index 94aaae8..af8f41d 100644\n" \
|
||||
"--- a/file1.txt\n" \
|
||||
"+++ b/file1.txt\n" \
|
||||
"@@ -1,15 +1,17 @@\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
"+_file1.txt_\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
"+\n" \
|
||||
"+\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
"-file1.txt\n" \
|
||||
"-file1.txt\n" \
|
||||
"-file1.txt\n" \
|
||||
"+_file1.txt_\n" \
|
||||
"+_file1.txt_\n" \
|
||||
" file1.txt\n" \
|
||||
"--\n" \
|
||||
"libgit2 " LIBGIT2_VERSION "\n" \
|
||||
"\n";
|
||||
|
||||
git_oid_fromstr(&oid, "9264b96c6d104d0e07ae33d3007b6a48246c6f92");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
|
||||
opts.id = git_commit_id(commit);
|
||||
opts.author = git_commit_author(commit);
|
||||
opts.summary = git_commit_summary(commit);
|
||||
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
cl_git_pass(git_diff_format_email(&buf, diff, &opts));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), email) == 0);
|
||||
|
||||
git_buf_clear(&buf);
|
||||
cl_git_pass(git_diff_commit_as_email(&buf, repo, commit, 1, 1, 0, NULL));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), email) == 0);
|
||||
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_format_email__multiple(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *email =
|
||||
"From 10808fe9c9be5a190c0ba68d1a002233fb363508 Mon Sep 17 00:00:00 2001\n" \
|
||||
"From: Jacques Germishuys <jacquesg@striata.com>\n" \
|
||||
"Date: Thu, 10 Apr 2014 19:37:05 +0200\n" \
|
||||
"Subject: [PATCH 1/2] Added file2.txt file3.txt\n" \
|
||||
"\n" \
|
||||
"---\n" \
|
||||
" file2.txt | 5 +++++\n" \
|
||||
" file3.txt | 5 +++++\n" \
|
||||
" 2 files changed, 10 insertions(+), 0 deletions(-)\n" \
|
||||
" create mode 100644 file2.txt\n" \
|
||||
" create mode 100644 file3.txt\n" \
|
||||
"\n" \
|
||||
"diff --git a/file2.txt b/file2.txt\n" \
|
||||
"new file mode 100644\n" \
|
||||
"index 0000000..e909123\n" \
|
||||
"--- /dev/null\n" \
|
||||
"+++ b/file2.txt\n" \
|
||||
"@@ -0,0 +1,5 @@\n" \
|
||||
"+file2\n" \
|
||||
"+file2\n" \
|
||||
"+file2\n" \
|
||||
"+file2\n" \
|
||||
"+file2\n" \
|
||||
"diff --git a/file3.txt b/file3.txt\n" \
|
||||
"new file mode 100644\n" \
|
||||
"index 0000000..9435022\n" \
|
||||
"--- /dev/null\n" \
|
||||
"+++ b/file3.txt\n" \
|
||||
"@@ -0,0 +1,5 @@\n" \
|
||||
"+file3\n" \
|
||||
"+file3\n" \
|
||||
"+file3\n" \
|
||||
"+file3\n" \
|
||||
"+file3\n" \
|
||||
"--\n" \
|
||||
"libgit2 " LIBGIT2_VERSION "\n" \
|
||||
"\n" \
|
||||
"From 873806f6f27e631eb0b23e4b56bea2bfac14a373 Mon Sep 17 00:00:00 2001\n" \
|
||||
"From: Jacques Germishuys <jacquesg@striata.com>\n" \
|
||||
"Date: Thu, 10 Apr 2014 19:37:36 +0200\n" \
|
||||
"Subject: [PATCH 2/2] Modified file2.txt, file3.txt\n" \
|
||||
"\n" \
|
||||
"---\n" \
|
||||
" file2.txt | 2 +-\n" \
|
||||
" file3.txt | 2 +-\n" \
|
||||
" 2 files changed, 2 insertions(+), 2 deletions(-)\n" \
|
||||
"\n" \
|
||||
"diff --git a/file2.txt b/file2.txt\n" \
|
||||
"index e909123..7aff11d 100644\n" \
|
||||
"--- a/file2.txt\n" \
|
||||
"+++ b/file2.txt\n" \
|
||||
"@@ -1,5 +1,5 @@\n" \
|
||||
" file2\n" \
|
||||
" file2\n" \
|
||||
" file2\n" \
|
||||
"-file2\n" \
|
||||
"+file2!\n" \
|
||||
" file2\n" \
|
||||
"diff --git a/file3.txt b/file3.txt\n" \
|
||||
"index 9435022..9a2d780 100644\n" \
|
||||
"--- a/file3.txt\n" \
|
||||
"+++ b/file3.txt\n" \
|
||||
"@@ -1,5 +1,5 @@\n" \
|
||||
" file3\n" \
|
||||
"-file3\n" \
|
||||
"+file3!\n" \
|
||||
" file3\n" \
|
||||
" file3\n" \
|
||||
" file3\n" \
|
||||
"--\n" \
|
||||
"libgit2 " LIBGIT2_VERSION "\n" \
|
||||
"\n";
|
||||
|
||||
git_oid_fromstr(&oid, "10808fe9c9be5a190c0ba68d1a002233fb363508");
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
|
||||
opts.id = git_commit_id(commit);
|
||||
opts.author = git_commit_author(commit);
|
||||
opts.summary = git_commit_summary(commit);
|
||||
opts.patch_no = 1;
|
||||
opts.total_patches = 2;
|
||||
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
cl_git_pass(git_diff_format_email(&buf, diff, &opts));
|
||||
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
diff = NULL;
|
||||
commit = NULL;
|
||||
|
||||
git_oid_fromstr(&oid, "873806f6f27e631eb0b23e4b56bea2bfac14a373");
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
|
||||
opts.id = git_commit_id(commit);
|
||||
opts.author = git_commit_author(commit);
|
||||
opts.summary = git_commit_summary(commit);
|
||||
opts.patch_no = 2;
|
||||
opts.total_patches = 2;
|
||||
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
cl_git_pass(git_diff_format_email(&buf, diff, &opts));
|
||||
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), email) == 0);
|
||||
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_format_email__exclude_marker(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *email =
|
||||
"From 9264b96c6d104d0e07ae33d3007b6a48246c6f92 Mon Sep 17 00:00:00 2001\n" \
|
||||
"From: Jacques Germishuys <jacquesg@striata.com>\n" \
|
||||
"Date: Wed, 9 Apr 2014 20:57:01 +0200\n" \
|
||||
"Subject: Modify some content\n" \
|
||||
"\n" \
|
||||
"---\n" \
|
||||
" file1.txt | 8 +++++---\n" \
|
||||
" 1 file changed, 5 insertions(+), 3 deletions(-)\n" \
|
||||
"\n" \
|
||||
"diff --git a/file1.txt b/file1.txt\n" \
|
||||
"index 94aaae8..af8f41d 100644\n" \
|
||||
"--- a/file1.txt\n" \
|
||||
"+++ b/file1.txt\n" \
|
||||
"@@ -1,15 +1,17 @@\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
"+_file1.txt_\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
"+\n" \
|
||||
"+\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
"-file1.txt\n" \
|
||||
"-file1.txt\n" \
|
||||
"-file1.txt\n" \
|
||||
"+_file1.txt_\n" \
|
||||
"+_file1.txt_\n" \
|
||||
" file1.txt\n" \
|
||||
"--\n" \
|
||||
"libgit2 " LIBGIT2_VERSION "\n" \
|
||||
"\n";
|
||||
|
||||
git_oid_fromstr(&oid, "9264b96c6d104d0e07ae33d3007b6a48246c6f92");
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
|
||||
opts.id = git_commit_id(commit);
|
||||
opts.author = git_commit_author(commit);
|
||||
opts.summary = git_commit_summary(commit);
|
||||
|
||||
opts.flags |= GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER;
|
||||
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
cl_git_pass(git_diff_format_email(&buf, diff, &opts));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), email) == 0);
|
||||
|
||||
git_buf_clear(&buf);
|
||||
cl_git_pass(git_diff_commit_as_email(&buf, repo, commit, 1, 1,
|
||||
GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER, NULL));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), email) == 0);
|
||||
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_format_email__invalid_no(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
git_oid_fromstr(&oid, "9264b96c6d104d0e07ae33d3007b6a48246c6f92");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
|
||||
opts.id = git_commit_id(commit);
|
||||
opts.author = git_commit_author(commit);
|
||||
opts.summary = git_commit_summary(commit);
|
||||
opts.patch_no = 2;
|
||||
opts.total_patches = 1;
|
||||
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
cl_git_fail(git_diff_format_email(&buf, diff, &opts));
|
||||
cl_git_fail(git_diff_commit_as_email(&buf, repo, commit, 2, 1, 0, NULL));
|
||||
cl_git_fail(git_diff_commit_as_email(&buf, repo, commit, 0, 0, 0, NULL));
|
||||
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_format_email__mode_change(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *email =
|
||||
"From 7ade76dd34bba4733cf9878079f9fd4a456a9189 Mon Sep 17 00:00:00 2001\n" \
|
||||
"From: Jacques Germishuys <jacquesg@striata.com>\n" \
|
||||
"Date: Thu, 10 Apr 2014 10:05:03 +0200\n" \
|
||||
"Subject: [PATCH] Update permissions\n" \
|
||||
"\n" \
|
||||
"---\n" \
|
||||
" file1.txt.renamed | 0\n" \
|
||||
" 1 file changed, 0 insertions(+), 0 deletions(-)\n" \
|
||||
" mode change 100644 => 100755 file1.txt.renamed\n" \
|
||||
"\n" \
|
||||
"diff --git a/file1.txt.renamed b/file1.txt.renamed\n" \
|
||||
"old mode 100644\n" \
|
||||
"new mode 100755\n" \
|
||||
"index a97157a..a97157a\n" \
|
||||
"--- a/file1.txt.renamed\n" \
|
||||
"+++ b/file1.txt.renamed\n" \
|
||||
"--\n" \
|
||||
"libgit2 " LIBGIT2_VERSION "\n" \
|
||||
"\n";
|
||||
|
||||
git_oid_fromstr(&oid, "7ade76dd34bba4733cf9878079f9fd4a456a9189");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
|
||||
opts.id = git_commit_id(commit);
|
||||
opts.author = git_commit_author(commit);
|
||||
opts.summary = git_commit_summary(commit);
|
||||
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
cl_git_pass(git_diff_format_email(&buf, diff, &opts));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), email) == 0);
|
||||
|
||||
git_buf_clear(&buf);
|
||||
cl_git_pass(git_diff_commit_as_email(&buf, repo, commit, 1, 1, 0, NULL));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), email) == 0);
|
||||
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_format_email__rename_add_remove(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *email =
|
||||
"From 6e05acc5a5dab507d91a0a0cc0fb05a3dd98892d Mon Sep 17 00:00:00 2001\n" \
|
||||
"From: Jacques Germishuys <jacquesg@striata.com>\n" \
|
||||
"Date: Wed, 9 Apr 2014 21:15:56 +0200\n" \
|
||||
"Subject: [PATCH] Renamed file1.txt -> file1.txt.renamed\n" \
|
||||
"\n" \
|
||||
"---\n" \
|
||||
" file1.txt | 17 -----------------\n" \
|
||||
" file1.txt.renamed | 17 +++++++++++++++++\n" \
|
||||
" 2 files changed, 17 insertions(+), 17 deletions(-)\n" \
|
||||
" delete mode 100644 file1.txt\n" \
|
||||
" create mode 100644 file1.txt.renamed\n" \
|
||||
"\n" \
|
||||
"diff --git a/file1.txt b/file1.txt\n" \
|
||||
"deleted file mode 100644\n" \
|
||||
"index af8f41d..0000000\n" \
|
||||
"--- a/file1.txt\n" \
|
||||
"+++ /dev/null\n" \
|
||||
"@@ -1,17 +0,0 @@\n" \
|
||||
"-file1.txt\n" \
|
||||
"-file1.txt\n" \
|
||||
"-_file1.txt_\n" \
|
||||
"-file1.txt\n" \
|
||||
"-file1.txt\n" \
|
||||
"-file1.txt\n" \
|
||||
"-file1.txt\n" \
|
||||
"-\n" \
|
||||
"-\n" \
|
||||
"-file1.txt\n" \
|
||||
"-file1.txt\n" \
|
||||
"-file1.txt\n" \
|
||||
"-file1.txt\n" \
|
||||
"-file1.txt\n" \
|
||||
"-_file1.txt_\n" \
|
||||
"-_file1.txt_\n" \
|
||||
"-file1.txt\n" \
|
||||
"diff --git a/file1.txt.renamed b/file1.txt.renamed\n" \
|
||||
"new file mode 100644\n" \
|
||||
"index 0000000..a97157a\n" \
|
||||
"--- /dev/null\n" \
|
||||
"+++ b/file1.txt.renamed\n" \
|
||||
"@@ -0,0 +1,17 @@\n" \
|
||||
"+file1.txt\n" \
|
||||
"+file1.txt\n" \
|
||||
"+_file1.txt_\n" \
|
||||
"+file1.txt\n" \
|
||||
"+file1.txt\n" \
|
||||
"+file1.txt_renamed\n" \
|
||||
"+file1.txt\n" \
|
||||
"+\n" \
|
||||
"+\n" \
|
||||
"+file1.txt\n" \
|
||||
"+file1.txt\n" \
|
||||
"+file1.txt_renamed\n" \
|
||||
"+file1.txt\n" \
|
||||
"+file1.txt\n" \
|
||||
"+_file1.txt_\n" \
|
||||
"+_file1.txt_\n" \
|
||||
"+file1.txt\n" \
|
||||
"--\n" \
|
||||
"libgit2 " LIBGIT2_VERSION "\n" \
|
||||
"\n";
|
||||
|
||||
git_oid_fromstr(&oid, "6e05acc5a5dab507d91a0a0cc0fb05a3dd98892d");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
|
||||
opts.id = git_commit_id(commit);
|
||||
opts.author = git_commit_author(commit);
|
||||
opts.summary = git_commit_summary(commit);
|
||||
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
cl_git_pass(git_diff_format_email(&buf, diff, &opts));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), email) == 0);
|
||||
|
||||
git_buf_clear(&buf);
|
||||
cl_git_pass(git_diff_commit_as_email(&buf, repo, commit, 1, 1, 0, NULL));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), email) == 0);
|
||||
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_format_email__multiline_summary(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *email =
|
||||
"From 9264b96c6d104d0e07ae33d3007b6a48246c6f92 Mon Sep 17 00:00:00 2001\n" \
|
||||
"From: Jacques Germishuys <jacquesg@striata.com>\n" \
|
||||
"Date: Wed, 9 Apr 2014 20:57:01 +0200\n" \
|
||||
"Subject: [PATCH] Modify some content\n" \
|
||||
"\n" \
|
||||
"---\n" \
|
||||
" file1.txt | 8 +++++---\n" \
|
||||
" 1 file changed, 5 insertions(+), 3 deletions(-)\n" \
|
||||
"\n" \
|
||||
"diff --git a/file1.txt b/file1.txt\n" \
|
||||
"index 94aaae8..af8f41d 100644\n" \
|
||||
"--- a/file1.txt\n" \
|
||||
"+++ b/file1.txt\n" \
|
||||
"@@ -1,15 +1,17 @@\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
"+_file1.txt_\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
"+\n" \
|
||||
"+\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
" file1.txt\n" \
|
||||
"-file1.txt\n" \
|
||||
"-file1.txt\n" \
|
||||
"-file1.txt\n" \
|
||||
"+_file1.txt_\n" \
|
||||
"+_file1.txt_\n" \
|
||||
" file1.txt\n" \
|
||||
"--\n" \
|
||||
"libgit2 " LIBGIT2_VERSION "\n" \
|
||||
"\n";
|
||||
|
||||
git_oid_fromstr(&oid, "9264b96c6d104d0e07ae33d3007b6a48246c6f92");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
|
||||
opts.id = git_commit_id(commit);
|
||||
opts.author = git_commit_author(commit);
|
||||
opts.summary = "Modify some content\nSome extra stuff here";
|
||||
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
cl_git_pass(git_diff_format_email(&buf, diff, &opts));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), email) == 0);
|
||||
|
||||
git_buf_clear(&buf);
|
||||
cl_git_pass(git_diff_commit_as_email(&buf, repo, commit, 1, 1, 0, NULL));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), email) == 0);
|
||||
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_format_email__binary(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
/* TODO: Actually 0 bytes here should be 5!. Seems like we don't load the new content for binary files? */
|
||||
const char *email =
|
||||
"From 8d7523f6fcb2404257889abe0d96f093d9f524f9 Mon Sep 17 00:00:00 2001\n" \
|
||||
"From: Jacques Germishuys <jacquesg@striata.com>\n" \
|
||||
"Date: Sun, 13 Apr 2014 18:10:18 +0200\n" \
|
||||
"Subject: [PATCH] Modified binary file\n" \
|
||||
"\n" \
|
||||
"---\n" \
|
||||
" binary.bin | Bin 3 -> 0 bytes\n" \
|
||||
" 1 file changed, 0 insertions(+), 0 deletions(-)\n" \
|
||||
"\n" \
|
||||
"diff --git a/binary.bin b/binary.bin\n" \
|
||||
"index bd474b2..9ac35ff 100644\n" \
|
||||
"Binary files a/binary.bin and b/binary.bin differ\n" \
|
||||
"--\n" \
|
||||
"libgit2 " LIBGIT2_VERSION "\n" \
|
||||
"\n";
|
||||
|
||||
git_oid_fromstr(&oid, "8d7523f6fcb2404257889abe0d96f093d9f524f9");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
|
||||
opts.id = git_commit_id(commit);
|
||||
opts.author = git_commit_author(commit);
|
||||
opts.summary = "Modified binary file";
|
||||
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
cl_git_pass(git_diff_format_email(&buf, diff, &opts));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), email) == 0);
|
||||
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
428
tests/diff/stats.c
Normal file
428
tests/diff/stats.c
Normal file
@ -0,0 +1,428 @@
|
||||
#include "clar.h"
|
||||
#include "clar_libgit2.h"
|
||||
|
||||
#include "buffer.h"
|
||||
#include "commit.h"
|
||||
#include "diff.h"
|
||||
|
||||
static git_repository *repo;
|
||||
|
||||
void test_diff_stats__initialize(void)
|
||||
{
|
||||
repo = cl_git_sandbox_init("diff_format_email");
|
||||
}
|
||||
|
||||
void test_diff_stats__cleanup(void)
|
||||
{
|
||||
cl_git_sandbox_cleanup();
|
||||
}
|
||||
|
||||
void test_diff_stats__stat(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_stats *stats = NULL;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *stat =
|
||||
" file1.txt | 8 +++++---\n" \
|
||||
" 1 file changed, 5 insertions(+), 3 deletions(-)\n";
|
||||
|
||||
git_oid_fromstr(&oid, "9264b96c6d104d0e07ae33d3007b6a48246c6f92");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
|
||||
cl_git_pass(git_diff_get_stats(&stats, diff));
|
||||
cl_assert(git_diff_stats_files_changed(stats) == 1);
|
||||
cl_assert(git_diff_stats_insertions(stats) == 5);
|
||||
cl_assert(git_diff_stats_deletions(stats) == 3);
|
||||
|
||||
cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0);
|
||||
|
||||
git_diff_stats_free(stats);
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_stats__multiple_hunks(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_stats *stats = NULL;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *stat =
|
||||
" file2.txt | 5 +++--\n" \
|
||||
" file3.txt | 6 ++++--\n" \
|
||||
" 2 files changed, 7 insertions(+), 4 deletions(-)\n";
|
||||
|
||||
git_oid_fromstr(&oid, "cd471f0d8770371e1bc78bcbb38db4c7e4106bd2");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
|
||||
cl_git_pass(git_diff_get_stats(&stats, diff));
|
||||
cl_assert(git_diff_stats_files_changed(stats) == 2);
|
||||
cl_assert(git_diff_stats_insertions(stats) == 7);
|
||||
cl_assert(git_diff_stats_deletions(stats) == 4);
|
||||
|
||||
cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0);
|
||||
|
||||
git_diff_stats_free(stats);
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_stats__numstat(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_stats *stats = NULL;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *stat =
|
||||
"3 2 file2.txt\n"
|
||||
"4 2 file3.txt\n";
|
||||
|
||||
git_oid_fromstr(&oid, "cd471f0d8770371e1bc78bcbb38db4c7e4106bd2");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
|
||||
cl_git_pass(git_diff_get_stats(&stats, diff));
|
||||
|
||||
cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_NUMBER));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0);
|
||||
|
||||
git_diff_stats_free(stats);
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_stats__shortstat(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_stats *stats = NULL;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *stat =
|
||||
" 1 file changed, 5 insertions(+), 3 deletions(-)\n";
|
||||
|
||||
git_oid_fromstr(&oid, "9264b96c6d104d0e07ae33d3007b6a48246c6f92");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
|
||||
cl_git_pass(git_diff_get_stats(&stats, diff));
|
||||
cl_assert(git_diff_stats_files_changed(stats) == 1);
|
||||
cl_assert(git_diff_stats_insertions(stats) == 5);
|
||||
cl_assert(git_diff_stats_deletions(stats) == 3);
|
||||
|
||||
cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_SHORT));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0);
|
||||
|
||||
git_diff_stats_free(stats);
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_stats__rename(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_stats *stats = NULL;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *stat =
|
||||
" file2.txt => file2.txt.renamed | 1 +\n"
|
||||
" file3.txt => file3.txt.renamed | 4 +++-\n"
|
||||
" 2 files changed, 4 insertions(+), 1 deletions(-)\n";
|
||||
|
||||
git_oid_fromstr(&oid, "8947a46e2097638ca6040ad4877246f4186ec3bd");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
cl_git_pass(git_diff_find_similar(diff, NULL));
|
||||
|
||||
cl_git_pass(git_diff_get_stats(&stats, diff));
|
||||
cl_assert(git_diff_stats_files_changed(stats) == 2);
|
||||
cl_assert(git_diff_stats_insertions(stats) == 4);
|
||||
cl_assert(git_diff_stats_deletions(stats) == 1);
|
||||
|
||||
cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0);
|
||||
|
||||
git_diff_stats_free(stats);
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_stats__rename_nochanges(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_stats *stats = NULL;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *stat =
|
||||
" file2.txt.renamed => file2.txt.renamed2 | 0\n"
|
||||
" file3.txt.renamed => file3.txt.renamed2 | 0\n"
|
||||
" 2 files changed, 0 insertions(+), 0 deletions(-)\n";
|
||||
|
||||
git_oid_fromstr(&oid, "3991dce9e71a0641ca49a6a4eea6c9e7ff402ed4");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
cl_git_pass(git_diff_find_similar(diff, NULL));
|
||||
|
||||
cl_git_pass(git_diff_get_stats(&stats, diff));
|
||||
cl_assert(git_diff_stats_files_changed(stats) == 2);
|
||||
cl_assert(git_diff_stats_insertions(stats) == 0);
|
||||
cl_assert(git_diff_stats_deletions(stats) == 0);
|
||||
|
||||
cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0);
|
||||
|
||||
git_diff_stats_free(stats);
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_stats__rename_and_modifiy(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_stats *stats = NULL;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *stat =
|
||||
" file2.txt.renamed2 | 2 +-\n"
|
||||
" file3.txt.renamed2 => file3.txt.renamed | 0\n"
|
||||
" 2 files changed, 1 insertions(+), 1 deletions(-)\n";
|
||||
|
||||
git_oid_fromstr(&oid, "4ca10087e696d2ba78d07b146a118e9a7096ed4f");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
cl_git_pass(git_diff_find_similar(diff, NULL));
|
||||
|
||||
cl_git_pass(git_diff_get_stats(&stats, diff));
|
||||
cl_assert(git_diff_stats_files_changed(stats) == 2);
|
||||
cl_assert(git_diff_stats_insertions(stats) == 1);
|
||||
cl_assert(git_diff_stats_deletions(stats) == 1);
|
||||
|
||||
cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0);
|
||||
|
||||
git_diff_stats_free(stats);
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_stats__rename_no_find(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_stats *stats = NULL;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *stat =
|
||||
" file2.txt | 5 -----\n"
|
||||
" file2.txt.renamed | 6 ++++++\n"
|
||||
" file3.txt | 5 -----\n"
|
||||
" file3.txt.renamed | 7 +++++++\n"
|
||||
" 4 files changed, 13 insertions(+), 10 deletions(-)\n";
|
||||
|
||||
git_oid_fromstr(&oid, "8947a46e2097638ca6040ad4877246f4186ec3bd");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
|
||||
cl_git_pass(git_diff_get_stats(&stats, diff));
|
||||
cl_assert(git_diff_stats_files_changed(stats) == 4);
|
||||
cl_assert(git_diff_stats_insertions(stats) == 13);
|
||||
cl_assert(git_diff_stats_deletions(stats) == 10);
|
||||
|
||||
cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0);
|
||||
|
||||
git_diff_stats_free(stats);
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_stats__rename_nochanges_no_find(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_stats *stats = NULL;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *stat =
|
||||
" file2.txt.renamed | 6 ------\n"
|
||||
" file2.txt.renamed2 | 6 ++++++\n"
|
||||
" file3.txt.renamed | 7 -------\n"
|
||||
" file3.txt.renamed2 | 7 +++++++\n"
|
||||
" 4 files changed, 13 insertions(+), 13 deletions(-)\n";
|
||||
|
||||
git_oid_fromstr(&oid, "3991dce9e71a0641ca49a6a4eea6c9e7ff402ed4");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
|
||||
cl_git_pass(git_diff_get_stats(&stats, diff));
|
||||
cl_assert(git_diff_stats_files_changed(stats) == 4);
|
||||
cl_assert(git_diff_stats_insertions(stats) == 13);
|
||||
cl_assert(git_diff_stats_deletions(stats) == 13);
|
||||
|
||||
cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0);
|
||||
|
||||
git_diff_stats_free(stats);
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_stats__rename_and_modifiy_no_find(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_stats *stats = NULL;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *stat =
|
||||
" file2.txt.renamed2 | 2 +-\n"
|
||||
" file3.txt.renamed | 7 +++++++\n"
|
||||
" file3.txt.renamed2 | 7 -------\n"
|
||||
" 3 files changed, 8 insertions(+), 8 deletions(-)\n";
|
||||
|
||||
git_oid_fromstr(&oid, "4ca10087e696d2ba78d07b146a118e9a7096ed4f");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
|
||||
cl_git_pass(git_diff_get_stats(&stats, diff));
|
||||
cl_assert(git_diff_stats_files_changed(stats) == 3);
|
||||
cl_assert(git_diff_stats_insertions(stats) == 8);
|
||||
cl_assert(git_diff_stats_deletions(stats) == 8);
|
||||
|
||||
cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0);
|
||||
|
||||
git_diff_stats_free(stats);
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_stats__binary(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_stats *stats = NULL;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
/* TODO: Actually 0 bytes here should be 5!. Seems like we don't load the new content for binary files? */
|
||||
const char *stat =
|
||||
" binary.bin | Bin 3 -> 0 bytes\n"
|
||||
" 1 file changed, 0 insertions(+), 0 deletions(-)\n";
|
||||
|
||||
git_oid_fromstr(&oid, "8d7523f6fcb2404257889abe0d96f093d9f524f9");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
|
||||
cl_git_pass(git_diff_get_stats(&stats, diff));
|
||||
cl_assert(git_diff_stats_files_changed(stats) == 1);
|
||||
cl_assert(git_diff_stats_insertions(stats) == 0);
|
||||
cl_assert(git_diff_stats_deletions(stats) == 0);
|
||||
|
||||
cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0);
|
||||
|
||||
git_diff_stats_free(stats);
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_stats__binary_numstat(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_stats *stats = NULL;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *stat =
|
||||
"- - binary.bin\n";
|
||||
|
||||
git_oid_fromstr(&oid, "8d7523f6fcb2404257889abe0d96f093d9f524f9");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
|
||||
cl_git_pass(git_diff_get_stats(&stats, diff));
|
||||
|
||||
cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_NUMBER));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0);
|
||||
|
||||
git_diff_stats_free(stats);
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_diff_stats__mode_change(void)
|
||||
{
|
||||
git_oid oid;
|
||||
git_commit *commit = NULL;
|
||||
git_diff *diff = NULL;
|
||||
git_diff_stats *stats = NULL;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
const char *stat =
|
||||
" file1.txt.renamed | 0\n" \
|
||||
" 1 file changed, 0 insertions(+), 0 deletions(-)\n" \
|
||||
" mode change 100644 => 100755 file1.txt.renamed\n" \
|
||||
"\n";
|
||||
|
||||
git_oid_fromstr(&oid, "7ade76dd34bba4733cf9878079f9fd4a456a9189");
|
||||
|
||||
cl_git_pass(git_commit_lookup(&commit, repo, &oid));
|
||||
cl_git_pass(git_diff__commit(&diff, repo, commit, NULL));
|
||||
|
||||
cl_git_pass(git_diff_get_stats(&stats, diff));
|
||||
|
||||
cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL | GIT_DIFF_STATS_INCLUDE_SUMMARY));
|
||||
cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0);
|
||||
|
||||
git_diff_stats_free(stats);
|
||||
git_diff_free(diff);
|
||||
git_commit_free(commit);
|
||||
git_buf_free(&buf);
|
||||
}
|
BIN
tests/resources/diff_format_email/.gitted/HEAD
Normal file
BIN
tests/resources/diff_format_email/.gitted/HEAD
Normal file
Binary file not shown.
BIN
tests/resources/diff_format_email/.gitted/config
Normal file
BIN
tests/resources/diff_format_email/.gitted/config
Normal file
Binary file not shown.
BIN
tests/resources/diff_format_email/.gitted/index
Normal file
BIN
tests/resources/diff_format_email/.gitted/index
Normal file
Binary file not shown.
BIN
tests/resources/diff_format_email/.gitted/info/exclude
Normal file
BIN
tests/resources/diff_format_email/.gitted/info/exclude
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
tests/resources/diff_format_email/.gitted/refs/heads/binary
Normal file
BIN
tests/resources/diff_format_email/.gitted/refs/heads/binary
Normal file
Binary file not shown.
BIN
tests/resources/diff_format_email/.gitted/refs/heads/master
Normal file
BIN
tests/resources/diff_format_email/.gitted/refs/heads/master
Normal file
Binary file not shown.
BIN
tests/resources/diff_format_email/.gitted/refs/heads/multihunk
Normal file
BIN
tests/resources/diff_format_email/.gitted/refs/heads/multihunk
Normal file
Binary file not shown.
BIN
tests/resources/diff_format_email/.gitted/refs/heads/rename
Normal file
BIN
tests/resources/diff_format_email/.gitted/refs/heads/rename
Normal file
Binary file not shown.
BIN
tests/resources/diff_format_email/file1.txt.renamed
Executable file
BIN
tests/resources/diff_format_email/file1.txt.renamed
Executable file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user