#include "log-tree.h"
#include "builtin.h"
#include "string-list.h"
+#include "dir.h"
-static int read_directory(const char *path, struct string_list *list)
+static int read_directory_contents(const char *path, struct string_list *list)
{
DIR *dir;
struct dirent *e;
return error("Could not open directory %s", path);
while ((e = readdir(dir)))
- if (strcmp(".", e->d_name) && strcmp("..", e->d_name))
+ if (!is_dot_or_dotdot(e->d_name))
string_list_insert(list, e->d_name);
closedir(dir);
int i1, i2, ret = 0;
size_t len1 = 0, len2 = 0;
- if (name1 && read_directory(name1, &p1))
+ if (name1 && read_directory_contents(name1, &p1))
return -1;
- if (name2 && read_directory(name2, &p2)) {
+ if (name2 && read_directory_contents(name2, &p2)) {
string_list_clear(&p1, 0);
return -1;
}
}
}
+/* append basename of F to D */
+static void append_basename(struct strbuf *path, const char *dir, const char *file)
+{
+ const char *tail = strrchr(file, '/');
+
+ strbuf_addstr(path, dir);
+ while (path->len && path->buf[path->len - 1] == '/')
+ path->len--;
+ strbuf_addch(path, '/');
+ strbuf_addstr(path, tail ? tail + 1 : file);
+}
+
+/*
+ * DWIM "diff D F" into "diff D/F F" and "diff F D" into "diff F D/F"
+ * Note that we append the basename of F to D/, so "diff a/b/file D"
+ * becomes "diff a/b/file D/file", not "diff a/b/file D/a/b/file".
+ */
+static void fixup_paths(const char **path, struct strbuf *replacement)
+{
+ unsigned int isdir0, isdir1;
+
+ if (path[0] == file_from_standard_input ||
+ path[1] == file_from_standard_input)
+ return;
+ isdir0 = is_directory(path[0]);
+ isdir1 = is_directory(path[1]);
+ if (isdir0 == isdir1)
+ return;
+ if (isdir0) {
+ append_basename(replacement, path[0], path[1]);
+ path[0] = replacement->buf;
+ } else {
+ append_basename(replacement, path[1], path[0]);
+ path[1] = replacement->buf;
+ }
+}
+
void diff_no_index(struct rev_info *revs,
int argc, const char **argv,
const char *prefix)
{
int i, prefixlen;
- unsigned deprecated_show_diff_q_option_used = 0;
const char *paths[2];
+ struct strbuf replacement = STRBUF_INIT;
diff_setup(&revs->diffopt);
for (i = 1; i < argc - 2; ) {
int j;
if (!strcmp(argv[i], "--no-index"))
i++;
- else if (!strcmp(argv[i], "-q")) {
- deprecated_show_diff_q_option_used = 1;
- i++;
- }
else if (!strcmp(argv[i], "--"))
i++;
else {
p = xstrdup(prefix_filename(prefix, prefixlen, p));
paths[i] = p;
}
+
+ fixup_paths(paths, &replacement);
+
revs->diffopt.skip_stat_unmatch = 1;
if (!revs->diffopt.output_format)
revs->diffopt.output_format = DIFF_FORMAT_PATCH;
revs->max_count = -2;
diff_setup_done(&revs->diffopt);
- if (deprecated_show_diff_q_option_used)
- handle_deprecated_show_diff_q(&revs->diffopt);
-
setup_diff_pager(&revs->diffopt);
DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
+ strbuf_release(&replacement);
+
/*
* The return code for --no-index imitates diff(1):
* 0 = no changes, 1 = changes, else error