#include "diffcore.h"
static const char *diff_opts = "-pu";
-static unsigned char null_sha1[20] = { 0, };
static int use_size_cache;
static void prep_temp_blob(struct diff_tempfile *temp,
void *blob,
unsigned long size,
- unsigned char *sha1,
+ const unsigned char *sha1,
int mode)
{
int fd;
remove_tempfile();
}
+static void diff_fill_sha1_info(struct diff_filespec *one)
+{
+ if (DIFF_FILE_VALID(one)) {
+ if (!one->sha1_valid) {
+ struct stat st;
+ if (stat(one->path, &st) < 0)
+ die("stat %s", one->path);
+ if (index_path(one->sha1, one->path, &st, 0))
+ die("cannot hash %s\n", one->path);
+ }
+ }
+ else
+ memset(one->sha1, 0, 20);
+}
+
static void run_diff(struct diff_filepair *p)
{
const char *pgm = external_diff();
- char msg_[PATH_MAX*2+200], *xfrm_msg;
+ char msg[PATH_MAX*2+300], *xfrm_msg;
struct diff_filespec *one;
struct diff_filespec *two;
const char *name;
const char *other;
int complete_rewrite = 0;
+ int len;
if (DIFF_PAIR_UNMERGED(p)) {
/* unmerged */
name = p->one->path;
other = (strcmp(name, p->two->path) ? p->two->path : NULL);
one = p->one; two = p->two;
+
+ diff_fill_sha1_info(one);
+ diff_fill_sha1_info(two);
+
+ len = 0;
switch (p->status) {
case DIFF_STATUS_COPIED:
- sprintf(msg_,
- "similarity index %d%%\n"
- "copy from %s\n"
- "copy to %s",
- (int)(0.5 + p->score * 100.0/MAX_SCORE),
- name, other);
- xfrm_msg = msg_;
+ len += snprintf(msg + len, sizeof(msg) - len,
+ "similarity index %d%%\n"
+ "copy from %s\n"
+ "copy to %s\n",
+ (int)(0.5 + p->score * 100.0/MAX_SCORE),
+ name, other);
break;
case DIFF_STATUS_RENAMED:
- sprintf(msg_,
- "similarity index %d%%\n"
- "rename from %s\n"
- "rename to %s",
- (int)(0.5 + p->score * 100.0/MAX_SCORE),
- name, other);
- xfrm_msg = msg_;
+ len += snprintf(msg + len, sizeof(msg) - len,
+ "similarity index %d%%\n"
+ "rename from %s\n"
+ "rename to %s\n",
+ (int)(0.5 + p->score * 100.0/MAX_SCORE),
+ name, other);
break;
case DIFF_STATUS_MODIFIED:
if (p->score) {
- sprintf(msg_,
- "dissimilarity index %d%%",
- (int)(0.5 + p->score * 100.0/MAX_SCORE));
- xfrm_msg = msg_;
+ len += snprintf(msg + len, sizeof(msg) - len,
+ "dissimilarity index %d%%\n",
+ (int)(0.5 + p->score *
+ 100.0/MAX_SCORE));
complete_rewrite = 1;
break;
}
/* fallthru */
default:
- xfrm_msg = NULL;
+ /* nothing */
+ ;
+ }
+
+ if (memcmp(one->sha1, two->sha1, 20)) {
+ char one_sha1[41];
+ memcpy(one_sha1, sha1_to_hex(one->sha1), 41);
+
+ len += snprintf(msg + len, sizeof(msg) - len,
+ "index %.7s..%.7s", one_sha1,
+ sha1_to_hex(two->sha1));
+ if (one->mode == two->mode)
+ len += snprintf(msg + len, sizeof(msg) - len,
+ " %06o", one->mode);
+ len += snprintf(msg + len, sizeof(msg) - len, "\n");
}
+ if (len)
+ msg[--len] = 0;
+ xfrm_msg = len ? msg : NULL;
+
if (!pgm &&
DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) &&
(S_IFMT & one->mode) != (S_IFMT & two->mode)) {
options->output_format = DIFF_FORMAT_RAW;
options->line_termination = '\n';
options->break_opt = -1;
+ options->rename_limit = -1;
}
int diff_setup_done(struct diff_options *options)
{
- if (options->find_copies_harder &&
+ if ((options->find_copies_harder || 0 <= options->rename_limit) &&
options->detect_rename != DIFF_DETECT_COPY)
return -1;
if (options->setup & DIFF_SETUP_USE_CACHE) {
options->output_format = DIFF_FORMAT_PATCH;
else if (!strcmp(arg, "-z"))
options->line_termination = 0;
+ else if (!strncmp(arg, "-l", 2))
+ options->rename_limit = strtoul(arg+2, NULL, 10);
else if (!strcmp(arg, "--name-only"))
options->output_format = DIFF_FORMAT_NAME;
+ else if (!strcmp(arg, "--name-status"))
+ options->output_format = DIFF_FORMAT_NAME_STATUS;
else if (!strcmp(arg, "-R"))
options->reverse_diff = 1;
else if (!strncmp(arg, "-S", 2))
static void diff_flush_raw(struct diff_filepair *p,
int line_termination,
- int inter_name_termination)
+ int inter_name_termination,
+ int output_format)
{
int two_paths;
char status[10];
two_paths = 0;
break;
}
- printf(":%06o %06o %s ",
- p->one->mode, p->two->mode, sha1_to_hex(p->one->sha1));
- printf("%s %s%c%s",
- sha1_to_hex(p->two->sha1),
- status,
- inter_name_termination,
- p->one->path);
+ if (output_format != DIFF_FORMAT_NAME_STATUS) {
+ printf(":%06o %06o %s ",
+ p->one->mode, p->two->mode, sha1_to_hex(p->one->sha1));
+ printf("%s ", sha1_to_hex(p->two->sha1));
+ }
+ printf("%s%c%s",status, inter_name_termination, p->one->path);
if (two_paths)
printf("%c%s", inter_name_termination, p->two->path);
putchar(line_termination);
diff_flush_patch(p);
break;
case DIFF_FORMAT_RAW:
+ case DIFF_FORMAT_NAME_STATUS:
diff_flush_raw(p, line_termination,
- inter_name_termination);
+ inter_name_termination,
+ diff_output_format);
break;
case DIFF_FORMAT_NAME:
diff_flush_name(p, line_termination);
if (options->break_opt != -1)
diffcore_break(options->break_opt);
if (options->detect_rename)
- diffcore_rename(options->detect_rename, options->rename_score);
+ diffcore_rename(options);
if (options->break_opt != -1)
diffcore_merge_broken();
if (options->pickaxe)