Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for SHA-256 repositories
Browse files Browse the repository at this point in the history
Use variable extensions.objectformat, if available, to determine the
length of the hash id in the current repository.
koutcher committed Nov 21, 2023
1 parent e543cfe commit f4c4757
Showing 27 changed files with 309 additions and 40 deletions.
2 changes: 2 additions & 0 deletions doc/manual.adoc
Original file line number Diff line number Diff line change
@@ -203,6 +203,8 @@ following variables.
|%(repo:is-inside-work-tree)
|Whether Tig is running inside a work tree,
either `true` or `false`.
|%(repo:object-format) |The hash algorithm used for the repository, e.g. `sha1`
or `sha256`.
|=============================================================================

Example user-defined commands:
2 changes: 1 addition & 1 deletion include/tig/main.h
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@
#include "tig/util.h"

struct commit {
char id[SIZEOF_REV]; /* SHA1 ID. */
char id[SIZEOF_REV]; /* Hash ID. */
const struct ident *author; /* Author of the commit. */
struct time time; /* Date from the author ident. */
struct graph_canvas graph; /* Ancestry chain graphics. */
6 changes: 3 additions & 3 deletions include/tig/parse.h
Original file line number Diff line number Diff line change
@@ -31,17 +31,17 @@ bool parse_chunk_header(struct chunk_header *header, const char *line);
bool parse_chunk_lineno(unsigned long *lineno, const char *chunk, int marker);

struct blame_commit {
char id[SIZEOF_REV]; /* SHA1 ID. */
char id[SIZEOF_REV]; /* Hash ID. */
char title[128]; /* First line of the commit message. */
const struct ident *author; /* Author of the commit. */
struct time time; /* Date from the author ident. */
const char *filename; /* Name of file. */
char parent_id[SIZEOF_REV]; /* Parent/previous SHA1 ID. */
char parent_id[SIZEOF_REV]; /* Parent/previous hash ID. */
const char *parent_filename; /* Parent/previous name of file. */
};

struct blame_header {
char id[SIZEOF_REV]; /* SHA1 ID. */
char id[SIZEOF_REV]; /* Hash ID. */
size_t orig_lineno;
size_t lineno;
size_t group;
5 changes: 3 additions & 2 deletions include/tig/refdb.h
Original file line number Diff line number Diff line change
@@ -17,19 +17,20 @@
#include "tig/tig.h"
#include "tig/types.h"
#include "tig/util.h"
#include "tig/repo.h"

struct argv_env;

struct ref {
struct ref *next;
enum reference_type type;
char id[SIZEOF_REV]; /* Commit SHA1 ID */
char id[SIZEOF_REV]; /* Commit hash ID */
unsigned int valid:1; /* Is the ref still valid? */
char name[1]; /* Ref name; tag or head names are shortened. */
};

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

10 changes: 10 additions & 0 deletions include/tig/repo.h
Original file line number Diff line number Diff line change
@@ -16,11 +16,21 @@

#include "tig/tig.h"

typedef enum {
REPO_INFO_SHA1 = 40,
REPO_INFO_SHA256 = 64
} repo_object_format;

/* Holds a hash ID and an ending NUL. */
#define REPO_INFO_SIZEOF_REV (repo.object_format + 1)

typedef char repo_ref[SIZEOF_REF];
typedef char repo_rev[SIZEOF_REV];
typedef char repo_str[SIZEOF_STR];

/* Leave object_format in first position. */
#define REPO_INFO(_) \
_(repo_object_format, object_format) \
_(repo_ref, head) \
_(repo_rev, head_id) \
_(repo_ref, remote) \
2 changes: 1 addition & 1 deletion include/tig/string.h
Original file line number Diff line number Diff line change
@@ -85,7 +85,7 @@ void string_ncopy_do(char *dst, size_t dstlen, const char *src, size_t srclen);
void string_copy_rev(char *dst, const char *src);
void string_copy_rev_from_commit_line(char *dst, const char *src);

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

#define string_add(dst, from, src) \
string_ncopy_do(dst + (from), sizeof(dst) - (from), src, sizeof(src))
6 changes: 3 additions & 3 deletions include/tig/tig.h
Original file line number Diff line number Diff line change
@@ -148,8 +148,8 @@

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

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

#define NULL_ID "0000000000000000000000000000000000000000"
#define NULL_ID "0000000000000000000000000000000000000000000000000000000000000000"

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

8 changes: 8 additions & 0 deletions src/argv.c
Original file line number Diff line number Diff line change
@@ -415,6 +415,14 @@ bool_formatter(struct format_context *format, struct format_var *var)
return string_format_from(format->buf, &format->bufpos, "%s", value ? "true" : "false");
}

static bool
repo_object_format_formatter(struct format_context *format, struct format_var *var)
{
repo_object_format value = *(repo_object_format *)var->value_ref;

return string_format_from(format->buf, &format->bufpos, "%s", value == REPO_INFO_SHA256 ? "sha256" : "sha1");
}

static bool
repo_str_formatter(struct format_context *format, struct format_var *var)
{
6 changes: 3 additions & 3 deletions src/blame.c
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@
*/

struct blame_history_state {
char id[SIZEOF_REV]; /* SHA1 ID. */
char id[SIZEOF_REV]; /* Hash ID. */
const char *filename; /* Name of file. */
};

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

if (!strncmp(blame->commit->id, id, SIZEOF_REV - 1))
if (!strncmp(blame->commit->id, id, REPO_INFO_SIZEOF_REV - 1))
return blame->commit;
}

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

if (commit)
string_ncopy(commit->id, id, SIZEOF_REV);
string_ncopy(commit->id, id, REPO_INFO_SIZEOF_REV);
return commit;
}
}
3 changes: 2 additions & 1 deletion src/draw.c
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
#include "tig/graph.h"
#include "tig/draw.h"
#include "tig/options.h"
#include "tig/repo.h"
#include "compat/hashtab.h"

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

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

