Skip to content

Commit

Permalink
Libify diff-files.
Browse files Browse the repository at this point in the history
This is the first installment to libify diff brothers.

The updated diff-files uses revision.c::setup_revisions()
infrastructure to parse its command line arguments, which means
the pathname arguments are checked more strictly than before.
The tests are adjusted to separate possibly missing paths from
the rest of arguments with double-dashes, to show the kosher
way.

As Linus pointed out, renaming diff.c to diff-lib.c was simply
stupid, so I am renaming it back.  The new diff-lib.c is to
contain pieces extracted from diff brothers.

Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
Junio C Hamano committed Apr 22, 2006
1 parent e64961b commit 6973dca
Show file tree
Hide file tree
Showing 7 changed files with 1,929 additions and 1,953 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ LIB_H = \
tree-walk.h log-tree.h

DIFF_OBJS = \
diff-lib.o diffcore-break.o diffcore-order.o \
diff.o diff-lib.o diffcore-break.o diffcore-order.o \
diffcore-pickaxe.o diffcore-rename.o tree-diff.o combine-diff.o \
diffcore-delta.o log-tree.o

Expand Down
212 changes: 26 additions & 186 deletions diff-files.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,203 +12,43 @@ static const char diff_files_usage[] =
"git-diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]"
COMMON_DIFF_OPTIONS_HELP;

static struct rev_info rev;
static int silent = 0;
static int diff_unmerged_stage = 2;
static int combine_merges = 0;
static int dense_combined_merges = 0;

static void show_unmerge(const char *path)
{
diff_unmerge(&rev.diffopt, path);
}

static void show_file(int pfx, struct cache_entry *ce)
{
diff_addremove(&rev.diffopt, pfx, ntohl(ce->ce_mode),
ce->sha1, ce->name, NULL);
}

static void show_modified(int oldmode, int mode,
const unsigned char *old_sha1, const unsigned char *sha1,
char *path)
{
diff_change(&rev.diffopt, oldmode, mode, old_sha1, sha1, path, NULL);
}

