}
/*
* 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.
+ * specified rev.max_count is reasonable (0 <= n <= 3), and
+ * there is no other revision filtering parameter.
*/
if (revs->pending_objects ||
revs->min_age != -1 ||
- revs->max_age != -1)
+ revs->max_age != -1 ||
+ 3 < revs->max_count)
usage(builtin_diff_usage);
+ if (revs->max_count < 0 &&
+ (revs->diffopt.output_format == DIFF_FORMAT_PATCH))
+ revs->combine_merges = revs->dense_combined_merges = 1;
/*
* Backward compatibility wart - "diff-files -s" used to
* defeat the common diff option "-s" which asked for
if (opt->reverse_diff) {
unsigned tmp;
- const
- const unsigned char *tmp_u;
+ const unsigned char *tmp_u;
const char *tmp_c;
tmp = old_mode; old_mode = new_mode; new_mode = tmp;
tmp_u = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_u;
stuff_change(&revs->diffopt,
canon_mode(st.st_mode), canon_mode(st.st_mode),
blob[0].sha1, null_sha1,
- blob[0].name, path);
+ path, path);
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
return 0;
int argc, const char **argv,
struct blobinfo *blob)
{
- /* Blobs */
+ /* Blobs: the arguments are reversed when setup_revisions()
+ * picked them up.
+ */
unsigned mode = canon_mode(S_IFREG | 0644);
while (1 < argc) {
}
stuff_change(&revs->diffopt,
mode, mode,
- blob[0].sha1, blob[1].sha1,
- blob[1].name, blob[1].name);
+ blob[1].sha1, blob[0].sha1,
+ blob[0].name, blob[0].name);
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
return 0;
int argc, const char **argv,
struct object_list *ent)
{
- /* We saw two trees, ent[0] and ent[1].
- * unless ent[0] is unintesting, they are swapped
- */
const unsigned char *(sha1[2]);
int swap = 1;
while (1 < argc) {
usage(builtin_diff_usage);
argv++; argc--;
}
+
+ /* We saw two trees, ent[0] and ent[1].
+ * unless ent[0] is unintesting, they are swapped
+ */
if (ent[0].item->flags & UNINTERESTING)
swap = 0;
sha1[swap] = ent[0].item->sha1;
return 0;
}
-static void add_head(struct rev_info *revs)
+static int builtin_diff_combined(struct rev_info *revs,
+ int argc, const char **argv,
+ struct object_list *ent,
+ int ents)
+{
+ const unsigned char (*parent)[20];
+ int i;
+
+ while (1 < argc) {
+ const char *arg = argv[1];
+ if (!strcmp(arg, "--raw"))
+ revs->diffopt.output_format = DIFF_FORMAT_RAW;
+ else
+ usage(builtin_diff_usage);
+ argv++; argc--;
+ }
+ if (!revs->dense_combined_merges && !revs->combine_merges)
+ revs->dense_combined_merges = revs->combine_merges = 1;
+ parent = xmalloc(ents * sizeof(*parent));
+ /* Again, the revs are all reverse */
+ for (i = 0; i < ents; i++)
+ memcpy(parent + i, ent[ents - 1 - i].item->sha1, 20);
+ diff_tree_combined(parent[0], parent + 1, ents - 1,
+ revs->dense_combined_merges, revs);
+ return 0;
+}
+
+void add_head(struct rev_info *revs)
{
unsigned char sha1[20];
struct object *obj;
int cmd_diff(int argc, const char **argv, char **envp)
{
struct rev_info rev;
- struct object_list *list, ent[2];
+ struct object_list *list, ent[100];
int ents = 0, blobs = 0, paths = 0;
const char *path = NULL;
struct blobinfo blob[2];
*
* Other cases are errors.
*/
-
+
git_config(git_diff_config);
init_revisions(&rev);
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
if (!strcmp(obj->type, commit_type))
obj = &((struct commit *)obj)->tree->object;
if (!strcmp(obj->type, tree_type)) {
- if (2 <= ents)
- die("more than two trees given: '%s'", name);
+ if (ARRAY_SIZE(ent) <= ents)
+ die("more than %d trees given: '%s'",
+ (int) ARRAY_SIZE(ent), name);
obj->flags |= flags;
ent[ents].item = obj;
ent[ents].name = name;
blob[blobs].name = name;
blobs++;
continue;
-
+
}
die("unhandled object '%s' given.", name);
}
return builtin_diff_b_f(&rev, argc, argv, blob, path);
break;
case 2:
+ if (paths)
+ usage(builtin_diff_usage);
return builtin_diff_blobs(&rev, argc, argv, blob);
break;
default:
return builtin_diff_index(&rev, argc, argv);
else if (ents == 2)
return builtin_diff_tree(&rev, argc, argv, ent);
+ else
+ return builtin_diff_combined(&rev, argc, argv, ent, ents);
usage(builtin_diff_usage);
}