Skip to content

Commit 7ef0d04

Browse files
committed
Merge branch 'jk/diff-blob'
The result from "git diff" that compares two blobs, e.g. "git diff $commit1:$path $commit2:$path", used to be shown with the full object name as given on the command line, but it is more natural to use the $path in the output and use it to look up .gitattributes. * jk/diff-blob: diff: use blob path for blob/file diffs diff: use pending "path" if it is available diff: use the word "path" instead of "name" for blobs diff: pass whole pending entry in blobinfo handle_revision_arg: record paths for pending objects handle_revision_arg: record modes for "a..b" endpoints t4063: add tests of direct blob diffs get_sha1_with_context: dynamically allocate oc->path get_sha1_with_context: always initialize oc->symlink_path sha1_name: consistently refer to object_context as "oc" handle_revision_arg: add handle_dotdot() helper handle_revision_arg: hoist ".." check out of range parsing handle_revision_arg: stop using "dotdot" as a generic pointer handle_revision_arg: simplify commit reference lookups handle_revision_arg: reset "dotdot" consistently
2 parents f4fd99b + 30d005c commit 7ef0d04

File tree

10 files changed

+301
-147
lines changed

10 files changed

+301
-147
lines changed

builtin/cat-file.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
6161
if (unknown_type)
6262
flags |= LOOKUP_UNKNOWN_OBJECT;
6363

64-
if (get_sha1_with_context(obj_name, 0, oid.hash, &obj_context))
64+
if (get_sha1_with_context(obj_name, GET_SHA1_RECORD_PATH,
65+
oid.hash, &obj_context))
6566
die("Not a valid object name %s", obj_name);
6667

6768
if (!path)
@@ -166,6 +167,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
166167

167168
write_or_die(1, buf, size);
168169
free(buf);
170+
free(obj_context.path);
169171
return 0;
170172
}
171173

builtin/diff.c

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,22 @@
2020
#define DIFF_NO_INDEX_EXPLICIT 1
2121
#define DIFF_NO_INDEX_IMPLICIT 2
2222

23-
struct blobinfo {
24-
struct object_id oid;
25-
const char *name;
26-
unsigned mode;
27-
};
28-
2923
static const char builtin_diff_usage[] =
3024
"git diff [<options>] [<commit> [<commit>]] [--] [<path>...]";
3125

26+
static const char *blob_path(struct object_array_entry *entry)
27+
{
28+
return entry->path ? entry->path : entry->name;
29+
}
30+
3231
static void stuff_change(struct diff_options *opt,
3332
unsigned old_mode, unsigned new_mode,
3433
const struct object_id *old_oid,
3534
const struct object_id *new_oid,
3635
int old_oid_valid,
3736
int new_oid_valid,
38-
const char *old_name,
39-
const char *new_name)
37+
const char *old_path,
38+
const char *new_path)
4039
{
4140
struct diff_filespec *one, *two;
4241

@@ -47,16 +46,16 @@ static void stuff_change(struct diff_options *opt,
4746
if (DIFF_OPT_TST(opt, REVERSE_DIFF)) {
4847
SWAP(old_mode, new_mode);
4948
SWAP(old_oid, new_oid);
50-
SWAP(old_name, new_name);
49+
SWAP(old_path, new_path);
5150
}
5251

5352
if (opt->prefix &&
54-
(strncmp(old_name, opt->prefix, opt->prefix_length) ||
55-
strncmp(new_name, opt->prefix, opt->prefix_length)))
53+
(strncmp(old_path, opt->prefix, opt->prefix_length) ||
54+
strncmp(new_path, opt->prefix, opt->prefix_length)))
5655
return;
5756

58-
one = alloc_filespec(old_name);
59-
two = alloc_filespec(new_name);
57+
one = alloc_filespec(old_path);
58+
two = alloc_filespec(new_path);
6059
fill_filespec(one, old_oid->hash, old_oid_valid, old_mode);
6160
fill_filespec(two, new_oid->hash, new_oid_valid, new_mode);
6261

@@ -65,7 +64,7 @@ static void stuff_change(struct diff_options *opt,
6564

6665
static int builtin_diff_b_f(struct rev_info *revs,
6766
int argc, const char **argv,
68-
struct blobinfo *blob)
67+
struct object_array_entry **blob)
6968
{
7069
/* Blob vs file in the working tree*/
7170
struct stat st;
@@ -84,39 +83,40 @@ static int builtin_diff_b_f(struct rev_info *revs,
8483

8584
diff_set_mnemonic_prefix(&revs->diffopt, "o/", "w/");
8685

87-
if (blob[0].mode == S_IFINVALID)
88-
blob[0].mode = canon_mode(st.st_mode);
86+
if (blob[0]->mode == S_IFINVALID)
87+
blob[0]->mode = canon_mode(st.st_mode);
8988

9089
stuff_change(&revs->diffopt,
91-
blob[0].mode, canon_mode(st.st_mode),
92-
&blob[0].oid, &null_oid,
90+
blob[0]->mode, canon_mode(st.st_mode),
91+
&blob[0]->item->oid, &null_oid,
9392
1, 0,
94-
path, path);
93+
blob[0]->path ? blob[0]->path : path,
94+
path);
9595
diffcore_std(&revs->diffopt);
9696
diff_flush(&revs->diffopt);
9797
return 0;
9898
}
9999

100100
static int builtin_diff_blobs(struct rev_info *revs,
101101
int argc, const char **argv,
102-
struct blobinfo *blob)
102+
struct object_array_entry **blob)
103103
{
104104
unsigned mode = canon_mode(S_IFREG | 0644);
105105

106106
if (argc > 1)
107107
usage(builtin_diff_usage);
108108

109-
if (blob[0].mode == S_IFINVALID)
110-
blob[0].mode = mode;
109+
if (blob[0]->mode == S_IFINVALID)
110+
blob[0]->mode = mode;
111111

112-
if (blob[1].mode == S_IFINVALID)
113-
blob[1].mode = mode;
112+
if (blob[1]->mode == S_IFINVALID)
113+
blob[1]->mode = mode;
114114

115115
stuff_change(&revs->diffopt,
116-
blob[0].mode, blob[1].mode,
117-
&blob[0].oid, &blob[1].oid,
116+
blob[0]->mode, blob[1]->mode,
117+
&blob[0]->item->oid, &blob[1]->item->oid,
118118
1, 1,
119-
blob[0].name, blob[1].name);
119+
blob_path(blob[0]), blob_path(blob[1]));
120120
diffcore_std(&revs->diffopt);
121121
diff_flush(&revs->diffopt);
122122
return 0;
@@ -259,7 +259,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
259259
struct rev_info rev;
260260
struct object_array ent = OBJECT_ARRAY_INIT;
261261
int blobs = 0, paths = 0;
262-
struct blobinfo blob[2];
262+
struct object_array_entry *blob[2];
263263
int nongit = 0, no_index = 0;
264264
int result = 0;
265265

