Skip to content

Commit 4682d85

Browse files
committed
diff-index.c: "git diff" has no need to read blob from the standard input
Only "diff --no-index -" does. Bolting the logic into the low-level function diff_populate_filespec() was a layering violation from day one. Move populate_from_stdin() function out of the generic diff.c to its only user, diff-index.c. Also make sure "-" from the command line stays a special token "read from the standard input", even if we later decide to sanitize the result from prefix_filename() function in a few obvious ways, e.g. removing unnecessary "./" prefix, duplicated slashes "//" in the middle, etc. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 3b069b1 commit 4682d85

File tree

4 files changed

+55
-31
lines changed

4 files changed

+55
-31
lines changed

diff-no-index.c

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ static int read_directory(const char *path, struct string_list *list)
3232
return 0;
3333
}
3434

35+
/*
36+
* This should be "(standard input)" or something, but it will
37+
* probably expose many more breakages in the way no-index code
38+
* is bolted onto the diff callchain.
39+
*/
40+
static const char file_from_standard_input[] = "-";
41+
3542
static int get_mode(const char *path, int *mode)
3643
{
3744
struct stat st;
@@ -42,7 +49,7 @@ static int get_mode(const char *path, int *mode)
4249
else if (!strcasecmp(path, "nul"))
4350
*mode = 0;
4451
#endif
45-
else if (!strcmp(path, "-"))
52+
else if (path == file_from_standard_input)
4653
*mode = create_ce_mode(0666);
4754
else if (lstat(path, &st))
4855
return error("Could not access '%s'", path);
@@ -51,6 +58,36 @@ static int get_mode(const char *path, int *mode)
5158
return 0;
5259
}
5360

61+
static int populate_from_stdin(struct diff_filespec *s)
62+
{
63+
struct strbuf buf = STRBUF_INIT;
64+
size_t size = 0;
65+
66+
if (strbuf_read(&buf, 0, 0) < 0)
67+
return error("error while reading from stdin %s",
68+
strerror(errno));
69+
70+
s->should_munmap = 0;
71+
s->data = strbuf_detach(&buf, &size);
72+
s->size = size;
73+
s->should_free = 1;
74+
s->is_stdin = 1;
75+
return 0;
76+
}
77+
78+
static struct diff_filespec *noindex_filespec(const char *name, int mode)
79+
{
80+
struct diff_filespec *s;
81+
82+
if (!name)
83+
name = "/dev/null";
84+
s = alloc_filespec(name);
85+
fill_filespec(s, null_sha1, mode);
86+
if (name == file_from_standard_input)
87+
populate_from_stdin(s);
88+
return s;
89+
}
90+
5491
static int queue_diff(struct diff_options *o,
5592
const char *name1, const char *name2)
5693
{
@@ -135,15 +172,8 @@ static int queue_diff(struct diff_options *o,
135172
tmp_c = name1; name1 = name2; name2 = tmp_c;
136173
}
137174

138-
if (!name1)
139-
name1 = "/dev/null";
140-
if (!name2)
141-
name2 = "/dev/null";
142-
d1 = alloc_filespec(name1);
143-
d2 = alloc_filespec(name2);
144-
fill_filespec(d1, null_sha1, mode1);
145-
fill_filespec(d2, null_sha1, mode2);
146-
175+
d1 = noindex_filespec(name1, mode1);
176+
d2 = noindex_filespec(name2, mode2);
147177
diff_queue(&diff_queued_diff, d1, d2);
148178
return 0;
149179
}
@@ -238,7 +268,7 @@ void diff_no_index(struct rev_info *revs,
238268
* stdin should be spelled as "-"; if you have
239269
* path that is "-", spell it as "./-".
240270
*/
241-
p = p;
271+
p = file_from_standard_input;
242272
else if (prefixlen)
243273
p = xstrdup(prefix_filename(prefix, prefixlen, p));
244274
paths[i] = p;

diff.c

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2426,22 +2426,6 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
24262426
return 0;
24272427
}
24282428

2429-
static int populate_from_stdin(struct diff_filespec *s)
2430-
{
2431-
struct strbuf buf = STRBUF_INIT;
2432-
size_t size = 0;
2433-
2434-
if (strbuf_read(&buf, 0, 0) < 0)
2435-
return error("error while reading from stdin %s",
2436-
strerror(errno));
2437-
2438-
s->should_munmap = 0;
2439-
s->data = strbuf_detach(&buf, &size);
2440-
s->size = size;
2441-
s->should_free = 1;
2442-
return 0;
2443-
}
2444-
24452429
static int diff_populate_gitlink(struct diff_filespec *s, int size_only)
24462430
{
24472431
int len;
@@ -2491,9 +2475,6 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
24912475
struct stat st;
24922476
int fd;
24932477

2494-
if (!strcmp(s->path, "-"))
2495-
return populate_from_stdin(s);
2496-
24972478
if (lstat(s->path, &st) < 0) {
24982479
if (errno == ENOENT) {
24992480
err_empty:
@@ -2855,7 +2836,7 @@ static void diff_fill_sha1_info(struct diff_filespec *one)
28552836
if (DIFF_FILE_VALID(one)) {
28562837
if (!one->sha1_valid) {
28572838
struct stat st;
2858-
if (!strcmp(one->path, "-")) {
2839+
if (one->is_stdin) {
28592840
hashcpy(one->sha1, null_sha1);
28602841
return;
28612842
}

diffcore.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ struct diff_filespec {
4343
unsigned should_free : 1; /* data should be free()'ed */
4444
unsigned should_munmap : 1; /* data should be munmap()'ed */
4545
unsigned dirty_submodule : 2; /* For submodules: its work tree is dirty */
46+
unsigned is_stdin : 1;
4647
#define DIRTY_SUBMODULE_UNTRACKED 1
4748
#define DIRTY_SUBMODULE_MODIFIED 2
4849

t/t7501-commit.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,4 +458,16 @@ test_expect_success 'amend can copy notes' '
458458
459459
'
460460

461+
test_expect_success 'commit a file whose name is a dash' '
462+
git reset --hard &&
463+
for i in 1 2 3 4 5
464+
do
465+
echo $i
466+
done >./- &&
467+
git add ./- &&
468+
test_tick &&
469+
git commit -m "add dash" >output </dev/null &&
470+
test_i18ngrep " changed, 5 insertions" output
471+
'
472+
461473
test_done

0 commit comments

Comments
 (0)