int main(int argc, const char **argv)
{
const char **pathspec;
const char *prefix = setup_git_directory();
int entries, i;
struct rev_info rev;
int silent = 0;

git_config(git_diff_config);
diff_setup(&rev.diffopt);
init_revisions(&rev);
rev.abbrev = 0;

argc = setup_revisions(argc, argv, &rev, NULL);
while (1 < argc && argv[1][0] == '-') {
if (!strcmp(argv[1], "--")) {
argv++;
argc--;
break;
}
if (!strcmp(argv[1], "-0"))
diff_unmerged_stage = 0;
else if (!strcmp(argv[1], "-1"))
diff_unmerged_stage = 1;
else if (!strcmp(argv[1], "-2"))
diff_unmerged_stage = 2;
else if (!strcmp(argv[1], "-3"))
diff_unmerged_stage = 3;
else if (!strcmp(argv[1], "--base"))
diff_unmerged_stage = 1;
if (!strcmp(argv[1], "--base"))
rev.max_count = 1;
else if (!strcmp(argv[1], "--ours"))
diff_unmerged_stage = 2;
rev.max_count = 2;
else if (!strcmp(argv[1], "--theirs"))
diff_unmerged_stage = 3;
rev.max_count = 3;
else if (!strcmp(argv[1], "-q"))
silent = 1;
else if (!strcmp(argv[1], "-r"))
; /* no-op */
else if (!strcmp(argv[1], "-s"))
; /* no-op */
else if (!strcmp(argv[1], "-c"))
combine_merges = 1;
else if (!strcmp(argv[1], "--cc"))
dense_combined_merges = combine_merges = 1;
else {
int diff_opt_cnt;
diff_opt_cnt = diff_opt_parse(&rev.diffopt,
argv+1, argc-1);
if (diff_opt_cnt < 0)
usage(diff_files_usage);
else if (diff_opt_cnt) {
argv += diff_opt_cnt;
argc -= diff_opt_cnt;
continue;
}
else
usage(diff_files_usage);
}
else
usage(diff_files_usage);
argv++; argc--;
}
if (dense_combined_merges)
rev.diffopt.output_format = DIFF_FORMAT_PATCH;

/* Find the directory, and set up the pathspec */
pathspec = get_pathspec(prefix, argv + 1);
entries = read_cache();

if (diff_setup_done(&rev.diffopt) < 0)
/*
* Make sure there are NO revision (i.e. pending object) parameter,
* rev.max_count is reasonable (0 <= n <= 3),
* there is no other revision filtering parameters.
*/
if (rev.pending_objects ||
rev.min_age != -1 || rev.max_age != -1)
usage(diff_files_usage);

/* At this point, if argc == 1, then we are doing everything.
* Otherwise argv[1] .. argv[argc-1] have the explicit paths.
/*
* Backward compatibility wart - "diff-files -s" used to
* defeat the common diff option "-s" which asked for
* DIFF_FORMAT_NO_OUTPUT.
*/
if (entries < 0) {
perror("read_cache");
exit(1);
}

for (i = 0; i < entries; i++) {
struct stat st;
unsigned int oldmode, newmode;
struct cache_entry *ce = active_cache[i];
int changed;

if (!ce_path_match(ce, pathspec))
continue;

if (ce_stage(ce)) {
struct {
struct combine_diff_path p;
struct combine_diff_parent filler[5];
} combine;
int num_compare_stages = 0;

combine.p.next = NULL;
combine.p.len = ce_namelen(ce);
combine.p.path = xmalloc(combine.p.len + 1);
memcpy(combine.p.path, ce->name, combine.p.len);
combine.p.path[combine.p.len] = 0;
combine.p.mode = 0;
memset(combine.p.sha1, 0, 20);
memset(&combine.p.parent[0], 0,
sizeof(combine.filler));

while (i < entries) {
struct cache_entry *nce = active_cache[i];
int stage;

if (strcmp(ce->name, nce->name))
break;

/* Stage #2 (ours) is the first parent,
* stage #3 (theirs) is the second.
*/
stage = ce_stage(nce);
if (2 <= stage) {
int mode = ntohl(nce->ce_mode);
num_compare_stages++;
memcpy(combine.p.parent[stage-2].sha1,
nce->sha1, 20);
combine.p.parent[stage-2].mode =
canon_mode(mode);
combine.p.parent[stage-2].status =
DIFF_STATUS_MODIFIED;
}

/* diff against the proper unmerged stage */
if (stage == diff_unmerged_stage)
ce = nce;
i++;
}
/*
* Compensate for loop update
*/
i--;

if (combine_merges && num_compare_stages == 2) {
show_combined_diff(&combine.p, 2,
dense_combined_merges,
&rev);
free(combine.p.path);
continue;
}
free(combine.p.path);

/*
* Show the diff for the 'ce' if we found the one
* from the desired stage.
*/
show_unmerge(ce->name);
if (ce_stage(ce) != diff_unmerged_stage)
continue;
}

if (lstat(ce->name, &st) < 0) {
if (errno != ENOENT && errno != ENOTDIR) {
perror(ce->name);
continue;
}
if (silent)
continue;
show_file('-', ce);
continue;
}
changed = ce_match_stat(ce, &st, 0);
if (!changed && !rev.diffopt.find_copies_harder)
continue;
oldmode = ntohl(ce->ce_mode);

newmode = canon_mode(st.st_mode);
if (!trust_executable_bit &&
S_ISREG(newmode) && S_ISREG(oldmode) &&
((newmode ^ oldmode) == 0111))
newmode = oldmode;
show_modified(oldmode, newmode,
ce->sha1, (changed ? null_sha1 : ce->sha1),
ce->name);
}
diffcore_std(&rev.diffopt);
diff_flush(&rev.diffopt);
return 0;
if (rev.diffopt.output_format == DIFF_FORMAT_NO_OUTPUT)
rev.diffopt.output_format = DIFF_FORMAT_RAW;
return run_diff_files(&rev, silent);
}
Loading

0 comments on commit 6973dca

Please sign in to comment.