@@ -408,9 +408,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
408408
} else if (obj->type == OBJ_BLOB) {
409409
if (2 <= blobs)
410410
die(_("more than two blobs given: '%s'"), name);
411-
oidcpy(&blob[blobs].oid, &obj->oid);
412-
blob[blobs].name = name;
413-
blob[blobs].mode = entry->mode;
411+
blob[blobs] = entry;
414412
blobs++;
415413

416414
} else {

builtin/grep.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1190,7 +1190,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
11901190
break;
11911191
}
11921192

1193-
if (get_sha1_with_context(arg, 0, oid.hash, &oc)) {
1193+
if (get_sha1_with_context(arg, GET_SHA1_RECORD_PATH,
1194+
oid.hash, &oc)) {
11941195
if (seen_dashdash)
11951196
die(_("unable to resolve revision: %s"), arg);
11961197
break;
@@ -1200,6 +1201,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
12001201
if (!seen_dashdash)
12011202
verify_non_filename(prefix, arg);
12021203
add_object_array_with_path(object, arg, &list, oc.mode, oc.path);
1204+
free(oc.path);
12031205
}
12041206

12051207
/*

builtin/log.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -483,16 +483,20 @@ static int show_blob_object(const struct object_id *oid, struct rev_info *rev, c
483483
!DIFF_OPT_TST(&rev->diffopt, ALLOW_TEXTCONV))
484484
return stream_blob_to_fd(1, oid, NULL, 0);
485485

486-
if (get_sha1_with_context(obj_name, 0, oidc.hash, &obj_context))
486+
if (get_sha1_with_context(obj_name, GET_SHA1_RECORD_PATH,
487+
oidc.hash, &obj_context))
487488
die(_("Not a valid object name %s"), obj_name);
488-
if (!obj_context.path[0] ||
489-
!textconv_object(obj_context.path, obj_context.mode, &oidc, 1, &buf, &size))
489+
if (!obj_context.path ||
490+
!textconv_object(obj_context.path, obj_context.mode, &oidc, 1, &buf, &size)) {
491+
free(obj_context.path);
490492
return stream_blob_to_fd(1, oid, NULL, 0);
493+
}
491494

492495
if (!buf)
493496
die(_("git show %s: bad file"), obj_name);
494497

495498
write_or_die(1, buf, size);
499+
free(obj_context.path);
496500
return 0;
497501
}
498502

cache.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,13 +1334,18 @@ static inline int hex2chr(const char *s)
13341334

13351335
struct object_context {
13361336
unsigned char tree[20];
1337-
char path[PATH_MAX];
13381337
unsigned mode;
13391338
/*
13401339
* symlink_path is only used by get_tree_entry_follow_symlinks,
13411340
* and only for symlinks that point outside the repository.
13421341
*/
13431342
struct strbuf symlink_path;
1343+
/*
1344+
* If GET_SHA1_RECORD_PATH is set, this will record path (if any)
1345+
* found when resolving the name. The caller is responsible for
1346+
* releasing the memory.
1347+
*/
1348+
char *path;
13441349
};
13451350

13461351
#define GET_SHA1_QUIETLY 01
@@ -1350,6 +1355,7 @@ struct object_context {
13501355
#define GET_SHA1_TREEISH 020
13511356
#define GET_SHA1_BLOB 040
13521357
#define GET_SHA1_FOLLOW_SYMLINKS 0100
1358+
#define GET_SHA1_RECORD_PATH 0200
13531359
#define GET_SHA1_ONLY_TO_DIE 04000
13541360

13551361
#define GET_SHA1_DISAMBIGUATORS \
@@ -1364,7 +1370,7 @@ extern int get_sha1_tree(const char *str, unsigned char *sha1);
13641370
extern int get_sha1_treeish(const char *str, unsigned char *sha1);
13651371
extern int get_sha1_blob(const char *str, unsigned char *sha1);
13661372
extern void maybe_die_on_misspelt_object_name(const char *name, const char *prefix);
1367-
extern int get_sha1_with_context(const char *str, unsigned flags, unsigned char *sha1, struct object_context *orc);
1373+
extern int get_sha1_with_context(const char *str, unsigned flags, unsigned char *sha1, struct object_context *oc);
13681374

13691375
extern int get_oid(const char *str, struct object_id *oid);
13701376

0 commit comments

Comments
 (0)