* [PATCH] Teach git-diff{,-files} the new option `--no-index`
@ 2007-02-20 18:46 Johannes Schindelin
2007-02-22 10:36 ` Junio C Hamano
0 siblings, 1 reply; 13+ messages in thread
From: Johannes Schindelin @ 2007-02-20 18:46 UTC (permalink / raw)
To: git, junkio
With this flag and given two paths, git-diff-files behaves as a GNU diff
lookalike (plus the git goodies like --check, colour, etc.). This flag
is also available in git-diff. It also works outside of a git repository.
In addition, if git-diff{,-files} is called without revision or stage
parameter, and with exactly two paths at least one of which is not tracked,
the default is --no-index.
This also unifies the duplicated argument parsing between cmd_diff_files()
and builtin_diff_files().
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
Is this better than diff2 or what?
This patch is only weakly tested; basically it passes `make test`.
Documentation/git-diff-files.txt | 5 +-
Documentation/git-diff.txt | 4 +
builtin-diff-files.c | 29 +-----
builtin-diff.c | 38 +-------
diff-lib.c | 207 +++++++++++++++++++++++++++++++++++++-
diff.c | 3 +-
diff.h | 2 +-
git.c | 4 +-
wt-status.c | 2 +-
9 files changed, 226 insertions(+), 68 deletions(-)
diff --git a/Documentation/git-diff-files.txt b/Documentation/git-diff-files.txt
index 7248b35..b78c4c6 100644
--- a/Documentation/git-diff-files.txt
+++ b/Documentation/git-diff-files.txt
@@ -8,7 +8,7 @@ git-diff-files - Compares files in the working tree and the index
SYNOPSIS
--------
-'git-diff-files' [-q] [-0|-1|-2|-3|-c|--cc] [<common diff options>] [<path>...]
+'git-diff-files' [-q] [-0|-1|-2|-3|-c|--cc|-n|--no-index] [<common diff options>] [<path>...]
DESCRIPTION
-----------
@@ -36,6 +36,9 @@ omit diff output for unmerged entries and just show "Unmerged".
diff, similar to the way 'diff-tree' shows a merge
commit with these flags.
+\-n,\--no-index::
+ Compare the two given files / directories.
+
-q::
Remain silent even on nonexistent files
diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt
index 6a098df..12a531d 100644
--- a/Documentation/git-diff.txt
+++ b/Documentation/git-diff.txt
@@ -23,6 +23,10 @@ tree and the index file, or the index file and the working tree.
further add to the index but you still haven't. You can
stage these changes by using gitlink:git-add[1].
+ If exactly two paths are given, and at least one is untracked,
+ compare the two files / directories. This behavior can be
+ forced by --no-index.
+
'git-diff' [--options] --cached [<commit>] [--] [<path>...]::
This form is to view the changes you staged for the next
diff --git a/builtin-diff-files.c b/builtin-diff-files.c
index 5d4a5c5..8d78dfa 100644
--- a/builtin-diff-files.c
+++ b/builtin-diff-files.c
@@ -10,42 +10,21 @@
#include "builtin.h"
static const char diff_files_usage[] =
-"git-diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]"
+"git-diff-files [-q] [-0/-1/2/3 |-c|--cc|-n|--no-index] [<common diff options>] [<path>...]"
COMMON_DIFF_OPTIONS_HELP;
int cmd_diff_files(int argc, const char **argv, const char *prefix)
{
struct rev_info rev;
- int silent = 0;
+ int nongit = 0;
+ prefix = setup_git_directory_gently(&nongit);
init_revisions(&rev, prefix);
git_config(git_default_config); /* no "diff" UI options */
rev.abbrev = 0;
argc = setup_revisions(argc, argv, &rev, NULL);
- while (1 < argc && argv[1][0] == '-') {
- if (!strcmp(argv[1], "--base"))
- rev.max_count = 1;
- else if (!strcmp(argv[1], "--ours"))
- rev.max_count = 2;
- else if (!strcmp(argv[1], "--theirs"))
- rev.max_count = 3;
- else if (!strcmp(argv[1], "-q"))
- silent = 1;
- else
- usage(diff_files_usage);
- argv++; argc--;
- }
if (!rev.diffopt.output_format)
rev.diffopt.output_format = DIFF_FORMAT_RAW;
-
- /*
- * 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.nr ||
- rev.min_age != -1 || rev.max_age != -1)
- usage(diff_files_usage);
- return run_diff_files(&rev, silent);
+ return run_diff_files(&rev, argc, argv);
}
diff --git a/builtin-diff.c b/builtin-diff.c
index a659020..9334589 100644
--- a/builtin-diff.c
+++ b/builtin-diff.c
@@ -25,40 +25,6 @@ struct blobinfo {
static const char builtin_diff_usage[] =
"git-diff <options> <rev>{0,2} -- <path>*";
-static int builtin_diff_files(struct rev_info *revs,
- int argc, const char **argv)
-{
- int silent = 0;
- while (1 < argc) {
- const char *arg = argv[1];
- if (!strcmp(arg, "--base"))
- revs->max_count = 1;
- else if (!strcmp(arg, "--ours"))
- revs->max_count = 2;
- else if (!strcmp(arg, "--theirs"))
- revs->max_count = 3;
- else if (!strcmp(arg, "-q"))
- silent = 1;
- else
- usage(builtin_diff_usage);
- argv++; argc--;
- }
- /*
- * Make sure there are NO revision (i.e. pending object) parameter,
- * specified rev.max_count is reasonable (0 <= n <= 3), and
- * there is no other revision filtering parameter.
- */
- if (revs->pending.nr ||
- revs->min_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;
- return run_diff_files(revs, silent);
-}
-
static void stuff_change(struct diff_options *opt,
unsigned old_mode, unsigned new_mode,
const unsigned char *old_sha1,
@@ -218,6 +184,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
int ents = 0, blobs = 0, paths = 0;
const char *path = NULL;
struct blobinfo blob[2];
+ int nongit = 0;
/*
* We could get N tree-ish in the rev.pending_objects list.
@@ -239,6 +206,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
* Other cases are errors.
*/
+ prefix = setup_git_directory_gently(&nongit);
git_config(git_diff_ui_config);
init_revisions(&rev, prefix);
@@ -314,7 +282,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
if (!ents) {
switch (blobs) {
case 0:
- return builtin_diff_files(&rev, argc, argv);
+ return run_diff_files(&rev, argc, argv);
break;
case 1:
if (paths != 1)
diff --git a/diff-lib.c b/diff-lib.c
index 556d534..83d6682 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -8,15 +8,218 @@
#include "diffcore.h"
#include "revision.h"
#include "cache-tree.h"
+#include "path-list.h"
/*
* diff-files
*/
-int run_diff_files(struct rev_info *revs, int silent_on_removed)
+static int read_directory(const char *path, struct path_list *list)
+{
+ DIR *dir;
+ struct dirent *e;
+
+ if (!(dir = opendir(path)))
+ return error("Could not open directory %s", path);
+
+ while ((e = readdir(dir)))
+ if (strcmp(".", e->d_name) && strcmp("..", e->d_name))
+ path_list_insert(xstrdup(e->d_name), list);
+
+ closedir(dir);
+ return 0;
+}
+
+static int queue_diff(struct diff_options *o,
+ const char *name1, const char *name2)
+{
+ struct stat st;
+ int mode1 = 0, mode2 = 0;
+
+ if (name1) {
+ if (stat(name1, &st))
+ return error("Could not access '%s'", name1);
+ mode1 = st.st_mode;
+ }
+ if (name2) {
+ if (stat(name2, &st))
+ return error("Could not access '%s'", name1);
+ mode2 = st.st_mode;
+ }
+
+ if (mode1 && mode2 && S_ISDIR(mode1) != S_ISDIR(mode2))
+ return error("file/directory conflict: %s, %s", name1, name2);
+
+ if (S_ISDIR(mode1) || S_ISDIR(mode2)) {
+ char buffer1[PATH_MAX], buffer2[PATH_MAX];
+ struct path_list p1 = {NULL, 0, 0, 1}, p2 = {NULL, 0, 0, 1};
+ int len1 = 0, len2 = 0, i1, i2, ret = 0;
+
+ if (name1 && read_directory(name1, &p1))
+ return -1;
+ if (name2 && read_directory(name2, &p2)) {
+ path_list_clear(&p1, 0);
+ return -1;
+ }
+
+ if (name1) {
+ len1 = strlen(name1);
+ if (len1 > 0 && name1[len1 - 1] == '/')
+ len1--;
+ memcpy(buffer1, name1, len1);
+ buffer1[len1++] = '/';
+ }
+
+ if (name2) {
+ len2 = strlen(name2);
+ if (len2 > 0 && name2[len2 - 1] == '/')
+ len2--;
+ memcpy(buffer2, name2, len2);
+ buffer2[len2++] = '/';
+ }
+
+ for (i1 = i2 = 0; !ret && (i1 < p1.nr || i2 < p2.nr); ) {
+ const char *n1, *n2;
+ int comp;
+
+ if (i1 == p1.nr)
+ comp = 1;
+ else if (i2 == p2.nr)
+ comp = -1;
+ else
+ comp = strcmp(p1.items[i1].path,
+ p2.items[i2].path);
+
+ if (comp > 0)
+ n1 = NULL;
+ else {
+ n1 = buffer1;
+ strncpy(buffer1 + len1, p1.items[i1++].path,
+ PATH_MAX - len1);
+ }
+
+ if (comp < 0)
+ n2 = NULL;
+ else {
+ n2 = buffer2;
+ strncpy(buffer2 + len2, p2.items[i2++].path,
+ PATH_MAX - len2);
+ }
+
+ ret = queue_diff(o, n1, n2);
+ }
+ path_list_clear(&p1, 0);
+ path_list_clear(&p2, 0);
+
+ return ret;
+ } else {
+ struct diff_filespec *d1, *d2;
+
+ if (o->reverse_diff) {
+ unsigned tmp;
+ const char *tmp_c;
+ tmp = mode1; mode1 = mode2; mode2 = tmp;
+ tmp_c = name1; name1 = name2; name2 = tmp_c;
+ }
+
+ if (!name1)
+ name1 = "/dev/null";
+ if (!name2)
+ name2 = "/dev/null";
+ d1 = alloc_filespec(name1);
+ d2 = alloc_filespec(name2);
+ fill_filespec(d1, null_sha1, mode1);
+ fill_filespec(d2, null_sha1, mode2);
+
+ diff_queue(&diff_queued_diff, d1, d2);
+ return 0;
+ }
+}
+
+static int is_in_index(const char *path)
+{
+ int len = strlen(path);
+ int pos = cache_name_pos(path, len);
+ char c;
+
+ if (pos < 0)
+ return 0;
+ if (strncmp(active_cache[pos]->name, path, len))
+ return 0;
+ c = active_cache[pos]->name[len];
+ return c == '\0' || c == '/';
+}
+
+static int handle_diff_files_args(struct rev_info *revs,
+ int argc, const char **argv, int *silent)
+{
+ *silent = 0;
+
+ /* revs->max_count == -2 means --no-index */
+ while (1 < argc && argv[1][0] == '-') {
+ if (!strcmp(argv[1], "--base"))
+ revs->max_count = 1;
+ else if (!strcmp(argv[1], "--ours"))
+ revs->max_count = 2;
+ else if (!strcmp(argv[1], "--theirs"))
+ revs->max_count = 3;
+ else if (!strcmp(argv[1], "-n") ||
+ !strcmp(argv[1], "--no-index"))
+ revs->max_count = -2;
+ else if (!strcmp(argv[1], "-q"))
+ *silent = 1;
+ else
+ return error("invalid option: %s", argv[1]);
+ argv++; argc--;
+ }
+
+ if (revs->max_count == -1 && revs->diffopt.nr_paths == 2) {
+ /*
+ * If two files are specified, and at least one is untracked,
+ * default to no-index.
+ */
+ read_cache();
+ if (!is_in_index(revs->diffopt.paths[0]) ||
+ !is_in_index(revs->diffopt.paths[1]))
+ revs->max_count = -2;
+ }
+
+ /*
+ * 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 (revs->pending.nr || revs->max_count > 3 ||
+ revs->min_age != -1 || revs->max_age != -1)
+ return error("no revision allowed with diff-files");
+
+ if (revs->max_count == -1 &&
+ (revs->diffopt.output_format & DIFF_FORMAT_PATCH))
+ revs->combine_merges = revs->dense_combined_merges = 1;
+
+ return 0;
+}
+
+int run_diff_files(struct rev_info *revs, int argc, const char **argv)
{
int entries, i;
- int diff_unmerged_stage = revs->max_count;
+ int diff_unmerged_stage;
+ int silent_on_removed;
+
+ if (handle_diff_files_args(revs, argc, argv, &silent_on_removed))
+ return -1;
+
+ diff_unmerged_stage = revs->max_count;
+
+ if (revs->max_count == -2) {
+ if (revs->diffopt.nr_paths != 2)
+ return error("need two files/directories with --no-index");
+ queue_diff(&revs->diffopt, revs->diffopt.paths[0],
+ revs->diffopt.paths[1]);
+ diffcore_std(&revs->diffopt);
+ diff_flush(&revs->diffopt);
+ return 0;
+ }
if (diff_unmerged_stage < 0)
diff_unmerged_stage = 2;
diff --git a/diff.c b/diff.c
index 12c8b2b..701880a 100644
--- a/diff.c
+++ b/diff.c
@@ -2406,7 +2406,8 @@ static void diff_resolve_rename_copy(void)
p->status = DIFF_STATUS_RENAMED;
}
else if (hashcmp(p->one->sha1, p->two->sha1) ||
- p->one->mode != p->two->mode)
+ p->one->mode != p->two->mode ||
+ is_null_sha1(p->one->sha1))
p->status = DIFF_STATUS_MODIFIED;
else {
/* This is a "no-change" entry and should not
diff --git a/diff.h b/diff.h
index eece65d..cc28418 100644
--- a/diff.h
+++ b/diff.h
@@ -218,7 +218,7 @@ 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);
+extern int run_diff_files(struct rev_info *revs, int argc, const char **argv);
extern int run_diff_index(struct rev_info *revs, int cached);
diff --git a/git.c b/git.c
index 4dd1967..79fc73c 100644
--- a/git.c
+++ b/git.c
@@ -237,8 +237,8 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "config", cmd_config },
{ "count-objects", cmd_count_objects, RUN_SETUP },
{ "describe", cmd_describe, RUN_SETUP },
- { "diff", cmd_diff, RUN_SETUP | USE_PAGER },
- { "diff-files", cmd_diff_files, RUN_SETUP },
+ { "diff", cmd_diff, USE_PAGER },
+ { "diff-files", cmd_diff_files },
{ "diff-index", cmd_diff_index, RUN_SETUP },
{ "diff-tree", cmd_diff_tree, RUN_SETUP },
{ "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP },
diff --git a/wt-status.c b/wt-status.c
index 2879c3d..b68eea3 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -231,7 +231,7 @@ static void wt_status_print_changed(struct wt_status *s)
rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
rev.diffopt.format_callback = wt_status_print_changed_cb;
rev.diffopt.format_callback_data = s;
- run_diff_files(&rev, 0);
+ run_diff_files(&rev, 0, NULL);
}
static void wt_status_print_untracked(struct wt_status *s)
--
1.5.0.50.gb7581-dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH] Teach git-diff{,-files} the new option `--no-index`
2007-02-20 18:46 [PATCH] Teach git-diff{,-files} the new option `--no-index` Johannes Schindelin
@ 2007-02-22 10:36 ` Junio C Hamano
2007-02-22 16:25 ` Johannes Schindelin
0 siblings, 1 reply; 13+ messages in thread
From: Junio C Hamano @ 2007-02-22 10:36 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git, junkio
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> Is this better than diff2 or what?
Probably.
> +int run_diff_files(struct rev_info *revs, int argc, const char **argv)
> {
> int entries, i;
> + int diff_unmerged_stage;
> + int silent_on_removed;
> +
> + if (handle_diff_files_args(revs, argc, argv, &silent_on_removed))
> + return -1;
> +
> + diff_unmerged_stage = revs->max_count;
> +
> + if (revs->max_count == -2) {
> + if (revs->diffopt.nr_paths != 2)
> + return error("need two files/directories with --no-index");
> + queue_diff(&revs->diffopt, revs->diffopt.paths[0],
> + revs->diffopt.paths[1]);
> + diffcore_std(&revs->diffopt);
> + diff_flush(&revs->diffopt);
> + return 0;
> + }
However, I do not like this part.
I do not mind the "max_count == -2 is some magic" hack too much,
but I do not think it belongs to a generic service function
whose purpose is to run "diff-files" aka "diff between index and
working tree". run_diff_files() is used by other applications
(most notably wt-status) for example, and I expect we would need
that when we rewrite git-commit itself in C.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] Teach git-diff{,-files} the new option `--no-index`
2007-02-22 10:36 ` Junio C Hamano
@ 2007-02-22 16:25 ` Johannes Schindelin
2007-02-22 18:09 ` Junio C Hamano
0 siblings, 1 reply; 13+ messages in thread
From: Johannes Schindelin @ 2007-02-22 16:25 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Hi,
On Thu, 22 Feb 2007, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > +int run_diff_files(struct rev_info *revs, int argc, const char **argv)
> > {
> > int entries, i;
> > + int diff_unmerged_stage;
> > + int silent_on_removed;
> > +
> > + if (handle_diff_files_args(revs, argc, argv, &silent_on_removed))
> > + return -1;
> > +
> > + diff_unmerged_stage = revs->max_count;
> > +
> > + if (revs->max_count == -2) {
> > + if (revs->diffopt.nr_paths != 2)
> > + return error("need two files/directories with --no-index");
> > + queue_diff(&revs->diffopt, revs->diffopt.paths[0],
> > + revs->diffopt.paths[1]);
> > + diffcore_std(&revs->diffopt);
> > + diff_flush(&revs->diffopt);
> > + return 0;
> > + }
>
> I do not mind the "max_count == -2 is some magic" hack too much,
> but I do not think it belongs to a generic service function
> whose purpose is to run "diff-files" aka "diff between index and
> working tree". run_diff_files() is used by other applications
> (most notably wt-status) for example, and I expect we would need
> that when we rewrite git-commit itself in C.
Well, the alternative is to duplicate code, as you need both the option
parsing and the special handling of max_count==-2 in both builtin-diff.c
and builtin-diff-files.c.
Ciao,
Dscho
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] Teach git-diff{,-files} the new option `--no-index`
2007-02-22 16:25 ` Johannes Schindelin
@ 2007-02-22 18:09 ` Junio C Hamano
2007-02-22 18:27 ` Johannes Schindelin
0 siblings, 1 reply; 13+ messages in thread
From: Junio C Hamano @ 2007-02-22 18:09 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> Hi,
>
> On Thu, 22 Feb 2007, Junio C Hamano wrote:
>
>> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>>
>> > +int run_diff_files(struct rev_info *revs, int argc, const char **argv)
>> > {
>> > int entries, i;
>> > + int diff_unmerged_stage;
>> > + int silent_on_removed;
>> > +
>> > + if (handle_diff_files_args(revs, argc, argv, &silent_on_removed))
>> > + return -1;
>> > +
>> > + diff_unmerged_stage = revs->max_count;
>> > +
>> > + if (revs->max_count == -2) {
>> > + if (revs->diffopt.nr_paths != 2)
>> > + return error("need two files/directories with --no-index");
>> > + queue_diff(&revs->diffopt, revs->diffopt.paths[0],
>> > + revs->diffopt.paths[1]);
>> > + diffcore_std(&revs->diffopt);
>> > + diff_flush(&revs->diffopt);
>> > + return 0;
>> > + }
>>
>> I do not mind the "max_count == -2 is some magic" hack too much,
>> but I do not think it belongs to a generic service function
>> whose purpose is to run "diff-files" aka "diff between index and
>> working tree". run_diff_files() is used by other applications
>> (most notably wt-status) for example, and I expect we would need
>> that when we rewrite git-commit itself in C.
>
> Well, the alternative is to duplicate code, as you need both the option
> parsing and the special handling of max_count==-2 in both builtin-diff.c
> and builtin-diff-files.c.
Can't they made to call a new function, which has the option
parsing followed by the switch between magic max_count==-2
codepath and run_diff_files()?
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] Teach git-diff{,-files} the new option `--no-index`
2007-02-22 18:09 ` Junio C Hamano
@ 2007-02-22 18:27 ` Johannes Schindelin
2007-02-22 18:54 ` [PATCH] run_diff_files(): add option to prevent --no-index Johannes Schindelin
2007-02-22 19:18 ` [PATCH] Teach git-diff{,-files} the new option `--no-index` Junio C Hamano
0 siblings, 2 replies; 13+ messages in thread
From: Johannes Schindelin @ 2007-02-22 18:27 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Hi,
On Thu, 22 Feb 2007, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > Hi,
> >
> > On Thu, 22 Feb 2007, Junio C Hamano wrote:
> >
> >> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> >>
> >> > +int run_diff_files(struct rev_info *revs, int argc, const char **argv)
> >> > {
> >> > int entries, i;
> >> > + int diff_unmerged_stage;
> >> > + int silent_on_removed;
> >> > +
> >> > + if (handle_diff_files_args(revs, argc, argv, &silent_on_removed))
> >> > + return -1;
> >> > +
> >> > + diff_unmerged_stage = revs->max_count;
> >> > +
> >> > + if (revs->max_count == -2) {
> >> > + if (revs->diffopt.nr_paths != 2)
> >> > + return error("need two files/directories with --no-index");
> >> > + queue_diff(&revs->diffopt, revs->diffopt.paths[0],
> >> > + revs->diffopt.paths[1]);
> >> > + diffcore_std(&revs->diffopt);
> >> > + diff_flush(&revs->diffopt);
> >> > + return 0;
> >> > + }
> >>
> >> I do not mind the "max_count == -2 is some magic" hack too much,
> >> but I do not think it belongs to a generic service function
> >> whose purpose is to run "diff-files" aka "diff between index and
> >> working tree". run_diff_files() is used by other applications
> >> (most notably wt-status) for example, and I expect we would need
> >> that when we rewrite git-commit itself in C.
> >
> > Well, the alternative is to duplicate code, as you need both the option
> > parsing and the special handling of max_count==-2 in both builtin-diff.c
> > and builtin-diff-files.c.
>
> Can't they made to call a new function, which has the option
> parsing followed by the switch between magic max_count==-2
> codepath and run_diff_files()?
How about adding "int always_use_index" to the signature of
run_diff_files()?
Ciao,
Dscho
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH] run_diff_files(): add option to prevent --no-index
2007-02-22 18:27 ` Johannes Schindelin
@ 2007-02-22 18:54 ` Johannes Schindelin
2007-02-22 19:18 ` [PATCH] Teach git-diff{,-files} the new option `--no-index` Junio C Hamano
1 sibling, 0 replies; 13+ messages in thread
From: Johannes Schindelin @ 2007-02-22 18:54 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
An important user, wt-status, does not want no-index. So add a
parameter to run_diff_files() which says if it is allowed or not.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
> How about adding "int always_use_index" to the signature of
> run_diff_files()?
I called the parameter "allow_no_index", since it is a little
friendlier. I have been accused of being not friendly enough.
builtin-diff-files.c | 2 +-
builtin-diff.c | 2 +-
diff-lib.c | 5 +++--
diff.h | 2 +-
wt-status.c | 2 +-
5 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/builtin-diff-files.c b/builtin-diff-files.c
index 8d78dfa..05a81b1 100644
--- a/builtin-diff-files.c
+++ b/builtin-diff-files.c
@@ -26,5 +26,5 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix)
argc = setup_revisions(argc, argv, &rev, NULL);
if (!rev.diffopt.output_format)
rev.diffopt.output_format = DIFF_FORMAT_RAW;
- return run_diff_files(&rev, argc, argv);
+ return run_diff_files(&rev, argc, argv, 1);
}
diff --git a/builtin-diff.c b/builtin-diff.c
index 9334589..7f1ad60 100644
--- a/builtin-diff.c
+++ b/builtin-diff.c
@@ -282,7 +282,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
if (!ents) {
switch (blobs) {
case 0:
- return run_diff_files(&rev, argc, argv);
+ return run_diff_files(&rev, argc, argv, 1);
break;
case 1:
if (paths != 1)
diff --git a/diff-lib.c b/diff-lib.c
index 83d6682..7877f5c 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -200,7 +200,8 @@ static int handle_diff_files_args(struct rev_info *revs,
return 0;
}
-int run_diff_files(struct rev_info *revs, int argc, const char **argv)
+int run_diff_files(struct rev_info *revs, int argc, const char **argv,
+ int allow_no_index)
{
int entries, i;
int diff_unmerged_stage;
@@ -211,7 +212,7 @@ int run_diff_files(struct rev_info *revs, int argc, const char **argv)
diff_unmerged_stage = revs->max_count;
- if (revs->max_count == -2) {
+ if (allow_no_index && revs->max_count == -2) {
if (revs->diffopt.nr_paths != 2)
return error("need two files/directories with --no-index");
queue_diff(&revs->diffopt, revs->diffopt.paths[0],
diff --git a/diff.h b/diff.h
index cc28418..bf2d3c9 100644
--- a/diff.h
+++ b/diff.h
@@ -218,7 +218,7 @@ 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 argc, const char **argv);
+extern int run_diff_files(struct rev_info *revs, int argc, const char **argv, int allow_no_index);
extern int run_diff_index(struct rev_info *revs, int cached);
diff --git a/wt-status.c b/wt-status.c
index b68eea3..4e8904d 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -231,7 +231,7 @@ static void wt_status_print_changed(struct wt_status *s)
rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
rev.diffopt.format_callback = wt_status_print_changed_cb;
rev.diffopt.format_callback_data = s;
- run_diff_files(&rev, 0, NULL);
+ run_diff_files(&rev, 0, NULL, 0);
}
static void wt_status_print_untracked(struct wt_status *s)
--
1.5.0.51.ge5582-dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH] Teach git-diff{,-files} the new option `--no-index`
2007-02-22 18:27 ` Johannes Schindelin
2007-02-22 18:54 ` [PATCH] run_diff_files(): add option to prevent --no-index Johannes Schindelin
@ 2007-02-22 19:18 ` Junio C Hamano
2007-02-22 20:01 ` Johannes Schindelin
1 sibling, 1 reply; 13+ messages in thread
From: Junio C Hamano @ 2007-02-22 19:18 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>> Can't they made to call a new function, which has the option
>> parsing followed by the switch between magic max_count==-2
>> codepath and run_diff_files()?
>
> How about adding "int always_use_index" to the signature of
> run_diff_files()?
The "magic" part is not about the index at all (it is about
using only that magic part to do diff on filesystem), and the
original code is about "index vs filesystem". I would rather
keep them in separate function. That is:
run_diff_files(); /* compares index vs filesystem */
run_diff_filesystem(); /* runs diff2 */
run_diff_files_cmd() {
/* a new helper */
parse args;
if (magic)
run_diff_filesystem();
else
run_diff_files();
}
builtin_diff() {
if (not about two trees nor two blobs ...)
run_diff_files_cmd();
else if (about two trees)
run_diff_tree();
else if (about tree and index)
run_diff_index();
}
wt_status() {
run_diff_files();
run_diff_index();
}
For one thing, I want to move read_cache() out of
run_diff_files() and run_diff_index() to their callers, so that
the caller can use a handcrafted active_cache[] that is somewhat
different from what read_cache() originally read.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] Teach git-diff{,-files} the new option `--no-index`
2007-02-22 19:18 ` [PATCH] Teach git-diff{,-files} the new option `--no-index` Junio C Hamano
@ 2007-02-22 20:01 ` Johannes Schindelin
2007-02-22 20:28 ` Junio C Hamano
0 siblings, 1 reply; 13+ messages in thread
From: Johannes Schindelin @ 2007-02-22 20:01 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Hi,
On Thu, 22 Feb 2007, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> >> Can't they made to call a new function, which has the option
> >> parsing followed by the switch between magic max_count==-2
> >> codepath and run_diff_files()?
> >
> > How about adding "int always_use_index" to the signature of
> > run_diff_files()?
>
> The "magic" part is not about the index at all (it is about
> using only that magic part to do diff on filesystem), and the
> original code is about "index vs filesystem".
I don't understand. diff-files until --no-index _always_ diffed against
the index. Now, if "allow_no_index" is non-zero, under very special
circumstances diff-files does the DWIMery.
> I would rather keep them in separate function. That is:
>
> run_diff_files(); /* compares index vs filesystem */
>
> run_diff_filesystem(); /* runs diff2 */
>
> run_diff_files_cmd() {
> /* a new helper */
> parse args;
> if (magic)
> run_diff_filesystem();
> else
> run_diff_files();
> }
>
> builtin_diff() {
> if (not about two trees nor two blobs ...)
> run_diff_files_cmd();
> else if (about two trees)
> run_diff_tree();
> else if (about tree and index)
> run_diff_index();
> }
>
> wt_status() {
> run_diff_files();
> run_diff_index();
> }
So you mean only add run_diff_files_cmd(), called by diff and diff-files?
> For one thing, I want to move read_cache() out of run_diff_files() and
> run_diff_index() to their callers, so that the caller can use a
> handcrafted active_cache[] that is somewhat different from what
> read_cache() originally read.
I don't understand. Would it not be easier to "return active_nr" in
read_cache_from(path) _also_ when active_cache is set? Or alternatively
check if active_alloc is set?
Ciao,
Dscho
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] Teach git-diff{,-files} the new option `--no-index`
2007-02-22 20:01 ` Johannes Schindelin
@ 2007-02-22 20:28 ` Junio C Hamano
2007-02-22 20:47 ` Johannes Schindelin
2007-02-22 20:50 ` [PATCH, N'TH TRY] Teach git-diff-files " Johannes Schindelin
0 siblings, 2 replies; 13+ messages in thread
From: Junio C Hamano @ 2007-02-22 20:28 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>> For one thing, I want to move read_cache() out of run_diff_files() and
>> run_diff_index() to their callers, so that the caller can use a
>> handcrafted active_cache[] that is somewhat different from what
>> read_cache() originally read.
>
> I don't understand. Would it not be easier to "return active_nr" in
> read_cache_from(path) _also_ when active_cache is set? Or alternatively
> check if active_alloc is set?
I do not understand your questions.
What I am getting at is that in the current code (without your
patch), run_diff_files() is about diff between $GIT_DIR/index
and working tree. I want to make it diff between active_cache[]
and working tree.
The caller still can use read_cache() or read_cache_from(path)
to populate active_cache[], but it is not limited to. It can do
other index manipulations before calling run_diff_files(). For
example, it can do read_tree() to populate active_cache[] before
calling run_diff_files() and/or run_diff_index(). Or maybe it
can run multi-tree read_tree() to populate active_cache[],
internally merge them without writing the merge results out, and
then call run_diff_files() to show "here is what would happen if
you were to run a merge now", all inside active_cache[].
Of course such a caller needs to be careful not to write
active_cache[] out when it shouldn't, but that goes without
saying. git-diff-index already mucks with active_cache[] with
full intention of not writing it out.
Please see near the tip of 'pu', around here, for much simpler
usage pattern I had in mind:
commit 910d798768989d8fe581c2afcfd501307db81b10
Author: Junio C Hamano <junkio@cox.net>
git-status: use in-core --refresh in a read-only repository.
commit c5cc9b14a0f36d7fab66b3152f0ebcb442674bfc
Author: Junio C Hamano <junkio@cox.net>
git-runstatus --refresh
commit b4e1e4a787d3771f617182b3344dcdd9224bd0cb
Author: Junio C Hamano <junkio@cox.net>
run_diff_{files,index}(): update calling convention.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] Teach git-diff{,-files} the new option `--no-index`
2007-02-22 20:28 ` Junio C Hamano
@ 2007-02-22 20:47 ` Johannes Schindelin
2007-02-22 20:50 ` [PATCH, N'TH TRY] Teach git-diff-files " Johannes Schindelin
1 sibling, 0 replies; 13+ messages in thread
From: Johannes Schindelin @ 2007-02-22 20:47 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Hi,
On Thu, 22 Feb 2007, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> >> For one thing, I want to move read_cache() out of run_diff_files() and
> >> run_diff_index() to their callers, so that the caller can use a
> >> handcrafted active_cache[] that is somewhat different from what
> >> read_cache() originally read.
> >
> > I don't understand. Would it not be easier to "return active_nr" in
> > read_cache_from(path) _also_ when active_cache is set? Or alternatively
> > check if active_alloc is set?
>
> I do not understand your questions.
>
> What I am getting at is that in the current code (without your
> patch), run_diff_files() is about diff between $GIT_DIR/index
> and working tree. I want to make it diff between active_cache[]
> and working tree.
My point was: you could just ignore the read_cache() calls if they just
returned, doing nothing, as long as there is an active_cache.
But that's probably too dirty.
Anyway, I restructured the patch as per your comments, and will send it
after this mail.
Ciao,
Dscho
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH, N'TH TRY] Teach git-diff-files the new option `--no-index`
2007-02-22 20:28 ` Junio C Hamano
2007-02-22 20:47 ` Johannes Schindelin
@ 2007-02-22 20:50 ` Johannes Schindelin
2007-02-23 11:44 ` Junio C Hamano
1 sibling, 1 reply; 13+ messages in thread
From: Johannes Schindelin @ 2007-02-22 20:50 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
With this flag and given two paths, git-diff-files behaves as a GNU diff
lookalike (plus the git goodies like --check, colour, etc.). This flag
is also available in git-diff. It also works outside of a git repository.
In addition, if git-diff{,-files} is called without revision or stage
parameter, and with exactly two paths at least one of which is not tracked,
the default is --no-index.
So, you can now say
git diff /etc/inittab /etc/fstab
and it actually works!
This also unifies the duplicated argument parsing between cmd_diff_files()
and builtin_diff_files().
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
Documentation/git-diff-files.txt | 5 +-
Documentation/git-diff.txt | 4 +
builtin-diff-files.c | 29 +-----
builtin-diff.c | 38 +-------
diff-lib.c | 207 ++++++++++++++++++++++++++++++++++++++
diff.c | 3 +-
diff.h | 1 +
git.c | 4 +-
8 files changed, 227 insertions(+), 64 deletions(-)
diff --git a/Documentation/git-diff-files.txt b/Documentation/git-diff-files.txt
index 7248b35..b78c4c6 100644
--- a/Documentation/git-diff-files.txt
+++ b/Documentation/git-diff-files.txt
@@ -8,7 +8,7 @@ git-diff-files - Compares files in the working tree and the index
SYNOPSIS
--------
-'git-diff-files' [-q] [-0|-1|-2|-3|-c|--cc] [<common diff options>] [<path>...]
+'git-diff-files' [-q] [-0|-1|-2|-3|-c|--cc|-n|--no-index] [<common diff options>] [<path>...]
DESCRIPTION
-----------
@@ -36,6 +36,9 @@ omit diff output for unmerged entries and just show "Unmerged".
diff, similar to the way 'diff-tree' shows a merge
commit with these flags.
+\-n,\--no-index::
+ Compare the two given files / directories.
+
-q::
Remain silent even on nonexistent files
diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt
index 6a098df..12a531d 100644
--- a/Documentation/git-diff.txt
+++ b/Documentation/git-diff.txt
@@ -23,6 +23,10 @@ tree and the index file, or the index file and the working tree.
further add to the index but you still haven't. You can
stage these changes by using gitlink:git-add[1].
+ If exactly two paths are given, and at least one is untracked,
+ compare the two files / directories. This behavior can be
+ forced by --no-index.
+
'git-diff' [--options] --cached [<commit>] [--] [<path>...]::
This form is to view the changes you staged for the next
diff --git a/builtin-diff-files.c b/builtin-diff-files.c
index 5d4a5c5..e1199f8 100644
--- a/builtin-diff-files.c
+++ b/builtin-diff-files.c
@@ -10,42 +10,21 @@
#include "builtin.h"
static const char diff_files_usage[] =
-"git-diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]"
+"git-diff-files [-q] [-0/-1/2/3 |-c|--cc|-n|--no-index] [<common diff options>] [<path>...]"
COMMON_DIFF_OPTIONS_HELP;
int cmd_diff_files(int argc, const char **argv, const char *prefix)
{
struct rev_info rev;
- int silent = 0;
+ int nongit = 0;
+ prefix = setup_git_directory_gently(&nongit);
init_revisions(&rev, prefix);
git_config(git_default_config); /* no "diff" UI options */
rev.abbrev = 0;
argc = setup_revisions(argc, argv, &rev, NULL);
- while (1 < argc && argv[1][0] == '-') {
- if (!strcmp(argv[1], "--base"))
- rev.max_count = 1;
- else if (!strcmp(argv[1], "--ours"))
- rev.max_count = 2;
- else if (!strcmp(argv[1], "--theirs"))
- rev.max_count = 3;
- else if (!strcmp(argv[1], "-q"))
- silent = 1;
- else
- usage(diff_files_usage);
- argv++; argc--;
- }
if (!rev.diffopt.output_format)
rev.diffopt.output_format = DIFF_FORMAT_RAW;
-
- /*
- * 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.nr ||
- rev.min_age != -1 || rev.max_age != -1)
- usage(diff_files_usage);
- return run_diff_files(&rev, silent);
+ return run_diff_files_cmd(&rev, argc, argv);
}
diff --git a/builtin-diff.c b/builtin-diff.c
index a659020..54bbf02 100644
--- a/builtin-diff.c
+++ b/builtin-diff.c
@@ -25,40 +25,6 @@ struct blobinfo {
static const char builtin_diff_usage[] =
"git-diff <options> <rev>{0,2} -- <path>*";
-static int builtin_diff_files(struct rev_info *revs,
- int argc, const char **argv)
-{
- int silent = 0;
- while (1 < argc) {
- const char *arg = argv[1];
- if (!strcmp(arg, "--base"))
- revs->max_count = 1;
- else if (!strcmp(arg, "--ours"))
- revs->max_count = 2;
- else if (!strcmp(arg, "--theirs"))
- revs->max_count = 3;
- else if (!strcmp(arg, "-q"))
- silent = 1;
- else
- usage(builtin_diff_usage);
- argv++; argc--;
- }
- /*
- * Make sure there are NO revision (i.e. pending object) parameter,
- * specified rev.max_count is reasonable (0 <= n <= 3), and
- * there is no other revision filtering parameter.
- */
- if (revs->pending.nr ||
- revs->min_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;
- return run_diff_files(revs, silent);
-}
-
static void stuff_change(struct diff_options *opt,
unsigned old_mode, unsigned new_mode,
const unsigned char *old_sha1,
@@ -218,6 +184,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
int ents = 0, blobs = 0, paths = 0;
const char *path = NULL;
struct blobinfo blob[2];
+ int nongit = 0;
/*
* We could get N tree-ish in the rev.pending_objects list.
@@ -239,6 +206,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
* Other cases are errors.
*/
+ prefix = setup_git_directory_gently(&nongit);
git_config(git_diff_ui_config);
init_revisions(&rev, prefix);
@@ -314,7 +282,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
if (!ents) {
switch (blobs) {
case 0:
- return builtin_diff_files(&rev, argc, argv);
+ return run_diff_files_cmd(&rev, argc, argv);
break;
case 1:
if (paths != 1)
diff --git a/diff-lib.c b/diff-lib.c
index 556d534..a9b5149 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -8,11 +8,218 @@
#include "diffcore.h"
#include "revision.h"
#include "cache-tree.h"
+#include "path-list.h"
/*
* diff-files
*/
+static int read_directory(const char *path, struct path_list *list)
+{
+ DIR *dir;
+ struct dirent *e;
+
+ if (!(dir = opendir(path)))
+ return error("Could not open directory %s", path);
+
+ while ((e = readdir(dir)))
+ if (strcmp(".", e->d_name) && strcmp("..", e->d_name))
+ path_list_insert(xstrdup(e->d_name), list);
+
+ closedir(dir);
+ return 0;
+}
+
+static int queue_diff(struct diff_options *o,
+ const char *name1, const char *name2)
+{
+ struct stat st;
+ int mode1 = 0, mode2 = 0;
+
+ if (name1) {
+ if (stat(name1, &st))
+ return error("Could not access '%s'", name1);
+ mode1 = st.st_mode;
+ }
+ if (name2) {
+ if (stat(name2, &st))
+ return error("Could not access '%s'", name1);
+ mode2 = st.st_mode;
+ }
+
+ if (mode1 && mode2 && S_ISDIR(mode1) != S_ISDIR(mode2))
+ return error("file/directory conflict: %s, %s", name1, name2);
+
+ if (S_ISDIR(mode1) || S_ISDIR(mode2)) {
+ char buffer1[PATH_MAX], buffer2[PATH_MAX];
+ struct path_list p1 = {NULL, 0, 0, 1}, p2 = {NULL, 0, 0, 1};
+ int len1 = 0, len2 = 0, i1, i2, ret = 0;
+
+ if (name1 && read_directory(name1, &p1))
+ return -1;
+ if (name2 && read_directory(name2, &p2)) {
+ path_list_clear(&p1, 0);
+ return -1;
+ }
+
+ if (name1) {
+ len1 = strlen(name1);
+ if (len1 > 0 && name1[len1 - 1] == '/')
+ len1--;
+ memcpy(buffer1, name1, len1);
+ buffer1[len1++] = '/';
+ }
+
+ if (name2) {
+ len2 = strlen(name2);
+ if (len2 > 0 && name2[len2 - 1] == '/')
+ len2--;
+ memcpy(buffer2, name2, len2);
+ buffer2[len2++] = '/';
+ }
+
+ for (i1 = i2 = 0; !ret && (i1 < p1.nr || i2 < p2.nr); ) {
+ const char *n1, *n2;
+ int comp;
+
+ if (i1 == p1.nr)
+ comp = 1;
+ else if (i2 == p2.nr)
+ comp = -1;
+ else
+ comp = strcmp(p1.items[i1].path,
+ p2.items[i2].path);
+
+ if (comp > 0)
+ n1 = NULL;
+ else {
+ n1 = buffer1;
+ strncpy(buffer1 + len1, p1.items[i1++].path,
+ PATH_MAX - len1);
+ }
+
+ if (comp < 0)
+ n2 = NULL;
+ else {
+ n2 = buffer2;
+ strncpy(buffer2 + len2, p2.items[i2++].path,
+ PATH_MAX - len2);
+ }
+
+ ret = queue_diff(o, n1, n2);
+ }
+ path_list_clear(&p1, 0);
+ path_list_clear(&p2, 0);
+
+ return ret;
+ } else {
+ struct diff_filespec *d1, *d2;
+
+ if (o->reverse_diff) {
+ unsigned tmp;
+ const char *tmp_c;
+ tmp = mode1; mode1 = mode2; mode2 = tmp;
+ tmp_c = name1; name1 = name2; name2 = tmp_c;
+ }
+
+ if (!name1)
+ name1 = "/dev/null";
+ if (!name2)
+ name2 = "/dev/null";
+ d1 = alloc_filespec(name1);
+ d2 = alloc_filespec(name2);
+ fill_filespec(d1, null_sha1, mode1);
+ fill_filespec(d2, null_sha1, mode2);
+
+ diff_queue(&diff_queued_diff, d1, d2);
+ return 0;
+ }
+}
+
+static int is_in_index(const char *path)
+{
+ int len = strlen(path);
+ int pos = cache_name_pos(path, len);
+ char c;
+
+ if (pos < 0)
+ return 0;
+ if (strncmp(active_cache[pos]->name, path, len))
+ return 0;
+ c = active_cache[pos]->name[len];
+ return c == '\0' || c == '/';
+}
+
+static int handle_diff_files_args(struct rev_info *revs,
+ int argc, const char **argv, int *silent)
+{
+ *silent = 0;
+
+ /* revs->max_count == -2 means --no-index */
+ while (1 < argc && argv[1][0] == '-') {
+ if (!strcmp(argv[1], "--base"))
+ revs->max_count = 1;
+ else if (!strcmp(argv[1], "--ours"))
+ revs->max_count = 2;
+ else if (!strcmp(argv[1], "--theirs"))
+ revs->max_count = 3;
+ else if (!strcmp(argv[1], "-n") ||
+ !strcmp(argv[1], "--no-index"))
+ revs->max_count = -2;
+ else if (!strcmp(argv[1], "-q"))
+ *silent = 1;
+ else
+ return error("invalid option: %s", argv[1]);
+ argv++; argc--;
+ }
+
+ if (revs->max_count == -1 && revs->diffopt.nr_paths == 2) {
+ /*
+ * If two files are specified, and at least one is untracked,
+ * default to no-index.
+ */
+ read_cache();
+ if (!is_in_index(revs->diffopt.paths[0]) ||
+ !is_in_index(revs->diffopt.paths[1]))
+ revs->max_count = -2;
+ }
+
+ /*
+ * 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 (revs->pending.nr || revs->max_count > 3 ||
+ revs->min_age != -1 || revs->max_age != -1)
+ return error("no revision allowed with diff-files");
+
+ if (revs->max_count == -1 &&
+ (revs->diffopt.output_format & DIFF_FORMAT_PATCH))
+ revs->combine_merges = revs->dense_combined_merges = 1;
+
+ return 0;
+}
+
+int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv)
+{
+ int silent_on_removed;
+
+ if (handle_diff_files_args(revs, argc, argv, &silent_on_removed))
+ return -1;
+
+ if (revs->max_count == -2) {
+ if (revs->diffopt.nr_paths != 2)
+ return error("need two files/directories with --no-index");
+ queue_diff(&revs->diffopt, revs->diffopt.paths[0],
+ revs->diffopt.paths[1]);
+ diffcore_std(&revs->diffopt);
+ diff_flush(&revs->diffopt);
+ return 0;
+ }
+
+ return run_diff_files(revs, silent_on_removed);
+}
+
int run_diff_files(struct rev_info *revs, int silent_on_removed)
{
int entries, i;
diff --git a/diff.c b/diff.c
index 12c8b2b..701880a 100644
--- a/diff.c
+++ b/diff.c
@@ -2406,7 +2406,8 @@ static void diff_resolve_rename_copy(void)
p->status = DIFF_STATUS_RENAMED;
}
else if (hashcmp(p->one->sha1, p->two->sha1) ||
- p->one->mode != p->two->mode)
+ p->one->mode != p->two->mode ||
+ is_null_sha1(p->one->sha1))
p->status = DIFF_STATUS_MODIFIED;
else {
/* This is a "no-change" entry and should not
diff --git a/diff.h b/diff.h
index eece65d..b608828 100644
--- a/diff.h
+++ b/diff.h
@@ -219,6 +219,7 @@ 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);
+extern int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv);
extern int run_diff_index(struct rev_info *revs, int cached);
diff --git a/git.c b/git.c
index 4dd1967..79fc73c 100644
--- a/git.c
+++ b/git.c
@@ -237,8 +237,8 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "config", cmd_config },
{ "count-objects", cmd_count_objects, RUN_SETUP },
{ "describe", cmd_describe, RUN_SETUP },
- { "diff", cmd_diff, RUN_SETUP | USE_PAGER },
- { "diff-files", cmd_diff_files, RUN_SETUP },
+ { "diff", cmd_diff, USE_PAGER },
+ { "diff-files", cmd_diff_files },
{ "diff-index", cmd_diff_index, RUN_SETUP },
{ "diff-tree", cmd_diff_tree, RUN_SETUP },
{ "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP },
--
1.5.0.51.ge5582-dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH, N'TH TRY] Teach git-diff-files the new option `--no-index`
2007-02-22 20:50 ` [PATCH, N'TH TRY] Teach git-diff-files " Johannes Schindelin
@ 2007-02-23 11:44 ` Junio C Hamano
2007-02-23 16:07 ` diff-patch: Avoid emitting double-slashes in textual patch Johannes Schindelin
0 siblings, 1 reply; 13+ messages in thread
From: Junio C Hamano @ 2007-02-23 11:44 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> With this flag and given two paths, git-diff-files behaves as a GNU diff
> lookalike (plus the git goodies like --check, colour, etc.). This flag
> is also available in git-diff. It also works outside of a git repository.
>
> In addition, if git-diff{,-files} is called without revision or stage
> parameter, and with exactly two paths at least one of which is not tracked,
> the default is --no-index.
>
> So, you can now say
>
> git diff /etc/inittab /etc/fstab
>
> and it actually works!
Modulo double slashes X-<.
$ diff --git a//etc/inittab b//etc/fstab
index 04eabd6..7314c1a 100644
--- a//etc/inittab
+++ b//etc/fstab
@@ -1,69 +1,13 @@
...
This problem is not new; this should fix it.
-- >8 --
diff-patch: Avoid emitting double-slashes in textual patch.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
diff --git a/diff.c b/diff.c
index 5ecb122..84937cb 100644
--- a/diff.c
+++ b/diff.c
@@ -219,6 +219,9 @@ static void emit_rewrite_diff(const char *name_a,
const char *new = diff_get_color(color_diff, DIFF_FILE_NEW);
const char *reset = diff_get_color(color_diff, DIFF_RESET);
+ name_a += (*name_a == '/');
+ name_b += (*name_b == '/');
+
name_a_tab = strchr(name_a, ' ') ? "\t" : "";
name_b_tab = strchr(name_b, ' ') ? "\t" : "";
@@ -1064,8 +1067,8 @@ static void builtin_diff(const char *name_a,
const char *set = diff_get_color(o->color_diff, DIFF_METAINFO);
const char *reset = diff_get_color(o->color_diff, DIFF_RESET);
- a_one = quote_two("a/", name_a);
- b_two = quote_two("b/", name_b);
+ a_one = quote_two("a/", name_a + (*name_a == '/'));
+ b_two = quote_two("b/", name_b + (*name_b == '/'));
lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null";
lbl[1] = DIFF_FILE_VALID(two) ? b_two : "/dev/null";
printf("%sdiff --git %s %s%s\n", set, a_one, b_two, reset);
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: diff-patch: Avoid emitting double-slashes in textual patch.
2007-02-23 11:44 ` Junio C Hamano
@ 2007-02-23 16:07 ` Johannes Schindelin
0 siblings, 0 replies; 13+ messages in thread
From: Johannes Schindelin @ 2007-02-23 16:07 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Hi,
On Fri, 23 Feb 2007, Junio C Hamano wrote:
> - a_one = quote_two("a/", name_a);
> - b_two = quote_two("b/", name_b);
> + a_one = quote_two("a/", name_a + (*name_a == '/'));
> + b_two = quote_two("b/", name_b + (*name_b == '/'));
I briefly thought about something like this instead:
- a_one = quote_two("a/", name_a + (*name_a == '/'));
- b_two = quote_two("b/", name_b + (*name_b == '/'));
+ a_one = quote_two(*name_a == '/' ? "" : "a/", name_a);
+ b_two = quote_two(*name_b == '/' ? "" : "b/", name_b);
lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null";
lbl[1] = DIFF_FILE_VALID(two) ? b_two : "/dev/null";
- printf("%sdiff --git %s %s%s\n", set, a_one, b_two, reset);
+ printf("%sdiff %s%s %s%s\n", set, *name_a == '/' || *name_b == '/' ?
+ "" : "--git ", a_one, b_two, reset);
but I think your approach is better.
Ciao,
Dscho
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2007-02-23 16:07 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-02-20 18:46 [PATCH] Teach git-diff{,-files} the new option `--no-index` Johannes Schindelin
2007-02-22 10:36 ` Junio C Hamano
2007-02-22 16:25 ` Johannes Schindelin
2007-02-22 18:09 ` Junio C Hamano
2007-02-22 18:27 ` Johannes Schindelin
2007-02-22 18:54 ` [PATCH] run_diff_files(): add option to prevent --no-index Johannes Schindelin
2007-02-22 19:18 ` [PATCH] Teach git-diff{,-files} the new option `--no-index` Junio C Hamano
2007-02-22 20:01 ` Johannes Schindelin
2007-02-22 20:28 ` Junio C Hamano
2007-02-22 20:47 ` Johannes Schindelin
2007-02-22 20:50 ` [PATCH, N'TH TRY] Teach git-diff-files " Johannes Schindelin
2007-02-23 11:44 ` Junio C Hamano
2007-02-23 16:07 ` diff-patch: Avoid emitting double-slashes in textual patch Johannes Schindelin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).