mirror of
https://github.com/git/git
synced 2024-08-25 02:35:46 +00:00
![Linus Torvalds](/assets/img/avatar_default.png)
We always show the diff as an absolute path, but pathnames to diff are taken relative to the current working directory (and if no pathnames are given, the default ends up being all of the current working directory). Note that "../xyz" also works, so you can do cd linux/drivers/char git diff ../block and it will generate a diff of the linux/drivers/block changes. Signed-off-by: Linus Torvalds <torvalds@osdl.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
159 lines
4.1 KiB
C
159 lines
4.1 KiB
C
/*
|
|
* GIT - The information manager from hell
|
|
*
|
|
* Copyright (C) Linus Torvalds, 2005
|
|
*/
|
|
#include "cache.h"
|
|
#include "diff.h"
|
|
|
|
static const char diff_files_usage[] =
|
|
"git-diff-files [-q] "
|
|
"[<common diff options>] [<path>...]"
|
|
COMMON_DIFF_OPTIONS_HELP;
|
|
|
|
static int diff_output_format = DIFF_FORMAT_RAW;
|
|
static int diff_line_termination = '\n';
|
|
static int detect_rename = 0;
|
|
static int find_copies_harder = 0;
|
|
static int diff_setup_opt = 0;
|
|
static int diff_score_opt = 0;
|
|
static const char *pickaxe = NULL;
|
|
static int pickaxe_opts = 0;
|
|
static int diff_break_opt = -1;
|
|
static const char *orderfile = NULL;
|
|
static const char *diff_filter = NULL;
|
|
static int silent = 0;
|
|
|
|
static void show_unmerge(const char *path)
|
|
{
|
|
diff_unmerge(path);
|
|
}
|
|
|
|
static void show_file(int pfx, struct cache_entry *ce)
|
|
{
|
|
diff_addremove(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(oldmode, mode, old_sha1, sha1, path, NULL);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
static const unsigned char null_sha1[20] = { 0, };
|
|
const char **pathspec;
|
|
const char *prefix = setup_git_directory();
|
|
int entries, i;
|
|
|
|
while (1 < argc && argv[1][0] == '-') {
|
|
if (!strcmp(argv[1], "-p") || !strcmp(argv[1], "-u"))
|
|
diff_output_format = DIFF_FORMAT_PATCH;
|
|
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], "-z"))
|
|
diff_line_termination = 0;
|
|
else if (!strcmp(argv[1], "--name-only"))
|
|
diff_output_format = DIFF_FORMAT_NAME;
|
|
else if (!strcmp(argv[1], "-R"))
|
|
diff_setup_opt |= DIFF_SETUP_REVERSE;
|
|
else if (!strncmp(argv[1], "-S", 2))
|
|
pickaxe = argv[1] + 2;
|
|
else if (!strncmp(argv[1], "-O", 2))
|
|
orderfile = argv[1] + 2;
|
|
else if (!strncmp(argv[1], "--diff-filter=", 14))
|
|
diff_filter = argv[1] + 14;
|
|
else if (!strcmp(argv[1], "--pickaxe-all"))
|
|
pickaxe_opts = DIFF_PICKAXE_ALL;
|
|
else if (!strncmp(argv[1], "-B", 2)) {
|
|
if ((diff_break_opt =
|
|
diff_scoreopt_parse(argv[1])) == -1)
|
|
usage(diff_files_usage);
|
|
}
|
|
else if (!strncmp(argv[1], "-M", 2)) {
|
|
if ((diff_score_opt =
|
|
diff_scoreopt_parse(argv[1])) == -1)
|
|
usage(diff_files_usage);
|
|
detect_rename = DIFF_DETECT_RENAME;
|
|
}
|
|
else if (!strncmp(argv[1], "-C", 2)) {
|
|
if ((diff_score_opt =
|
|
diff_scoreopt_parse(argv[1])) == -1)
|
|
usage(diff_files_usage);
|
|
detect_rename = DIFF_DETECT_COPY;
|
|
}
|
|
else if (!strcmp(argv[1], "--find-copies-harder"))
|
|
find_copies_harder = 1;
|
|
else
|
|
usage(diff_files_usage);
|
|
argv++; argc--;
|
|
}
|
|
|
|
/* Find the directory, and set up the pathspec */
|
|
pathspec = get_pathspec(prefix, argv + 1);
|
|
entries = read_cache();
|
|
|
|
if (find_copies_harder && detect_rename != DIFF_DETECT_COPY)
|
|
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.
|
|
*/
|
|
if (entries < 0) {
|
|
perror("read_cache");
|
|
exit(1);
|
|
}
|
|
|
|
diff_setup(diff_setup_opt);
|
|
|
|
for (i = 0; i < entries; i++) {
|
|
struct stat st;
|
|
unsigned int oldmode;
|
|
struct cache_entry *ce = active_cache[i];
|
|
int changed;
|
|
|
|
if (!ce_path_match(ce, pathspec))
|
|
continue;
|
|
|
|
if (ce_stage(ce)) {
|
|
show_unmerge(ce->name);
|
|
while (i < entries &&
|
|
!strcmp(ce->name, active_cache[i]->name))
|
|
i++;
|
|
i--; /* compensate for loop control increments */
|
|
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);
|
|
if (!changed && !find_copies_harder)
|
|
continue;
|
|
oldmode = ntohl(ce->ce_mode);
|
|
show_modified(oldmode, DIFF_FILE_CANON_MODE(st.st_mode),
|
|
ce->sha1, (changed ? null_sha1 : ce->sha1),
|
|
ce->name);
|
|
}
|
|
diffcore_std(pathspec,
|
|
detect_rename, diff_score_opt,
|
|
pickaxe, pickaxe_opts,
|
|
diff_break_opt,
|
|
orderfile, diff_filter);
|
|
diff_flush(diff_output_format, diff_line_termination);
|
|
return 0;
|
|
}
|