type = palette_colors[color % ARRAY_SIZE(palette_colors)];
}
2 changes: 1 addition & 1 deletion src/graph-v1.c
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ struct graph_symbol {

struct graph_column {
struct graph_symbol symbol;
char id[SIZEOF_REV]; /* Parent SHA1 ID. */
char id[SIZEOF_REV]; /* Parent hash ID. */
};

struct graph_row {
2 changes: 1 addition & 1 deletion src/graph-v2.c
Original file line number Diff line number Diff line change
@@ -48,7 +48,7 @@ struct graph_symbol {

struct graph_column {
struct graph_symbol symbol;
const char *id; /* Parent SHA1 ID. */
const char *id; /* Parent hash ID. */
};

struct graph_row {
11 changes: 6 additions & 5 deletions src/main.c
Original file line number Diff line number Diff line change
@@ -101,7 +101,7 @@ main_add_commit(struct view *view, enum line_type type, struct commit *template,
view_column_info_update(view, line);

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

return commit;
@@ -127,10 +127,11 @@ main_add_changes_commit(struct view *view, enum line_type type, const char *pare
if (!parent)
return true;

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

if (!time_now(&now, &tz)) {
commit.time.tz = tz.tz_minuteswest * 60;
28 changes: 23 additions & 5 deletions src/options.c
Original file line number Diff line number Diff line change
@@ -701,9 +701,16 @@ parse_option(struct option_info *option, const char *prefix, const char *arg)
if (!strcmp(name, "line-number-interval") ||
!strcmp(name, "tab-size"))
return parse_int(option->value, arg, 1, 1024);
else if (!strcmp(name, "id-width"))
return parse_int(option->value, arg, 0, SIZEOF_REV - 1);
else
else if (!strcmp(name, "id-width")) {
enum status_code code = parse_int(option->value, arg, 0, SIZEOF_REV - 1);
if (code == SUCCESS) {
int *value = option->value;
/* Limit id-width to the length of the hash used for the repository. */
if (*value > REPO_INFO_SIZEOF_REV - 1)
*value = REPO_INFO_SIZEOF_REV - 1;
}
return code;
} else
return parse_int(option->value, arg, 0, 1024);
}

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

else if (!strcmp(name, "core.abbrev"))
parse_int(&opt_id_width, value, 0, SIZEOF_REV - 1);
else if (!strcmp(name, "core.abbrev")) {
/* We cannot use REPO_INFO_SIZEOF_REV until we parse extensions.objectformat. */
if (!strcmp(value, "no"))
opt_id_width = SIZEOF_REV - 1;
else if (strcmp(value, "auto"))
parse_int(&opt_id_width, value, 0, SIZEOF_REV - 1);

} else if (!strcmp(name, "extensions.objectformat"))
repo.object_format = !strcmp(value, "sha256") ? REPO_INFO_SHA256 : REPO_INFO_SHA1;

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

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

/* Limit id-width to the length of the hash used for the repository. */
if (opt_id_width > REPO_INFO_SIZEOF_REV - 1)
opt_id_width = REPO_INFO_SIZEOF_REV - 1;

if (git_worktree && *git_worktree)
string_ncopy(repo.worktree, git_worktree, strlen(git_worktree));

11 changes: 6 additions & 5 deletions src/parse.c
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@
#include "tig/tig.h"
#include "tig/parse.h"
#include "tig/map.h"
#include "tig/repo.h"

size_t
parse_size(const char *text)
@@ -109,12 +110,12 @@ parse_number(const char **posref, size_t *number)
bool
parse_blame_header(struct blame_header *header, const char *text)
{
const char *pos = text + SIZEOF_REV - 2;
const char *pos = text + REPO_INFO_SIZEOF_REV - 2;

if (strlen(text) <= SIZEOF_REV || pos[1] != ' ')
if (strlen(text) <= REPO_INFO_SIZEOF_REV || pos[1] != ' ')
return false;

string_ncopy(header->id, text, SIZEOF_REV);
string_copy_rev(header->id, text);

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

} else if (match_blame_header("previous ", &line)) {
if (strlen(line) <= SIZEOF_REV)
if (strlen(line) <= REPO_INFO_SIZEOF_REV)
return false;
string_copy_rev(commit->parent_id, line);
line += SIZEOF_REV;
line += REPO_INFO_SIZEOF_REV;
commit->parent_filename = get_path(line);
if (!commit->parent_filename)
return true;
4 changes: 2 additions & 2 deletions src/refdb.c
Original file line number Diff line number Diff line change
@@ -239,7 +239,7 @@ add_to_refs(const char *id, size_t idlen, char *name, size_t namelen, struct ref
}

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

ref->valid = true;
ref->type = type;
string_ncopy_do(ref->id, SIZEOF_REV, id, idlen);
string_ncopy_do(ref->id, REPO_INFO_SIZEOF_REV, id, idlen);

if (type == REFERENCE_HEAD) {
if (!refs_head ||
4 changes: 3 additions & 1 deletion src/repo.c
Original file line number Diff line number Diff line change
@@ -57,7 +57,7 @@ read_repo_info(char *name, size_t namelen, char *value, size_t valuelen, void *d
* this special case by looking at the emitted value. If it looks
* like a commit ID and there's no cdup path assume that no value
* was emitted. */
if (!*repo.cdup && namelen == 40 && iscommit(name))
if (!*repo.cdup && namelen == REPO_INFO_SIZEOF_REV - 1 && iscommit(name))
return read_repo_info(name, namelen, value, valuelen, data);

string_ncopy(repo.prefix, name, namelen);
@@ -102,6 +102,8 @@ load_repo_info(void)
};

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

2 changes: 1 addition & 1 deletion src/status.c
Original file line number Diff line number Diff line change
@@ -111,7 +111,7 @@ status_run(struct view *view, const char *argv[], char status, enum line_type ty
if (status) {
file->status = status;
if (status == 'A')
string_copy(file->old.rev, NULL_ID);
string_copy_rev(file->old.rev, NULL_ID);

} else {
if (!status_get_diff(&parsed, buf.data, buf.size))
7 changes: 4 additions & 3 deletions src/string.c
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@

#include "tig/tig.h"
#include "tig/string.h"
#include "tig/repo.h"
#include "compat/utf8proc.h"

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

return 7 <= pos && pos < SIZEOF_REV;
return 7 <= pos && pos < REPO_INFO_SIZEOF_REV;
}

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

for (srclen = 0; srclen < SIZEOF_REV; srclen++)
for (srclen = 0; srclen < REPO_INFO_SIZEOF_REV; srclen++)
if (!src[srclen] || isspace((unsigned char)src[srclen]))
break;

string_ncopy_do(dst, SIZEOF_REV, src, srclen);
string_ncopy_do(dst, REPO_INFO_SIZEOF_REV, src, srclen);
}

void
2 changes: 1 addition & 1 deletion src/tree.c
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@ push_tree_stack_entry(struct view *view, const char *name, struct position *posi
*/

#define SIZEOF_TREE_ATTR \
STRING_SIZE("100644 blob f931e1d229c3e185caad4449bf5b66ed72462657\t")
STRING_SIZE("100644 blob ") + REPO_INFO_SIZEOF_REV - 1 + STRING_SIZE("\t")

#define SIZEOF_TREE_MODE \
STRING_SIZE("100644 ")
Loading

0 comments on commit f4c4757

Please sign in to comment.