/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/*
Copyright 2013-2021 The Libfossil Authors, see LICENSES/BSD-2-Clause.txt
SPDX-License-Identifier: BSD-2-Clause-FreeBSD
SPDX-FileCopyrightText: 2021 The Libfossil Authors
SPDX-ArtifactOfProjectName: Libfossil
SPDX-FileType: Code
Heavily indebted to the Fossil SCM project (https://fossil-scm.org).
*****************************************************************************
This file implements an "artifact diff" for in-repo content.
*/
#include "fossil-scm/fossil-cli.h" /* Fossil App mini-framework */
#include <stdlib.h> /* atoi() */
struct ADiffOpt {
int diffFlags;
short sbsWidth;
short contextLines;
char ansiColor;
};
typedef struct ADiffOpt ADiffOpt;
/**
*/
static int f_adiff(fsl_id_t v1, fsl_id_t v2, const ADiffOpt * opt){
int rc = 0;
fsl_cx * f = fcli_cx();
fsl_buffer lhs = fsl_buffer_empty;
fsl_buffer rhs = fsl_buffer_empty;
rc = fsl_content_get(f, v1, &lhs);
if(rc) return rc;
rc = fsl_content_get(f, v2, &rhs);
if(rc) return rc;
rc = fsl_diff_text(&lhs, &rhs, fsl_output_f_FILE, stdout,
opt->contextLines, opt->sbsWidth,
opt->diffFlags);
fsl_buffer_clear(&lhs);
fsl_buffer_clear(&rhs);
return rc;
}
int main(int argc, char const * const * argv ){
int rc = 0;
const char * vFrom = NULL;
const char * vTo = NULL;
fsl_cx * f;
fsl_id_t idFrom = 0, idTo = 0;
bool flagBw = false;
bool flagInvert = false;
bool flagLineNo = false;
bool flagHtml = false;
const char * flagSbsWidth = 0;
const char * flagContextLines = "3";
ADiffOpt diffOpt = {
0/*diffFlags*/,
0/*sbsWidth*/,
0/*contextLines*/,
0/*ansiColor*/
};
fcli_cliflag FCliFlags[] = {
FCLI_FLAG("v1","from","from-version",&vFrom,
"UUID of version 1. Default is the first non-flag argument"),
FCLI_FLAG("v2","to","to-version",&vTo,
"UUID of version 2. Default is the second non-flag argument"),
FCLI_FLAG("w","sbs-width","column-width",&flagSbsWidth,
"Side-by-side diff view width."),
FCLI_FLAG("c","context-lines","line-count",&flagContextLines,
"Number of lines of context."),
FCLI_FLAG_BOOL("l","line-numbers",&flagLineNo,
"Add line numbers."),
FCLI_FLAG_BOOL("i","invert",&flagInvert,
"Invert the direction of the diff."),
FCLI_FLAG_BOOL("h","html",&flagHtml,
"Generate HTML output."),
FCLI_FLAG_BOOL("bw","no-color",&flagBw,
"Disables ANSI color sequences."),
fcli_cliflag_empty_m
};
fcli_help_info FCliHelp = {
"Generates diff of individual blobs (not checkin versions!).",
"fromArtifactUuid toArtifactUuid",
NULL
};
fcli.cliFlags = FCliFlags;
fcli.appHelp = &FCliHelp;
rc = fcli_setup(argc, argv);
if(rc) goto end;
/* Set up/validate args... */
f = fcli_cx();
if(!fsl_cx_db_repo(f)){
rc = fcli_err_set(FSL_RC_NOT_A_REPO,
"Requires a repository db. See --help.");
goto end;
}
if(flagInvert){
diffOpt.diffFlags |= FSL_DIFF_INVERT;
}
if(flagLineNo){
diffOpt.diffFlags |= FSL_DIFF_LINENO;
}
if(flagHtml){
diffOpt.diffFlags |= FSL_DIFF_HTML;
}
if(!flagBw && fsl_isatty(1)){
diffOpt.diffFlags |= FSL_DIFF_ANSI_COLOR;
}
if(flagSbsWidth){
diffOpt.diffFlags |= FSL_DIFF_SIDEBYSIDE;
diffOpt.sbsWidth = atoi(flagSbsWidth);
}
if(flagContextLines){
diffOpt.contextLines = atoi(flagContextLines);
}
if(fcli_has_unused_flags(0)) goto end;
if(!vFrom) vFrom = fcli_next_arg(1);
if(!vTo) vTo = fcli_next_arg(1);
if(!vFrom || !vTo){
rc = fcli_err_set(FSL_RC_MISUSE, "Both of -v1 UUID and -v2 UUID are required.");
goto end;
}
rc = fsl_sym_to_rid(f, vFrom, FSL_SATYPE_ANY, &idFrom);
if(!rc){
rc = fsl_sym_to_rid(f, vTo, FSL_SATYPE_ANY, &idTo);
}
if(rc) goto end;
rc = f_adiff( idFrom, idTo, &diffOpt );
end:
return fcli_end_of_main(rc);
}