#include "../subcommand/diff_subcommand.hpp"
#include
#include
#include
#include "../utils/common.hpp"
#include "../utils/git_exception.hpp"
#include "../wrapper/patch_wrapper.hpp"
#include "../wrapper/repository_wrapper.hpp"
diff_subcommand::diff_subcommand(const libgit2_object&, CLI::App& app)
{
auto* sub = app.add_subcommand("diff", "Show changes between commits, commit and working tree, etc");
sub->add_option("", m_files, "tree-ish objects to compare")->expected(0, 2);
sub->add_flag("--stat", m_stat_flag, "Generate a diffstat");
sub->add_flag("--shortstat", m_shortstat_flag, "Output only the last line of --stat");
sub->add_flag("--numstat", m_numstat_flag, "Machine-friendly --stat");
sub->add_flag("--summary", m_summary_flag, "Output a condensed summary");
sub->add_flag("--name-only", m_name_only_flag, "Show only names of changed files");
sub->add_flag("--name-status", m_name_status_flag, "Show names and status of changed files");
sub->add_flag("--raw", m_raw_flag, "Generate the diff in raw format");
sub->add_flag("--cached,--staged", m_cached_flag, "Compare staged changes to HEAD");
sub->add_flag("--no-index", m_no_index_flag, "Compare two files on filesystem");
sub->add_flag("-R", m_reverse_flag, "Swap two inputs");
sub->add_flag("-a,--text", m_text_flag, "Treat all files as text");
sub->add_flag("--ignore-space-at-eol", m_ignore_space_at_eol_flag, "Ignore changes in whitespace at EOL");
sub->add_flag("-b,--ignore-space-change", m_ignore_space_change_flag, "Ignore changes in amount of whitespace");
sub->add_flag("-w,--ignore-all-space", m_ignore_all_space_flag, "Ignore whitespace when comparing lines");
sub->add_flag("--patience", m_patience_flag, "Generate diff using patience algorithm");
sub->add_flag("--minimal", m_minimal_flag, "Spend extra time to find smallest diff");
sub->add_option("-M,--find-renames", m_rename_threshold, "Detect renames")
->expected(0, 1)
->default_val(50)
->each(
[this](const std::string&)
{
m_find_renames_flag = true;
}
);
sub->add_option("-C,--find-copies", m_copy_threshold, "Detect copies")
->expected(0, 1)
->default_val(50)
->each(
[this](const std::string&)
{
m_find_copies_flag = true;
}
);
sub->add_flag("--find-copies-harder", m_find_copies_harder_flag, "Detect copies from unmodified files");
sub->add_flag("-B,--break-rewrites", m_break_rewrites_flag, "Detect file rewrites");
sub->add_option("-U,--unified", m_context_lines, "Lines of context");
sub->add_option("--inter-hunk-context", m_interhunk_lines, "Context between hunks");
sub->add_option("--abbrev", m_abbrev, "Abbreviation length for object names")->expected(0, 1);
sub->add_flag("--color", m_colour_flag, "Show colored diff");
sub->add_flag("--no-color", m_no_colour_flag, "Turn off colored diff");
sub->callback(
[this]()
{
this->run();
}
);
}
namespace
{
int colour_printer(
[[maybe_unused]] const git_diff_delta* delta,
[[maybe_unused]] const git_diff_hunk* hunk,
const git_diff_line* line,
void* payload
)
{
bool use_colour = *reinterpret_cast(payload);
// Only print origin for context/addition/deletion lines
bool print_origin = (line->origin == GIT_DIFF_LINE_CONTEXT || line->origin == GIT_DIFF_LINE_ADDITION || line->origin == GIT_DIFF_LINE_DELETION);
if (use_colour)
{
switch (line->origin)
{
case GIT_DIFF_LINE_ADDITION:
std::cout