char *name; /* Ref name; tag or head names are shortened. */
char id[SIZEOF_REV]; /* Commit SHA1 ID */
unsigned int tag:1; /* Is it a tag? */
+ unsigned int ltag:1; /* If so, is the tag local? */
unsigned int remote:1; /* Is it a remote ref? */
unsigned int next:1; /* For ref lists: are there more refs? */
};
opt_cmd[buf_size] = 0;
}
- if (*opt_encoding && strcasecmp(opt_encoding, "UTF-8"))
- opt_utf8 = FALSE;
-
return TRUE;
}
LINE(MAIN_COMMIT, "", COLOR_DEFAULT, COLOR_DEFAULT, 0), \
LINE(MAIN_DELIM, "", COLOR_MAGENTA, COLOR_DEFAULT, 0), \
LINE(MAIN_TAG, "", COLOR_MAGENTA, COLOR_DEFAULT, A_BOLD), \
+LINE(MAIN_LOCAL_TAG,"", COLOR_MAGENTA, COLOR_DEFAULT, A_BOLD), \
LINE(MAIN_REMOTE, "", COLOR_YELLOW, COLOR_DEFAULT, A_BOLD), \
LINE(MAIN_REF, "", COLOR_CYAN, COLOR_DEFAULT, A_BOLD), \
LINE(MAIN_REVGRAPH,"", COLOR_MAGENTA, COLOR_DEFAULT, 0), \
return OK;
}
+static bool parse_bool(const char *s)
+{
+ return (!strcmp(s, "1") || !strcmp(s, "true") ||
+ !strcmp(s, "yes")) ? TRUE : FALSE;
+}
+
/* Wants: name = value */
static int
option_set_command(int argc, char *argv[])
return ERR;
}
+ if (!strcmp(argv[0], "show-author")) {
+ opt_author = parse_bool(argv[2]);
+ return OK;
+ }
+
+ if (!strcmp(argv[0], "show-date")) {
+ opt_date = parse_bool(argv[2]);
+ return OK;
+ }
+
if (!strcmp(argv[0], "show-rev-graph")) {
- opt_rev_graph = (!strcmp(argv[2], "1") ||
- !strcmp(argv[2], "true") ||
- !strcmp(argv[2], "yes"));
+ opt_rev_graph = parse_bool(argv[2]);
+ return OK;
+ }
+
+ if (!strcmp(argv[0], "show-refs")) {
+ opt_show_refs = parse_bool(argv[2]);
+ return OK;
+ }
+
+ if (!strcmp(argv[0], "show-line-numbers")) {
+ opt_line_number = parse_bool(argv[2]);
return OK;
}
struct view *parent;
/* Buffering */
- unsigned long lines; /* Total number of lines */
+ size_t lines; /* Total number of lines */
struct line *line; /* Line index */
- unsigned long line_size;/* Total number of allocated lines */
+ size_t line_alloc; /* Total number of allocated lines */
+ size_t line_size; /* Total number of used lines */
unsigned int digits; /* Number of digits in the lines member. */
/* Loading */
return TRUE;
}
+#define ITEM_CHUNK_SIZE 256
+static void *
+realloc_items(void *mem, size_t *size, size_t new_size, size_t item_size)
+{
+ size_t num_chunks = *size / ITEM_CHUNK_SIZE;
+ size_t num_chunks_new = (new_size + ITEM_CHUNK_SIZE - 1) / ITEM_CHUNK_SIZE;
+
+ if (mem == NULL || num_chunks != num_chunks_new) {
+ *size = num_chunks_new * ITEM_CHUNK_SIZE;
+ mem = realloc(mem, *size * item_size);
+ }
+
+ return mem;
+}
+
static struct line *
realloc_lines(struct view *view, size_t line_size)
{
- struct line *tmp = realloc(view->line, sizeof(*view->line) * line_size);
+ size_t alloc = view->line_alloc;
+ struct line *tmp = realloc_items(view->line, &alloc, line_size,
+ sizeof(*view->line));
if (!tmp)
return NULL;
view->line = tmp;
+ view->line_alloc = alloc;
view->line_size = line_size;
return view->line;
}
for (i = 0; i < view->lines; i++)
free(view->line[i].data);
free(view->line);
- view->lines = view->line_size = view->lineno = 0;
+ view->lines = view->line_alloc = view->line_size = view->lineno = 0;
view->line = NULL;
if (!realloc_lines(view, view->line_size + 6))
do {
if (type == LINE_CURSOR)
;
+ else if (commit->refs[i]->ltag)
+ wattrset(view->win, get_line_attr(LINE_MAIN_LOCAL_TAG));
else if (commit->refs[i]->tag)
wattrset(view->win, get_line_attr(LINE_MAIN_TAG));
else if (commit->refs[i]->remote)
* Repository references
*/
-static struct ref *refs;
-static size_t refs_size;
+static struct ref *refs = NULL;
+static size_t refs_alloc = 0;
+static size_t refs_size = 0;
/* Id <-> ref store */
-static struct ref ***id_refs;
-static size_t id_refs_size;
+static struct ref ***id_refs = NULL;
+static size_t id_refs_alloc = 0;
+static size_t id_refs_size = 0;
static struct ref **
get_refs(char *id)
{
struct ref ***tmp_id_refs;
struct ref **ref_list = NULL;
+ size_t ref_list_alloc = 0;
size_t ref_list_size = 0;
size_t i;
if (!strcmp(id, id_refs[i][0]->id))
return id_refs[i];
- tmp_id_refs = realloc(id_refs, (id_refs_size + 1) * sizeof(*id_refs));
+ tmp_id_refs = realloc_items(id_refs, &id_refs_alloc, id_refs_size + 1,
+ sizeof(*id_refs));
if (!tmp_id_refs)
return NULL;
if (strcmp(id, refs[i].id))
continue;
- tmp = realloc(ref_list, (ref_list_size + 1) * sizeof(*ref_list));
+ tmp = realloc_items(ref_list, &ref_list_alloc,
+ ref_list_size + 1, sizeof(*ref_list));
if (!tmp) {
if (ref_list)
free(ref_list);
{
struct ref *ref;
bool tag = FALSE;
+ bool ltag = FALSE;
bool remote = FALSE;
+ bool check_replace = FALSE;
if (!strncmp(name, "refs/tags/", STRING_SIZE("refs/tags/"))) {
- /* Commits referenced by tags has "^{}" appended. */
- if (name[namelen - 1] != '}')
- return OK;
-
- while (namelen > 0 && name[namelen] != '^')
- namelen--;
+ if (!strcmp(name + namelen - 3, "^{}")) {
+ namelen -= 3;
+ name[namelen] = 0;
+ if (refs_size > 0 && refs[refs_size - 1].ltag == TRUE)
+ check_replace = TRUE;
+ } else {
+ ltag = TRUE;
+ }
tag = TRUE;
namelen -= STRING_SIZE("refs/tags/");
return OK;
}
- refs = realloc(refs, sizeof(*refs) * (refs_size + 1));
+ if (check_replace && !strcmp(name, refs[refs_size - 1].name)) {
+ /* it's an annotated tag, replace the previous sha1 with the
+ * resolved commit id; relies on the fact git-ls-remote lists
+ * the commit id of an annotated tag right beofre the commit id
+ * it points to. */
+ refs[refs_size - 1].ltag = ltag;
+ string_copy_rev(refs[refs_size - 1].id, id);
+
+ return OK;
+ }
+ refs = realloc_items(refs, &refs_alloc, refs_size + 1, sizeof(*refs));
if (!refs)
return ERR;
strncpy(ref->name, name, namelen);
ref->name[namelen] = 0;
ref->tag = tag;
+ ref->ltag = ltag;
ref->remote = remote;
string_copy_rev(ref->id, id);
if (!opt_git_dir[0])
die("Not a git repository");
+ if (*opt_encoding && strcasecmp(opt_encoding, "UTF-8"))
+ opt_utf8 = FALSE;
+
if (*opt_codeset && strcmp(opt_codeset, opt_encoding)) {
opt_iconv = iconv_open(opt_codeset, opt_encoding);
if (opt_iconv == ICONV_NONE)