Browse Source

Libify diff-files.

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>
maint
Junio C Hamano 19 years ago
parent
commit
6973dcaee7
  1. 2
      Makefile
  2. 212
      diff-files.c
  3. 1862
      diff-lib.c
  4. 1795
      diff.c
  5. 7
      diff.h
  6. 2
      t/t1001-read-tree-m-2way.sh
  7. 2
      t/t1002-read-tree-m-u-2way.sh

2
Makefile

@ -199,7 +199,7 @@ LIB_H = \ @@ -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


212
diff-files.c

@ -12,203 +12,43 @@ static const char diff_files_usage[] = @@ -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);
}

1862
diff-lib.c

File diff suppressed because it is too large Load Diff

1795
diff.c

File diff suppressed because it is too large Load Diff

7
diff.h

@ -28,10 +28,11 @@ struct diff_options { @@ -28,10 +28,11 @@ struct diff_options {
with_raw:1,
with_stat:1,
tree_in_recursive:1,
full_index:1;
full_index:1,
silent_on_remove:1,
find_copies_harder:1;
int break_opt;
int detect_rename;
int find_copies_harder;
int line_termination;
int output_format;
int pickaxe_opts;
@ -168,4 +169,6 @@ extern void diff_flush(struct diff_options*); @@ -168,4 +169,6 @@ extern void diff_flush(struct diff_options*);

extern const char *diff_unique_abbrev(const unsigned char *, int);

extern int run_diff_files(struct rev_info *revs, int silent_on_removed);

#endif /* DIFF_H */

2
t/t1001-read-tree-m-2way.sh

@ -37,7 +37,7 @@ compare_change () { @@ -37,7 +37,7 @@ compare_change () {
}

check_cache_at () {
clean_if_empty=`git-diff-files "$1"`
clean_if_empty=`git-diff-files -- "$1"`
case "$clean_if_empty" in
'') echo "$1: clean" ;;
?*) echo "$1: dirty" ;;

2
t/t1002-read-tree-m-u-2way.sh

@ -20,7 +20,7 @@ compare_change () { @@ -20,7 +20,7 @@ compare_change () {
}

check_cache_at () {
clean_if_empty=`git-diff-files "$1"`
clean_if_empty=`git-diff-files -- "$1"`
case "$clean_if_empty" in
'') echo "$1: clean" ;;
?*) echo "$1: dirty" ;;

Loading…
Cancel
Save