Skip to content

Commit 357af1a

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 d4a13ff commit 357af1a

26 files changed

+309
-40
lines changed

doc/manual.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ following variables.
203203
|%(repo:is-inside-work-tree)
204204
|Whether Tig is running inside a work tree,
205205
either `true` or `false`.
206+
|%(repo:object-format) |The hash algorithm used for the repository, e.g. `sha1`
207+
or `sha256`.
206208
|=============================================================================
207209

208210
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
@@ -148,8 +148,8 @@
148148

149149
#define SIZEOF_STR 1024 /* Default string size. */
150150
#define SIZEOF_MED_STR 8192 /* Medium string size. */
151-
#define SIZEOF_REF 256 /* Size of symbolic or SHA1 ID. */
152-
#define SIZEOF_REV 41 /* Holds a SHA-1 and an ending NUL. */
151+
#define SIZEOF_REF 256 /* Size of symbolic or hash ID. */
152+
#define SIZEOF_REV 65 /* Holds a SHA-1 or SHA-256 and an ending NUL. */
153153

154154
/* This color name can be used to refer to the default term colors. */
155155
#define COLOR_DEFAULT (-1)
@@ -164,7 +164,7 @@
164164
#define MIN_VIEW_WIDTH 4
165165
#define VSPLIT_SCALE 0.5
166166

167-
#define NULL_ID "0000000000000000000000000000000000000000"
167+
#define NULL_ID "0000000000000000000000000000000000000000000000000000000000000000"
168168

169169
#define S_ISGITLINK(mode) (((mode) & S_IFMT) == 0160000)
170170

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
@@ -101,7 +101,7 @@ main_add_commit(struct view *view, enum line_type type, struct commit *template,
101101
view_column_info_update(view, line);
102102

103103
if ((opt_start_on_head && is_head_commit(commit->id)) ||
104-
(view->env->goto_id[0] && !strncmp(view->env->goto_id, commit->id, SIZEOF_REV - 1)))
104+
(view->env->goto_id[0] && !strncmp(view->env->goto_id, commit->id, REPO_INFO_SIZEOF_REV - 1)))
105105
select_view_line(view, line->lineno + 1);
106106

