Skip to content

Commit 47dd0d5

Browse files
author
Junio C Hamano
committed
diff: --abbrev option
When I show transcripts to explain how something works, I often find myself hand-editing the diff-raw output to shorten various object names in the output. This adds --abbrev option to the diff family, which shortens diff-raw output and diff-tree commit id headers. Signed-off-by: Junio C Hamano <junkio@cox.net>
1 parent 1c15afb commit 47dd0d5

File tree

5 files changed

+93
-23
lines changed

5 files changed

+93
-23
lines changed

Documentation/diff-options.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@
1818
object name of pre- and post-image blob on the "index"
1919
line when generating a patch format output.
2020

21+
--abbrev::
22+
Instead of showing the full 40-byte hexadecimal object
23+
name in diff-raw format output and diff-tree header
24+
lines, show only handful prefix. This is independent of
25+
--full-index option above, which controls the diff-patch
26+
output format.
27+
2128
-B::
2229
Break complete rewrite changes into pairs of delete and create.
2330

diff-tree.c

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,6 @@ static enum cmit_fmt commit_format = CMIT_FMT_RAW;
1414

1515
static struct diff_options diff_options;
1616

17-
static void call_diff_setup_done(void)
18-
{
19-
diff_setup_done(&diff_options);
20-
}
21-
2217
static int call_diff_flush(void)
2318
{
2419
diffcore_std(&diff_options);
@@ -43,7 +38,6 @@ static int diff_tree_sha1_top(const unsigned char *old,
4338
{
4439
int ret;
4540

46-
call_diff_setup_done();
4741
ret = diff_tree_sha1(old, new, base, &diff_options);
4842
call_diff_flush();
4943
return ret;
@@ -55,7 +49,6 @@ static int diff_root_tree(const unsigned char *new, const char *base)
5549
void *tree;
5650
struct tree_desc empty, real;
5751

58-
call_diff_setup_done();
5952
tree = read_object_with_reference(new, "tree", &real.size, NULL);
6053
if (!tree)
6154
die("unable to read root tree (%s)", sha1_to_hex(new));
@@ -69,18 +62,29 @@ static int diff_root_tree(const unsigned char *new, const char *base)
6962
return retval;
7063
}
7164

72-
static const char *generate_header(const char *commit, const char *parent, const char *msg)
65+
static const char *generate_header(const unsigned char *commit_sha1,
66+
const unsigned char *parent_sha1,
67+
const char *msg)
7368
{
7469
static char this_header[16384];
7570
int offset;
7671
unsigned long len;
72+
int abbrev = diff_options.abbrev;
7773

7874
if (!verbose_header)
79-
return commit;
75+
return sha1_to_hex(commit_sha1);
8076

8177
len = strlen(msg);
82-
offset = sprintf(this_header, "%s%s (from %s)\n", header_prefix, commit, parent);
83-
offset += pretty_print_commit(commit_format, msg, len, this_header + offset, sizeof(this_header) - offset);
78+
79+
offset = sprintf(this_header, "%s%s ",
80+
header_prefix,
81+
diff_unique_abbrev(commit_sha1, abbrev));
82+
offset += sprintf(this_header + offset, "(from %s)\n",
83+
parent_sha1 ?
84+
diff_unique_abbrev(parent_sha1, abbrev) : "root");
85+
offset += pretty_print_commit(commit_format, msg, len,
86+
this_header + offset,
87+
sizeof(this_header) - offset);
8488
return this_header;
8589
}
8690

@@ -99,18 +103,18 @@ static int diff_tree_commit(const unsigned char *commit_sha1)
99103

100104
/* Root commit? */
101105
if (show_root_diff && !commit->parents) {
102-
header = generate_header(name, "root", commit->buffer);
106+
header = generate_header(sha1, NULL, commit->buffer);
103107
diff_root_tree(commit_sha1, "");
104108
}
105109

106110
/* More than one parent? */
107111
if (ignore_merges && commit->parents && commit->parents->next)
108-
return 0;
112+
return 0;
109113

110114
for (parents = commit->parents; parents; parents = parents->next) {
111115
struct commit *parent = parents->item;
112-
header = generate_header(name,
113-
sha1_to_hex(parent->object.sha1),
116+
header = generate_header(sha1,
117+
parent->object.sha1,
114118
commit->buffer);
115119
diff_tree_sha1_top(parent->object.sha1, commit_sha1, "");
116120
if (!header && verbose_header) {
@@ -129,6 +133,7 @@ static int diff_tree_stdin(char *line)
129133
int len = strlen(line);
130134
unsigned char commit[20], parent[20];
131135
static char this_header[1000];
136+
int abbrev = diff_options.abbrev;
132137

133138
if (!len || line[len-1] != '\n')
134139
return -1;
@@ -138,7 +143,9 @@ static int diff_tree_stdin(char *line)
138143
if (isspace(line[40]) && !get_sha1_hex(line+41, parent)) {
139144
line[40] = 0;
140145
line[81] = 0;
141-
sprintf(this_header, "%s (from %s)\n", line, line+41);
146+
sprintf(this_header, "%s (from %s)\n",
147+
diff_unique_abbrev(commit, abbrev),
148+
diff_unique_abbrev(parent, abbrev));
142149
header = this_header;
143150
return diff_tree_sha1_top(parent, commit, "");
144151
}
@@ -239,6 +246,7 @@ int main(int argc, const char **argv)
239246
diff_options.recursive = 1;
240247

241248
diff_tree_setup_paths(get_pathspec(prefix, argv));
249+
diff_setup_done(&diff_options);
242250

243251
switch (nr_sha1) {
244252
case 0:

diff.c

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -723,11 +723,13 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
723723

724724
if (memcmp(one->sha1, two->sha1, 20)) {
725725
char one_sha1[41];
726-
const char *index_fmt = o->full_index ? "index %s..%s" : "index %.7s..%.7s";
726+
int abbrev = o->full_index ? 40 : DIFF_DEFAULT_INDEX_ABBREV;
727727
memcpy(one_sha1, sha1_to_hex(one->sha1), 41);
728728

729729
len += snprintf(msg + len, sizeof(msg) - len,
730-
index_fmt, one_sha1, sha1_to_hex(two->sha1));
730+
"index %.*s..%.*s",
731+
abbrev, one_sha1, abbrev,
732+
sha1_to_hex(two->sha1));
731733
if (one->mode == two->mode)
732734
len += snprintf(msg + len, sizeof(msg) - len,
733735
" %06o", one->mode);
@@ -791,6 +793,8 @@ int diff_setup_done(struct diff_options *options)
791793
}
792794
if (options->setup & DIFF_SETUP_USE_SIZE_CACHE)
793795
use_size_cache = 1;
796+
if (options->abbrev <= 0 || 40 < options->abbrev)
797+
options->abbrev = 40; /* full */
794798

795799
return 0;
796800
}
@@ -841,6 +845,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
841845
}
842846
else if (!strcmp(arg, "--find-copies-harder"))
843847
options->find_copies_harder = 1;
848+
else if (!strcmp(arg, "--abbrev"))
849+
options->abbrev = DIFF_DEFAULT_ABBREV;
850+
else if (!strncmp(arg, "--abbrev=", 9))
851+
options->abbrev = strtoul(arg + 9, NULL, 10);
844852
else
845853
return 0;
846854
return 1;
@@ -947,14 +955,49 @@ void diff_free_filepair(struct diff_filepair *p)
947955
free(p);
948956
}
949957

958+
/* This is different from find_unique_abbrev() in that
959+
* it needs to deal with 0{40} SHA1.
960+
*/
961+
const char *diff_unique_abbrev(const unsigned char *sha1, int len)
962+
{
963+
int abblen;
964+
const char *abbrev;
965+
if (len == 40)
966+
return sha1_to_hex(sha1);
967+
968+
abbrev = find_unique_abbrev(sha1, len);
969+
if (!abbrev) {
970+
if (!memcmp(sha1, null_sha1, 20)) {
971+
char *buf = sha1_to_hex(null_sha1);
972+
if (len < 37)
973+
strcpy(buf + len, "...");
974+
return buf;
975+
}
976+
else
977+
return sha1_to_hex(sha1);
978+
}
979+
abblen = strlen(abbrev);
980+
if (abblen < 37) {
981+
static char hex[41];
982+
if (len < abblen && abblen <= len + 2)
983+
sprintf(hex, "%s%.*s", abbrev, len+3-abblen, "..");
984+
else
985+
sprintf(hex, "%s...", abbrev);
986+
return hex;
987+
}
988+
return sha1_to_hex(sha1);
989+
}
990+
950991
static void diff_flush_raw(struct diff_filepair *p,
951992
int line_termination,
952993
int inter_name_termination,
953-
int output_format)
994+
struct diff_options *options)
954995
{
955996
int two_paths;
956997
char status[10];
998+
int abbrev = options->abbrev;
957999
const char *path_one, *path_two;
1000+
int output_format = options->output_format;
9581001

9591002
path_one = p->one->path;
9601003
path_two = p->two->path;
@@ -985,8 +1028,10 @@ static void diff_flush_raw(struct diff_filepair *p,
9851028
}
9861029
if (output_format != DIFF_FORMAT_NAME_STATUS) {
9871030
printf(":%06o %06o %s ",
988-
p->one->mode, p->two->mode, sha1_to_hex(p->one->sha1));
989-
printf("%s ", sha1_to_hex(p->two->sha1));
1031+
p->one->mode, p->two->mode,
1032+
diff_unique_abbrev(p->one->sha1, abbrev));
1033+
printf("%s ",
1034+
diff_unique_abbrev(p->two->sha1, abbrev));
9901035
}
9911036
printf("%s%c%s", status, inter_name_termination, path_one);
9921037
if (two_paths)
@@ -1194,7 +1239,7 @@ void diff_flush(struct diff_options *options)
11941239
case DIFF_FORMAT_NAME_STATUS:
11951240
diff_flush_raw(p, line_termination,
11961241
inter_name_termination,
1197-
diff_output_format);
1242+
options);
11981243
break;
11991244
case DIFF_FORMAT_NAME:
12001245
diff_flush_name(p,

diff.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ struct diff_options {
4444
int reverse_diff;
4545
int rename_limit;
4646
int setup;
47+
int abbrev;
4748

4849
change_fn_t change;
4950
add_remove_fn_t add_remove;
@@ -87,6 +88,9 @@ extern int diff_setup_done(struct diff_options *);
8788

8889
#define DIFF_PICKAXE_ALL 1
8990

91+
#define DIFF_DEFAULT_INDEX_ABBREV 7 /* hex digits */
92+
#define DIFF_DEFAULT_ABBREV 7 /* hex digits */
93+
9094
extern void diffcore_std(struct diff_options *);
9195

9296
extern void diffcore_std_no_resolve(struct diff_options *);
@@ -98,7 +102,8 @@ extern void diffcore_std_no_resolve(struct diff_options *);
98102
" -u synonym for -p.\n" \
99103
" --name-only show only names of changed files.\n" \
100104
" --name-status show names and status of changed files.\n" \
101-
" --full-index show full object name on index ines.\n" \
105+
" --full-index show full object name on index lines.\n" \
106+
" --abbrev abbreviate object names in diff-tree header and diff-raw.\n" \
102107
" -R swap input file pairs.\n" \
103108
" -B detect complete rewrites.\n" \
104109
" -M detect renames.\n" \
@@ -137,4 +142,6 @@ extern void diff_flush(struct diff_options*);
137142
#define DIFF_STATUS_FILTER_AON '*'
138143
#define DIFF_STATUS_FILTER_BROKEN 'B'
139144

145+
extern const char *diff_unique_abbrev(const unsigned char *, int);
146+
140147
#endif /* DIFF_H */

sha1_name.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,10 @@ const char *find_unique_abbrev(const unsigned char *sha1, int len)
188188
{
189189
int status;
190190
static char hex[41];
191+
191192
memcpy(hex, sha1_to_hex(sha1), 40);
193+
if (len == 40)
194+
return hex;
192195
while (len < 40) {
193196
unsigned char sha1_ret[20];
194197
status = get_short_sha1(hex, len, sha1_ret, 1);

0 commit comments

Comments
 (0)