#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#define STRING_SIZE(x) (sizeof(x) - 1)
+#define SIZEOF_STR 1024 /* Default string size. */
#define SIZEOF_REF 256 /* Size of symbolic or SHA1 ID. */
-#define SIZEOF_CMD 1024 /* Size of command buffer. */
#define SIZEOF_REVGRAPH 19 /* Size of revision ancestry graphics. */
/* This color name can be used to refer to the default term colors. */
*/
static size_t
-sq_quote(char buf[SIZEOF_CMD], size_t bufsize, const char *src)
+sq_quote(char buf[SIZEOF_STR], size_t bufsize, const char *src)
{
char c;
-#define BUFPUT(x) do { if (bufsize < SIZEOF_CMD) buf[bufsize++] = (x); } while (0)
+#define BUFPUT(x) do { if (bufsize < SIZEOF_STR) buf[bufsize++] = (x); } while (0)
BUFPUT('\'');
while ((c = *src++)) {
static int opt_num_interval = NUMBER_INTERVAL;
static int opt_tab_size = TABSIZE;
static enum request opt_request = REQ_VIEW_MAIN;
-static char opt_cmd[SIZEOF_CMD] = "";
+static char opt_cmd[SIZEOF_STR] = "";
static FILE *opt_pipe = NULL;
static char opt_encoding[20] = "UTF-8";
static bool opt_utf8 = TRUE;
load_options(void)
{
char *home = getenv("HOME");
- char buf[1024];
+ char buf[SIZEOF_STR];
FILE *file;
config_lineno = 0;
enum keymap keymap; /* What keymap does this view have */
- char cmd[SIZEOF_CMD]; /* Command buffer */
+ char cmd[SIZEOF_STR]; /* Command buffer */
char ref[SIZEOF_REF]; /* Hovered commit reference */
char vid[SIZEOF_REF]; /* View ID. Set to id member when updating. */
return TRUE;
}
+static bool
+add_describe_ref(char *buf, int *bufpos, char *commit_id, const char *sep)
+{
+ char refbuf[SIZEOF_STR];
+ char *ref = NULL;
+ FILE *pipe;
+
+ if (!string_format(refbuf, "git describe %s", commit_id))
+ return TRUE;
+
+ pipe = popen(refbuf, "r");
+ if (!pipe)
+ return TRUE;
+
+ if ((ref = fgets(refbuf, sizeof(refbuf), pipe)))
+ ref = chomp_string(ref);
+ pclose(pipe);
+
+ if (!ref || !*ref)
+ return TRUE;
+
+ /* This is the only fatal call, since it can "corrupt" the buffer. */
+ if (!string_nformat(buf, SIZEOF_STR, bufpos, "%s%s", sep, ref))
+ return FALSE;
+
+ return TRUE;
+}
+
static void
add_pager_refs(struct view *view, struct line *line)
{
- char buf[1024];
- char *data = line->data;
+ char buf[SIZEOF_STR];
+ char *commit_id = line->data + STRING_SIZE("commit ");
struct ref **refs;
int bufpos = 0, refpos = 0;
const char *sep = "Refs: ";
+ bool is_tag = FALSE;
assert(line->type == LINE_COMMIT);
- refs = get_refs(data + STRING_SIZE("commit "));
- if (!refs)
+ refs = get_refs(commit_id);
+ if (!refs) {
+ if (view == VIEW(REQ_VIEW_DIFF))
+ goto try_add_describe_ref;
return;
+ }
do {
struct ref *ref = refs[refpos];
if (!string_format_from(buf, &bufpos, fmt, sep, ref->name))
return;
sep = ", ";
+ if (ref->tag)
+ is_tag = TRUE;
} while (refs[refpos++]->next);
+ if (!is_tag && view == VIEW(REQ_VIEW_DIFF)) {
+try_add_describe_ref:
+ if (!add_describe_ref(buf, &bufpos, commit_id, sep))
+ return;
+ }
+
if (!realloc_lines(view, view->line_size + 1))
return;
wbkgdset(status_win, get_line_attr(LINE_STATUS));
}
-static int
-read_prompt(void)
+static char *
+read_prompt(const char *prompt)
{
enum { READING, STOP, CANCEL } status = READING;
- char buf[sizeof(opt_cmd) - STRING_SIZE("git \0")];
+ static char buf[sizeof(opt_cmd) - STRING_SIZE("git \0")];
int pos = 0;
while (status == READING) {
foreach_view (view, i)
update_view(view);
- report(":%.*s", pos, buf);
+ report("%s%.*s", prompt, pos, buf);
/* Refresh, accept single keystroke of input */
key = wgetch(status_win);
switch (key) {
default:
if (pos >= sizeof(buf)) {
report("Input string too long");
- return ERR;
+ return NULL;
}
if (isprint(key))
if (status == CANCEL) {
/* Clear the status window */
report("");
- return ERR;
+ return NULL;
}
buf[pos++] = 0;
- if (!string_format(opt_cmd, "git %s", buf))
- return ERR;
- if (strncmp(buf, "show", 4) && isspace(buf[4]))
- opt_request = REQ_VIEW_DIFF;
- else
- opt_request = REQ_VIEW_PAGER;
- return OK;
+ return buf;
}
/*
* status_win restricted. */
switch (request) {
case REQ_PROMPT:
- if (read_prompt() == ERR)
- request = REQ_SCREEN_UPDATE;
- break;
+ {
+ char *cmd = read_prompt(":");
+ if (cmd && string_format(opt_cmd, "git %s", cmd)) {
+ if (strncmp(cmd, "show", 4) && isspace(cmd[4])) {
+ opt_request = REQ_VIEW_DIFF;
+ } else {
+ opt_request = REQ_VIEW_PAGER;
+ }
+ break;
+ }
+
+ request = REQ_SCREEN_UPDATE;
+ break;
+ }
case REQ_SCREEN_RESIZE:
{
int height, width;