107107
return commit;
@@ -117,7 +117,7 @@ main_flush_commit(struct view *view, struct commit *commit)
117117
static bool
118118
main_add_changes_commit(struct view *view, enum line_type type, const char *parent, const char *title)
119119
{
120-
char ids[SIZEOF_STR] = NULL_ID " ";
120+
char ids[SIZEOF_STR] = NULL_ID;
121121
struct main_state *state = view->private;
122122
struct graph *graph = state->graph;
123123
struct commit commit = {{0}};
@@ -127,10 +127,11 @@ main_add_changes_commit(struct view *view, enum line_type type, const char *pare
127127
if (!parent)
128128
return true;
129129

130-
if (*parent)
131-
string_copy_rev(ids + STRING_SIZE(NULL_ID " "), parent);
132-
else
133-
ids[STRING_SIZE(NULL_ID)] = 0;
130+
if (*parent) {
131+
ids[REPO_INFO_SIZEOF_REV - 1] = ' ';
132+
string_copy_rev(ids + REPO_INFO_SIZEOF_REV, parent);
133+
} else
134+
ids[REPO_INFO_SIZEOF_REV - 1] = 0;
134135

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

src/options.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -701,9 +701,16 @@ parse_option(struct option_info *option, const char *prefix, const char *arg)
701701
if (!strcmp(name, "line-number-interval") ||
702702
!strcmp(name, "tab-size"))
703703
return parse_int(option->value, arg, 1, 1024);
704-
else if (!strcmp(name, "id-width"))
705-
return parse_int(option->value, arg, 0, SIZEOF_REV - 1);
706-
else
704+
else if (!strcmp(name, "id-width")) {
705+
enum status_code code = parse_int(option->value, arg, 0, SIZEOF_REV - 1);
706+
if (code == SUCCESS) {
707+
int *value = option->value;
708+
/* Limit id-width to the length of the hash used for the repository. */
709+
if (*value > REPO_INFO_SIZEOF_REV - 1)
710+
*value = REPO_INFO_SIZEOF_REV - 1;
711+
}
712+
return code;
713+
} else
707714
return parse_int(option->value, arg, 0, 1024);
708715
}
709716

@@ -1528,8 +1535,15 @@ read_repo_config_option(char *name, size_t namelen, char *value, size_t valuelen
15281535
else if (!strcmp(name, "core.worktree"))
15291536
string_ncopy(repo.worktree, value, valuelen);
15301537

1531-
else if (!strcmp(name, "core.abbrev"))
1532-
parse_int(&opt_id_width, value, 0, SIZEOF_REV - 1);
1538+
else if (!strcmp(name, "core.abbrev")) {
1539+
/* We cannot use REPO_INFO_SIZEOF_REV until we parse extensions.objectformat. */
1540+
if (!strcmp(value, "no"))
1541+
opt_id_width = SIZEOF_REV - 1;
1542+
else if (strcmp(value, "auto"))
1543+
parse_int(&opt_id_width, value, 0, SIZEOF_REV - 1);
1544+
1545+
} else if (!strcmp(name, "extensions.objectformat"))
1546+
repo.object_format = !strcmp(value, "sha256") ? REPO_INFO_SHA256 : REPO_INFO_SHA1;
15331547

15341548
else if (!strcmp(name, "diff.noprefix"))
15351549
parse_bool(&opt_diff_noprefix, value);
@@ -1578,6 +1592,10 @@ load_git_config(void)
15781592

15791593
code = io_run_load(&io, config_list_argv, "=", read_repo_config_option, NULL);
15801594

1595+
/* Limit id-width to the length of the hash used for the repository. */
1596+
if (opt_id_width > REPO_INFO_SIZEOF_REV - 1)
1597+
opt_id_width = REPO_INFO_SIZEOF_REV - 1;
1598+
15811599
if (git_worktree && *git_worktree)
15821600
string_ncopy(repo.worktree, git_worktree, strlen(git_worktree));
15831601

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)
@@ -109,12 +110,12 @@ parse_number(const char **posref, size_t *number)
109110
bool
110111
parse_blame_header(struct blame_header *header, const char *text)
111112
{
112-
const char *pos = text + SIZEOF_REV - 2;
113+
const char *pos = text + REPO_INFO_SIZEOF_REV - 2;
113114

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

117-
string_ncopy(header->id, text, SIZEOF_REV);
118+
string_copy_rev(header->id, text);
118119

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

165166
} else if (match_blame_header("previous ", &line)) {
166-
if (strlen(line) <= SIZEOF_REV)
167+
if (strlen(line) <= REPO_INFO_SIZEOF_REV)
167168
return false;
168169
string_copy_rev(commit->parent_id, line);
169-
line += SIZEOF_REV;
170+
line += REPO_INFO_SIZEOF_REV;
170171
commit->parent_filename = get_path(line);
171172
if (!commit->parent_filename)
172173
return true;

src/refdb.c

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

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

273273
ref->valid = true;
274274
ref->type = type;
275-
string_ncopy_do(ref->id, SIZEOF_REV, id, idlen);
275+
string_ncopy_do(ref->id, REPO_INFO_SIZEOF_REV, id, idlen);
276276

277277
if (type == REFERENCE_HEAD) {
278278
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);
@@ -102,6 +102,8 @@ load_repo_info(void)
102102
};
103103

104104
memset(&repo, 0, sizeof(repo));
105+
/* defaults to SHA-1 as older Git versions don't have extensions.objectFormat */
106+
repo.object_format = REPO_INFO_SHA1;
105107
return reload_repo_info(rev_parse_argv);
106108
}
107109

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)