mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-28 15:58:29 +00:00
Some doc and examples/diff.c changes
I was playing with "git diff-index" and wanted to be able to emulate that behavior a little more closely with the diff example. Also, I wanted to play with running `git_diff_tree_to_workdir` directly even though core Git doesn't exactly have the equivalent, so I added a command line option for that and tweaked some other things in the example code. This changes a minor output thing in that the "raw" print helper function will no longer add ellipses (...) if the OID is not actually abbreviated.
This commit is contained in:
parent
a32d684f86
commit
12e422a056
151
examples/diff.c
151
examples/diff.c
@ -33,14 +33,26 @@ static const char *colors[] = {
|
||||
"\033[36m" /* cyan */
|
||||
};
|
||||
|
||||
enum {
|
||||
OUTPUT_DIFF = 0,
|
||||
OUTPUT_STAT = 1,
|
||||
OUTPUT_SHORTSTAT = 2,
|
||||
OUTPUT_NUMSTAT = 3
|
||||
};
|
||||
|
||||
enum {
|
||||
CACHE_NORMAL = 0,
|
||||
CACHE_ONLY = 1,
|
||||
CACHE_NONE = 2
|
||||
};
|
||||
|
||||
/** The 'opts' struct captures all the various parsed command line options. */
|
||||
struct opts {
|
||||
git_diff_options diffopts;
|
||||
git_diff_find_options findopts;
|
||||
int color;
|
||||
int cached;
|
||||
int numstat;
|
||||
int shortstat;
|
||||
int cache;
|
||||
int output;
|
||||
git_diff_format_t format;
|
||||
const char *treeish1;
|
||||
const char *treeish2;
|
||||
@ -48,11 +60,11 @@ struct opts {
|
||||
};
|
||||
|
||||
/** These functions are implemented at the end */
|
||||
static void usage(const char *message, const char *arg);
|
||||
static void parse_opts(struct opts *o, int argc, char *argv[]);
|
||||
static int color_printer(
|
||||
const git_diff_delta*, const git_diff_hunk*, const git_diff_line*, void*);
|
||||
static void diff_print_numstat(git_diff *diff);
|
||||
static void diff_print_shortstat(git_diff *diff);
|
||||
static void diff_print_stats(git_diff *diff, struct opts *o);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@ -61,7 +73,7 @@ int main(int argc, char *argv[])
|
||||
git_diff *diff;
|
||||
struct opts o = {
|
||||
GIT_DIFF_OPTIONS_INIT, GIT_DIFF_FIND_OPTIONS_INIT,
|
||||
-1, 0, 0, 0, GIT_DIFF_FORMAT_PATCH, NULL, NULL, "."
|
||||
-1, 0, 0, GIT_DIFF_FORMAT_PATCH, NULL, NULL, "."
|
||||
};
|
||||
|
||||
git_threads_init();
|
||||
@ -78,6 +90,7 @@ int main(int argc, char *argv[])
|
||||
* * <sha1> --cached
|
||||
* * <sha1>
|
||||
* * --cached
|
||||
* * --nocache (don't use index data in diff at all)
|
||||
* * nothing
|
||||
*
|
||||
* Currently ranged arguments like <sha1>..<sha2> and <sha1>...<sha2>
|
||||
@ -93,20 +106,23 @@ int main(int argc, char *argv[])
|
||||
check_lg2(
|
||||
git_diff_tree_to_tree(&diff, repo, t1, t2, &o.diffopts),
|
||||
"diff trees", NULL);
|
||||
else if (t1 && o.cached)
|
||||
check_lg2(
|
||||
git_diff_tree_to_index(&diff, repo, t1, NULL, &o.diffopts),
|
||||
"diff tree to index", NULL);
|
||||
else if (o.cache != CACHE_NORMAL) {
|
||||
if (!t1)
|
||||
treeish_to_tree(&t1, repo, "HEAD");
|
||||
|
||||
if (o.cache == CACHE_NONE)
|
||||
check_lg2(
|
||||
git_diff_tree_to_workdir(&diff, repo, t1, &o.diffopts),
|
||||
"diff tree to working directory", NULL);
|
||||
else
|
||||
check_lg2(
|
||||
git_diff_tree_to_index(&diff, repo, t1, NULL, &o.diffopts),
|
||||
"diff tree to index", NULL);
|
||||
}
|
||||
else if (t1)
|
||||
check_lg2(
|
||||
git_diff_tree_to_workdir_with_index(&diff, repo, t1, &o.diffopts),
|
||||
"diff tree to working directory", NULL);
|
||||
else if (o.cached) {
|
||||
treeish_to_tree(&t1, repo, "HEAD");
|
||||
check_lg2(
|
||||
git_diff_tree_to_index(&diff, repo, t1, NULL, &o.diffopts),
|
||||
"diff tree to index", NULL);
|
||||
}
|
||||
else
|
||||
check_lg2(
|
||||
git_diff_index_to_workdir(&diff, repo, NULL, &o.diffopts),
|
||||
@ -121,11 +137,14 @@ int main(int argc, char *argv[])
|
||||
|
||||
/** Generate simple output using libgit2 display helper. */
|
||||
|
||||
if (o.numstat == 1)
|
||||
diff_print_numstat(diff);
|
||||
else if (o.shortstat == 1)
|
||||
diff_print_shortstat(diff);
|
||||
else {
|
||||
switch (o.output) {
|
||||
case OUTPUT_STAT:
|
||||
case OUTPUT_NUMSTAT:
|
||||
case OUTPUT_SHORTSTAT:
|
||||
diff_print_stats(diff, &o);
|
||||
break;
|
||||
|
||||
case OUTPUT_DIFF:
|
||||
if (o.color >= 0)
|
||||
fputs(colors[0], stdout);
|
||||
|
||||
@ -135,6 +154,10 @@ 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. */
|
||||
@ -213,13 +236,20 @@ static void parse_opts(struct opts *o, int argc, char *argv[])
|
||||
!strcmp(a, "--patch"))
|
||||
o->format = GIT_DIFF_FORMAT_PATCH;
|
||||
else if (!strcmp(a, "--cached"))
|
||||
o->cached = 1;
|
||||
else if (!strcmp(a, "--name-only"))
|
||||
o->cache = CACHE_ONLY;
|
||||
else if (!strcmp(a, "--nocache"))
|
||||
o->cache = CACHE_NONE;
|
||||
else if (!strcmp(a, "--name-only") || !strcmp(a, "--format=name"))
|
||||
o->format = GIT_DIFF_FORMAT_NAME_ONLY;
|
||||
else if (!strcmp(a, "--name-status"))
|
||||
else if (!strcmp(a, "--name-status") ||
|
||||
!strcmp(a, "--format=name-status"))
|
||||
o->format = GIT_DIFF_FORMAT_NAME_STATUS;
|
||||
else if (!strcmp(a, "--raw"))
|
||||
else if (!strcmp(a, "--raw") || !strcmp(a, "--format=raw"))
|
||||
o->format = GIT_DIFF_FORMAT_RAW;
|
||||
else if (!strcmp(a, "--format=diff-index")) {
|
||||
o->format = GIT_DIFF_FORMAT_RAW;
|
||||
o->diffopts.id_abbrev = 40;
|
||||
}
|
||||
else if (!strcmp(a, "--color"))
|
||||
o->color = 0;
|
||||
else if (!strcmp(a, "--no-color"))
|
||||
@ -242,10 +272,12 @@ static void parse_opts(struct opts *o, int argc, char *argv[])
|
||||
o->diffopts.flags |= GIT_DIFF_PATIENCE;
|
||||
else if (!strcmp(a, "--minimal"))
|
||||
o->diffopts.flags |= GIT_DIFF_MINIMAL;
|
||||
else if (!strcmp(a, "--stat"))
|
||||
o->output = OUTPUT_STAT;
|
||||
else if (!strcmp(a, "--numstat"))
|
||||
o->numstat = 1;
|
||||
o->output = OUTPUT_NUMSTAT;
|
||||
else if (!strcmp(a, "--shortstat"))
|
||||
o->shortstat = 1;
|
||||
o->output = OUTPUT_SHORTSTAT;
|
||||
else if (match_uint16_arg(
|
||||
&o->findopts.rename_threshold, &args, "-M") ||
|
||||
match_uint16_arg(
|
||||
@ -267,6 +299,8 @@ static void parse_opts(struct opts *o, int argc, char *argv[])
|
||||
&o->diffopts.context_lines, &args, "--unified") &&
|
||||
!match_uint16_arg(
|
||||
&o->diffopts.interhunk_lines, &args, "--inter-hunk-context") &&
|
||||
!match_uint16_arg(
|
||||
&o->diffopts.id_abbrev, &args, "--abbrev") &&
|
||||
!match_str_arg(&o->diffopts.old_prefix, &args, "--src-prefix") &&
|
||||
!match_str_arg(&o->diffopts.new_prefix, &args, "--dst-prefix") &&
|
||||
!match_str_arg(&o->dir, &args, "--git-dir"))
|
||||
@ -274,34 +308,8 @@ static void parse_opts(struct opts *o, int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
/** Display diff output with "--numstat".*/
|
||||
static void diff_print_numstat(git_diff *diff)
|
||||
{
|
||||
git_patch *patch;
|
||||
const git_diff_delta *delta;
|
||||
size_t d, ndeltas = git_diff_num_deltas(diff);
|
||||
size_t nadditions, ndeletions;
|
||||
|
||||
for (d = 0; d < ndeltas; d++){
|
||||
check_lg2(
|
||||
git_patch_from_diff(&patch, diff, d),
|
||||
"generating patch from diff", NULL);
|
||||
|
||||
check_lg2(
|
||||
git_patch_line_stats(NULL, &nadditions, &ndeletions, patch),
|
||||
"generating the number of additions and deletions", NULL);
|
||||
|
||||
delta = git_patch_get_delta(patch);
|
||||
|
||||
printf("%ld\t%ld\t%s\n",
|
||||
(long)nadditions, (long)ndeletions, delta->new_file.path);
|
||||
|
||||
git_patch_free(patch);
|
||||
}
|
||||
}
|
||||
|
||||
/** Display diff output with "--shortstat".*/
|
||||
static void diff_print_shortstat(git_diff *diff)
|
||||
/** Display diff output with "--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);
|
||||
@ -320,26 +328,39 @@ static void diff_print_shortstat(git_diff *diff)
|
||||
git_patch_line_stats(NULL, &nadditions, &ndeletions, patch),
|
||||
"generating the number of additions and deletions", NULL);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
nadditions_sum += nadditions;
|
||||
ndeletions_sum += ndeletions;
|
||||
|
||||
git_patch_free(patch);
|
||||
}
|
||||
|
||||
if (ndeltas) {
|
||||
if (o->output != OUTPUT_NUMSTAT && ndeltas > 0) {
|
||||
printf(" %ld %s", (long)ndeltas,
|
||||
1 == ndeltas ? "file changed" : "files changed");
|
||||
|
||||
printf(" %ld ", (long)ndeltas);
|
||||
printf("%s", 1==ndeltas ? "file changed" : "files changed");
|
||||
|
||||
if(nadditions_sum) {
|
||||
printf(", %ld ",nadditions_sum);
|
||||
printf("%s", 1==nadditions_sum ? "insertion(+)" : "insertions(+)");
|
||||
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(-)");
|
||||
if (ndeletions_sum) {
|
||||
printf(", %ld ",ndeletions_sum);
|
||||
printf("%s", 1 == ndeletions_sum ? "deletion(-)" : "deletions(-)");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -725,24 +725,17 @@ GIT_EXTERN(int) git_diff_index_to_workdir(
|
||||
* The tree you provide will be used for the "old_file" side of the delta,
|
||||
* and the working directory will be used for the "new_file" side.
|
||||
*
|
||||
* Please note: this is *NOT* the same as `git diff <treeish>`. Running
|
||||
* `git diff HEAD` or the like actually uses information from the index,
|
||||
* along with the tree and working directory info.
|
||||
* This is not the same as `git diff <treeish>` or `git diff-index
|
||||
* <treeish>`. Those commands use information from the index, whereas this
|
||||
* function strictly returns the differences between the tree and the files
|
||||
* in the working directory, regardless of the state of the index. Use
|
||||
* `git_diff_tree_to_workdir_with_index` to emulate those commands.
|
||||
*
|
||||
* This function returns strictly the differences between the tree and the
|
||||
* files contained in the working directory, regardless of the state of
|
||||
* files in the index. It may come as a surprise, but there is no direct
|
||||
* equivalent in core git.
|
||||
*
|
||||
* To emulate `git diff <tree>`, use `git_diff_tree_to_workdir_with_index`
|
||||
* (or `git_diff_tree_to_index` and `git_diff_index_to_workdir`, then call
|
||||
* `git_diff_merge` on the results). That will yield a `git_diff` that
|
||||
* matches the git output.
|
||||
*
|
||||
* If this seems confusing, take the case of a file with a staged deletion
|
||||
* where the file has then been put back into the working dir and modified.
|
||||
* The tree-to-workdir diff for that file is 'modified', but core git would
|
||||
* show status 'deleted' since there is a pending deletion in the index.
|
||||
* To see difference between this and `git_diff_tree_to_workdir_with_index`,
|
||||
* consider the example of a staged file deletion where the file has then
|
||||
* been put back into the working dir and further modified. The
|
||||
* tree-to-workdir diff for that file is 'modified', but `git diff` would
|
||||
* show status 'deleted' since there is a staged delete.
|
||||
*
|
||||
* @param diff A pointer to a git_diff pointer that will be allocated.
|
||||
* @param repo The repository containing the tree.
|
||||
|
@ -175,7 +175,8 @@ static int diff_print_one_raw(
|
||||
git_oid_tostr(end_oid, pi->oid_strlen, &delta->new_file.id);
|
||||
|
||||
git_buf_printf(
|
||||
out, ":%06o %06o %s... %s... %c",
|
||||
out, (pi->oid_strlen <= GIT_OID_HEXSZ) ?
|
||||
":%06o %06o %s... %s... %c" : ":%06o %06o %s %s %c",
|
||||
delta->old_file.mode, delta->new_file.mode, start_oid, end_oid, code);
|
||||
|
||||
if (delta->similarity > 0)
|
||||
|
Loading…
Reference in New Issue
Block a user