Skip to content

Commit 76277be

Browse files
committed
Add support for SHA-256 repositories
Use variable extensions.objectformat, if available, to determine the length of the hash id in the current repository.
1 parent b5f6193 commit 76277be

26 files changed

+309
-40
lines changed

doc/manual.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@ following variables.
205205
|%(repo:is-inside-work-tree)
206206
|Whether Tig is running inside a work tree,
207207
either `true` or `false`.
208+
|%(repo:object-format) |The hash algorithm used for the repository, e.g. `sha1`
209+
or `sha256`.
208210
|=============================================================================
209211

210212
Example user-defined commands:

include/tig/main.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include "tig/util.h"
2020

2121
struct commit {
22-
char id[SIZEOF_REV]; /* SHA1 ID. */
22+
char id[SIZEOF_REV]; /* Hash ID. */
2323
const struct ident *author; /* Author of the commit. */
2424
struct time time; /* Date from the author ident. */
2525
struct graph_canvas graph; /* Ancestry chain graphics. */

include/tig/parse.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,17 @@ bool parse_chunk_header(struct chunk_header *header, const char *line);
3131
bool parse_chunk_lineno(unsigned long *lineno, const char *chunk, int marker);
3232

3333
struct blame_commit {
34-
char id[SIZEOF_REV]; /* SHA1 ID. */
34+
char id[SIZEOF_REV]; /* Hash ID. */
3535
char title[128]; /* First line of the commit message. */
3636
const struct ident *author; /* Author of the commit. */
3737
struct time time; /* Date from the author ident. */
3838
const char *filename; /* Name of file. */
39-
char parent_id[SIZEOF_REV]; /* Parent/previous SHA1 ID. */
39+
char parent_id[SIZEOF_REV]; /* Parent/previous hash ID. */
4040
const char *parent_filename; /* Parent/previous name of file. */
4141
};
4242

4343
struct blame_header {
44-
char id[SIZEOF_REV]; /* SHA1 ID. */
44+
char id[SIZEOF_REV]; /* Hash ID. */
4545
size_t orig_lineno;
4646
size_t lineno;
4747
size_t group;

include/tig/refdb.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,20 @@
1717
#include "tig/tig.h"
1818
#include "tig/types.h"
1919
#include "tig/util.h"
20+
#include "tig/repo.h"
2021

2122
struct argv_env;
2223

2324
struct ref {
2425
struct ref *next;
2526
enum reference_type type;
26-
char id[SIZEOF_REV]; /* Commit SHA1 ID */
27+
char id[SIZEOF_REV]; /* Commit hash ID */
2728
unsigned int valid:1; /* Is the ref still valid? */
2829
char name[1]; /* Ref name; tag or head names are shortened. */
2930
};
3031

3132
#define is_initial_commit() (!get_ref_head())
32-
#define is_head_commit(rev) (!strcmp((rev), "HEAD") || (get_ref_head() && !strncmp(rev, get_ref_head()->id, SIZEOF_REV - 1)))
33+
#define is_head_commit(rev) (!strcmp((rev), "HEAD") || (get_ref_head() && !strncmp(rev, get_ref_head()->id, REPO_INFO_SIZEOF_REV - 1)))
3334
#define ref_is_tag(ref) ((ref)->type == REFERENCE_TAG || (ref)->type == REFERENCE_LOCAL_TAG)
3435
#define ref_is_remote(ref) ((ref)->type == REFERENCE_REMOTE || (ref)->type == REFERENCE_TRACKED_REMOTE)
3536

include/tig/repo.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,21 @@
1616

1717
#include "tig/tig.h"
1818

19+
typedef enum {
20+
REPO_INFO_SHA1 = 40,
21+
REPO_INFO_SHA256 = 64
22+
} repo_object_format;
23+
24+
/* Holds a hash ID and an ending NUL. */
25+
#define REPO_INFO_SIZEOF_REV (repo.object_format + 1)
26+
1927
typedef char repo_ref[SIZEOF_REF];
2028
typedef char repo_rev[SIZEOF_REV];
2129
typedef char repo_str[SIZEOF_STR];
2230

31+
/* Leave object_format in first position. */
2332
#define REPO_INFO(_) \
33+
_(repo_object_format, object_format) \
2434
_(repo_ref, head) \
2535
_(repo_rev, head_id) \
2636
_(repo_ref, remote) \

include/tig/string.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ void string_ncopy_do(char *dst, size_t dstlen, const char *src, size_t srclen);
8585
void string_copy_rev(char *dst, const char *src);
8686
void string_copy_rev_from_commit_line(char *dst, const char *src);
8787

88-
#define string_rev_is_null(rev) !strncmp(rev, NULL_ID, STRING_SIZE(NULL_ID))
88+
#define string_rev_is_null(rev) !strncmp(rev, NULL_ID, REPO_INFO_SIZEOF_REV - 1)
8989

9090
#define string_add(dst, from, src) \
9191
string_ncopy_do(dst + (from), sizeof(dst) - (from), src, sizeof(src))

include/tig/tig.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,8 @@
150150

151151
#define SIZEOF_STR 1024 /* Default string size. */
152152
#define SIZEOF_MED_STR 8192 /* Medium string size. */
153-
#define SIZEOF_REF 256 /* Size of symbolic or SHA1 ID. */
154-
#define SIZEOF_REV 41 /* Holds a SHA-1 and an ending NUL. */
153+
#define SIZEOF_REF 256 /* Size of symbolic or hash ID. */
154+
#define SIZEOF_REV 65 /* Holds a SHA-1 or SHA-256 and an ending NUL. */
155155

156156
/* This color name can be used to refer to the default term colors. */
157157
#define COLOR_DEFAULT (-1)
@@ -166,7 +166,7 @@
166166
#define MIN_VIEW_WIDTH 4
167167
#define VSPLIT_SCALE 0.5
168168

169-
#define NULL_ID "0000000000000000000000000000000000000000"
169+
#define NULL_ID "0000000000000000000000000000000000000000000000000000000000000000"
170170

171171
#define S_ISGITLINK(mode) (((mode) & S_IFMT) == 0160000)
172172

src/argv.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,14 @@ bool_formatter(struct format_context *format, struct format_var *var)
415415
return string_format_from(format->buf, &format->bufpos, "%s", value ? "true" : "false");
416416
}
417417

418+
static bool
419+
repo_object_format_formatter(struct format_context *format, struct format_var *var)
420+
{
421+
repo_object_format value = *(repo_object_format *)var->value_ref;
422+
423+
return string_format_from(format->buf, &format->bufpos, "%s", value == REPO_INFO_SHA256 ? "sha256" : "sha1");
424+
}
425+
418426
static bool
419427
repo_str_formatter(struct format_context *format, struct format_var *var)
420428
{

src/blame.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
*/
2929

3030
struct blame_history_state {
31-
char id[SIZEOF_REV]; /* SHA1 ID. */
31+
char id[SIZEOF_REV]; /* Hash ID. */
3232
const char *filename; /* Name of file. */
3333
};
3434

@@ -187,15 +187,15 @@ get_blame_commit(struct view *view, const char *id)
187187
if (!blame->commit)
188188
continue;
189189

190-
if (!strncmp(blame->commit->id, id, SIZEOF_REV - 1))
190+
if (!strncmp(blame->commit->id, id, REPO_INFO_SIZEOF_REV - 1))
191191
return blame->commit;
192192
}
193193

194194
{
195195
struct blame_commit *commit = calloc(1, sizeof(*commit));
196196

197197
if (commit)
198-
string_ncopy(commit->id, id, SIZEOF_REV);
198+
string_copy_rev(commit->id, id);
199199
return commit;
200200
}
201201
}

src/draw.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "tig/graph.h"
1616
#include "tig/draw.h"
1717
#include "tig/options.h"
18+
#include "tig/repo.h"
1819
#include "compat/hashtab.h"
1920

2021
static const enum line_type palette_colors[] = {
@@ -267,7 +268,7 @@ draw_id(struct view *view, struct view_column *column, const char *id)
267268
return false;
268269

269270
if (column->opt.id.color && id) {
270-
hashval_t color = iterative_hash(id, SIZEOF_REV - 1, 0);
271+
hashval_t color = iterative_hash(id, REPO_INFO_SIZEOF_REV - 1, 0);
271272

272273
type = palette_colors[color % ARRAY_SIZE(palette_colors)];
273274
}

src/graph-v1.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ struct graph_symbol {
3232

3333
struct graph_column {
3434
struct graph_symbol symbol;
35-
char id[SIZEOF_REV]; /* Parent SHA1 ID. */
35+
char id[SIZEOF_REV]; /* Parent hash ID. */
3636
};
3737

3838
struct graph_row {

src/graph-v2.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ struct graph_symbol {
4848

4949
struct graph_column {
5050
struct graph_symbol symbol;
51-
const char *id; /* Parent SHA1 ID. */
51+
const char *id; /* Parent hash ID. */
5252
};
5353

5454
struct graph_row {

src/main.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ main_add_commit(struct view *view, enum line_type type, struct commit *template,
100100

101101
view_column_info_update(view, line);
102102

103-
if (view->env->goto_id[0] && !strncmp(view->env->goto_id, commit->id, SIZEOF_REV - 1)) {
103+
if (view->env->goto_id[0] && !strncmp(view->env->goto_id, commit->id, REPO_INFO_SIZEOF_REV - 1)) {
104104
select_view_line(view, line->lineno + 1);
105105
view->env->goto_id[0] = 0;
106106
} else if (opt_start_on_head && is_head_commit(commit->id)) {
@@ -121,7 +121,7 @@ main_flush_commit(struct view *view, struct commit *commit)
121121
static bool
122122
main_add_changes_commit(struct view *view, enum line_type type, const char *parent, const char *title)
123123
{
124-
char ids[SIZEOF_STR] = NULL_ID " ";
124+
char ids[SIZEOF_STR] = NULL_ID;
125125
struct main_state *state = view->private;
126126
struct graph *graph = state->graph;
127127
struct commit commit = {{0}};
@@ -131,10 +131,11 @@ main_add_changes_commit(struct view *view, enum line_type type, const char *pare
131131
if (!parent)
132132
return true;
133133

134-
if (*parent)
135-
string_copy_rev(ids + STRING_SIZE(NULL_ID " "), parent);
136-
else
137-
ids[STRING_SIZE(NULL_ID)] = 0;
134+
if (*parent) {
135+
ids[REPO_INFO_SIZEOF_REV - 1] = ' ';
136+
string_copy_rev(ids + REPO_INFO_SIZEOF_REV, parent);
137+
} else
138+
ids[REPO_INFO_SIZEOF_REV - 1] = 0;
138139

139140
if (!time_now(&now, &tz)) {
140141
commit.time.tz = tz.tz_minuteswest * 60;

src/options.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -723,9 +723,16 @@ parse_option(struct option_info *option, const char *prefix, const char *arg)
723723
if (!strcmp(name, "line-number-interval") ||
724724
!strcmp(name, "tab-size"))
725725
return parse_int(option->value, arg, 1, 1024);
726-
else if (!strcmp(name, "id-width"))
727-
return parse_int(option->value, arg, 0, SIZEOF_REV - 1);
728-
else
726+
else if (!strcmp(name, "id-width")) {
727+
enum status_code code = parse_int(option->value, arg, 0, SIZEOF_REV - 1);
728+
if (code == SUCCESS) {
729+
int *value = option->value;
730+
/* Limit id-width to the length of the hash used for the repository. */
731+
if (*value > REPO_INFO_SIZEOF_REV - 1)
732+
*value = REPO_INFO_SIZEOF_REV - 1;
733+
}
734+
return code;
735+
} else
729736
return parse_int(option->value, arg, 0, 1024);
730737
}
731738

@@ -1548,8 +1555,15 @@ read_repo_config_option(char *name, size_t namelen, char *value, size_t valuelen
15481555
else if (!strcmp(name, "core.worktree"))
15491556
string_ncopy(repo.worktree, value, valuelen);
15501557

1551-
else if (!strcmp(name, "core.abbrev"))
1552-
parse_int(&opt_id_width, value, 0, SIZEOF_REV - 1);
1558+
else if (!strcmp(name, "core.abbrev")) {
1559+
/* We cannot use REPO_INFO_SIZEOF_REV until we parse extensions.objectformat. */
1560+
if (!strcmp(value, "no"))
1561+
opt_id_width = SIZEOF_REV - 1;
1562+
else if (strcmp(value, "auto"))
1563+
parse_int(&opt_id_width, value, 0, SIZEOF_REV - 1);
1564+
1565+
} else if (!strcmp(name, "extensions.objectformat"))
1566+
repo.object_format = !strcmp(value, "sha256") ? REPO_INFO_SHA256 : REPO_INFO_SHA1;
15531567

15541568
else if (!strcmp(name, "diff.noprefix")) {
15551569
if (!find_option_info_by_value(&opt_diff_noprefix)->seen)
@@ -1599,6 +1613,10 @@ load_git_config(void)
15991613

16001614
code = io_run_load(&io, config_list_argv, "=", read_repo_config_option, NULL);
16011615

1616+
/* Limit id-width to the length of the hash used for the repository. */
1617+
if (opt_id_width > REPO_INFO_SIZEOF_REV - 1)
1618+
opt_id_width = REPO_INFO_SIZEOF_REV - 1;
1619+
16021620
if (git_worktree && *git_worktree)
16031621
string_ncopy(repo.worktree, git_worktree, strlen(git_worktree));
16041622

src/parse.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "tig/tig.h"
1515
#include "tig/parse.h"
1616
#include "tig/map.h"
17+
#include "tig/repo.h"
1718

1819
size_t
1920
parse_size(const char *text)
@@ -110,12 +111,12 @@ parse_number(const char **posref, size_t *number)
110111
bool
111112
parse_blame_header(struct blame_header *header, const char *text)
112113
{
113-
const char *pos = text + SIZEOF_REV - 2;
114+
const char *pos = text + REPO_INFO_SIZEOF_REV - 2;
114115

115-
if (strlen(text) <= SIZEOF_REV || pos[1] != ' ')
116+
if (strlen(text) <= REPO_INFO_SIZEOF_REV || pos[1] != ' ')
116117
return false;
117118

118-
string_ncopy(header->id, text, SIZEOF_REV);
119+
string_copy_rev(header->id, text);
119120

120121
if (!parse_number(&pos, &header->orig_lineno) ||
121122
!parse_number(&pos, &header->lineno))
@@ -164,10 +165,10 @@ parse_blame_info(struct blame_commit *commit, char author[SIZEOF_STR], char *lin
164165
string_ncopy(commit->title, line, strlen(line));
165166

166167
} else if (match_blame_header("previous ", &line)) {
167-
if (strlen(line) <= SIZEOF_REV)
168+
if (strlen(line) <= REPO_INFO_SIZEOF_REV)
168169
return false;
169170
string_copy_rev(commit->parent_id, line);
170-
line += SIZEOF_REV;
171+
line += REPO_INFO_SIZEOF_REV;
171172
commit->parent_filename = get_path(line);
172173
if (!commit->parent_filename)
173174
return true;

src/refdb.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ add_to_refs(const char *id, size_t idlen, char *name, size_t namelen, struct ref
249249
}
250250

251251
/* If we are reloading or it's an annotated tag, replace the
252-
* previous SHA1 with the resolved commit id; relies on the fact
252+
* previous hash with the resolved commit id; relies on the fact
253253
* git-ls-remote lists the commit id of an annotated tag right
254254
* before the commit id it points to. */
255255
if (type == REFERENCE_REPLACE) {
@@ -279,7 +279,7 @@ add_to_refs(const char *id, size_t idlen, char *name, size_t namelen, struct ref
279279

280280
ref->valid = true;
281281
ref->type = type;
282-
string_ncopy_do(ref->id, SIZEOF_REV, id, idlen);
282+
string_ncopy_do(ref->id, REPO_INFO_SIZEOF_REV, id, idlen);
283283

284284
if (type == REFERENCE_HEAD) {
285285
if (!refs_head ||

src/repo.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ read_repo_info(char *name, size_t namelen, char *value, size_t valuelen, void *d
5757
* this special case by looking at the emitted value. If it looks
5858
* like a commit ID and there's no cdup path assume that no value
5959
* was emitted. */
60-
if (!*repo.cdup && namelen == 40 && iscommit(name))
60+
if (!*repo.cdup && namelen == REPO_INFO_SIZEOF_REV - 1 && iscommit(name))
6161
return read_repo_info(name, namelen, value, valuelen, data);
6262

6363
string_ncopy(repo.prefix, name, namelen);
@@ -105,6 +105,8 @@ load_repo_info(void)
105105
};
106106

107107
memset(&repo, 0, sizeof(repo));
108+
/* defaults to SHA-1 as older Git versions don't have extensions.objectFormat */
109+
repo.object_format = REPO_INFO_SHA1;
108110
return reload_repo_info(rev_parse_argv);
109111
}
110112

src/status.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ status_run(struct view *view, const char *argv[], char status, enum line_type ty
111111
if (status) {
112112
file->status = status;
113113
if (status == 'A')
114-
string_copy(file->old.rev, NULL_ID);
114+
string_copy_rev(file->old.rev, NULL_ID);
115115

116116
} else {
117117
if (!status_get_diff(&parsed, buf.data, buf.size))

src/string.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "tig/tig.h"
1515
#include "tig/string.h"
16+
#include "tig/repo.h"
1617
#include "compat/utf8proc.h"
1718

1819
/*
@@ -42,7 +43,7 @@ iscommit(const char *str)
4243
return false;
4344
}
4445

45-
return 7 <= pos && pos < SIZEOF_REV;
46+
return 7 <= pos && pos < REPO_INFO_SIZEOF_REV;
4647
}
4748

4849
int
@@ -72,11 +73,11 @@ string_copy_rev(char *dst, const char *src)
7273
if (!*src)
7374
return;
7475

75-
for (srclen = 0; srclen < SIZEOF_REV; srclen++)
76+
for (srclen = 0; srclen < REPO_INFO_SIZEOF_REV; srclen++)
7677
if (!src[srclen] || isspace((unsigned char)src[srclen]))
7778
break;
7879

79-
string_ncopy_do(dst, SIZEOF_REV, src, srclen);
80+
string_ncopy_do(dst, REPO_INFO_SIZEOF_REV, src, srclen);
8081
}
8182

8283
void

0 commit comments

Comments
 (0)