X-Git-Url: https://git.distorted.org.uk/~mdw/tig/blobdiff_plain/173d76ea34a54342687c3d03ed71930429dca299..5699e0cfd59c6a6b30776efeab8b96fbdc586fa7:/tig.c?ds=sidebyside diff --git a/tig.c b/tig.c index 888133e..371377a 100644 --- a/tig.c +++ b/tig.c @@ -11,8 +11,8 @@ * GNU General Public License for more details. */ -#ifndef VERSION -#define VERSION "tig-0.6.git" +#ifndef VERSION +#define VERSION "unknown-version" #endif #ifndef DEBUG @@ -47,7 +47,7 @@ static void __NORETURN die(const char *err, ...); static void report(const char *msg, ...); -static int read_properties(FILE *pipe, const char *separators, int (*read)(char *, int, char *, int)); +static int read_properties(FILE *pipe, const char *separators, int (*read)(char *, size_t, char *, size_t)); static void set_nonblocking_input(bool loading); static size_t utf8_length(const char *string, size_t max_width, int *coloffset, int *trimmed); @@ -169,7 +169,7 @@ string_ncopy_do(char *dst, size_t dstlen, const char *src, size_t srclen) /* Shorthands for safely copying into a fixed buffer. */ #define string_copy(dst, src) \ - string_ncopy_do(dst, sizeof(dst), src, sizeof(dst)) + string_ncopy_do(dst, sizeof(dst), src, sizeof(src)) #define string_ncopy(dst, src, srclen) \ string_ncopy_do(dst, sizeof(dst), src, srclen) @@ -177,6 +177,9 @@ string_ncopy_do(char *dst, size_t dstlen, const char *src, size_t srclen) #define string_copy_rev(dst, src) \ string_ncopy_do(dst, SIZEOF_REV, src, SIZEOF_REV - 1) +#define string_add(dst, from, src) \ + string_ncopy_do(dst + (from), sizeof(dst) - (from), src, sizeof(src)) + static char * chomp_string(char *name) { @@ -384,7 +387,7 @@ get_request(const char *name) */ static const char usage[] = -VERSION " (" __DATE__ ")\n" +"tig " VERSION " (" __DATE__ ")\n" "\n" "Usage: tig [options]\n" " or: tig [options] [--] [git log options]\n" @@ -417,6 +420,7 @@ static bool opt_utf8 = TRUE; static char opt_codeset[20] = "UTF-8"; static iconv_t opt_iconv = ICONV_NONE; static char opt_search[SIZEOF_STR] = ""; +static char opt_cdup[SIZEOF_STR] = ""; enum option_type { OPT_NONE, @@ -1038,7 +1042,7 @@ option_set_command(int argc, char *argv[]) break; } default: - string_copy(opt_encoding, arg); + string_ncopy(opt_encoding, arg, strlen(arg)); return OK; } } @@ -1116,7 +1120,7 @@ set_option(char *opt, char *value) } static int -read_option(char *opt, int optlen, char *value, int valuelen) +read_option(char *opt, size_t optlen, char *value, size_t valuelen) { int status = OK; @@ -1135,7 +1139,7 @@ read_option(char *opt, int optlen, char *value, int valuelen) } else { /* Look for comment endings in the value. */ - int len = strcspn(value, "#"); + size_t len = strcspn(value, "#"); if (len < valuelen) { valuelen = len; @@ -1798,8 +1802,6 @@ end_update(struct view *view) static bool begin_update(struct view *view) { - const char *id = view->id; - if (view->pipe) end_update(view); @@ -1820,11 +1822,12 @@ begin_update(struct view *view) else if (sq_quote(path, 0, opt_path) >= sizeof(path)) return FALSE; - if (!string_format(view->cmd, format, id, path)) + if (!string_format(view->cmd, format, view->id, path)) return FALSE; } else { const char *format = view->cmd_env ? view->cmd_env : view->cmd_fmt; + const char *id = view->id; if (!string_format(view->cmd, format, id, id, id, id, id)) return FALSE; @@ -1833,7 +1836,7 @@ begin_update(struct view *view) * member. This is needed by the blob view. Most other * views sets it automatically after loading because the * first line is a commit line. */ - string_copy(view->ref, id); + string_copy_rev(view->ref, view->id); } /* Special case for the pager view. */ @@ -1852,7 +1855,7 @@ begin_update(struct view *view) view->offset = 0; view->lines = 0; view->lineno = 0; - string_copy_rev(view->vid, id); + string_copy_rev(view->vid, view->id); if (view->line) { int i; @@ -2240,7 +2243,7 @@ view_driver(struct view *view, enum request request) break; case REQ_SHOW_VERSION: - report("%s (built %s)", VERSION, __DATE__); + report("tig-%s (built %s)", VERSION, __DATE__); return TRUE; case REQ_SCREEN_RESIZE: @@ -2989,8 +2992,9 @@ static bool status_enter(struct view *view, struct line *line) { struct status *status = line->data; - const char *cmd; + char cmd[SIZEOF_STR]; char buf[SIZEOF_STR]; + size_t cmdsize = 0; size_t bufsize = 0; size_t written = 0; FILE *pipe; @@ -2998,6 +3002,11 @@ status_enter(struct view *view, struct line *line) if (!status) return TRUE; + if (opt_cdup[0] && + line->type != LINE_STAT_UNTRACKED && + !string_format_from(cmd, &cmdsize, "cd %s;", opt_cdup)) + return FALSE; + switch (line->type) { case LINE_STAT_STAGED: if (!string_format_from(buf, &bufsize, "%06o %s\t%s%c", @@ -3005,14 +3014,16 @@ status_enter(struct view *view, struct line *line) status->old.rev, status->name, 0)) return FALSE; - cmd = "git update-index -z --index-info"; + + string_add(cmd, cmdsize, "git update-index -z --index-info"); break; case LINE_STAT_UNSTAGED: case LINE_STAT_UNTRACKED: if (!string_format_from(buf, &bufsize, "%s%c", status->name, 0)) return FALSE; - cmd = "git update-index -z --add --remove --stdin"; + + string_add(cmd, cmdsize, "git update-index -z --add --remove --stdin"); break; default: @@ -3193,7 +3204,7 @@ push_rev_graph(struct rev_graph *graph, char *parent) return; if (graph->size < SIZEOF_REVITEMS) { - string_ncopy(graph->rev[graph->size++], parent, SIZEOF_REV); + string_copy_rev(graph->rev[graph->size++], parent); } } @@ -3481,7 +3492,7 @@ main_read(struct view *view, char *line) ident = "Unknown"; } - string_copy(commit->author, ident); + string_ncopy(commit->author, ident, strlen(ident)); /* Parse epoch and timezone */ if (emailend[1] == ' ') { @@ -3527,7 +3538,7 @@ main_read(struct view *view, char *line) /* FIXME: More graceful handling of titles; append "..." to * shortened titles, etc. */ - string_copy(commit->title, line); + string_ncopy(commit->title, line, strlen(line)); } return TRUE; @@ -3973,7 +3984,7 @@ get_refs(char *id) } static int -read_ref(char *id, int idlen, char *name, int namelen) +read_ref(char *id, size_t idlen, char *name, size_t namelen) { struct ref *ref; bool tag = FALSE; @@ -4032,10 +4043,10 @@ load_refs(void) } static int -read_repo_config_option(char *name, int namelen, char *value, int valuelen) +read_repo_config_option(char *name, size_t namelen, char *value, size_t valuelen) { if (!strcmp(name, "i18n.commitencoding")) - string_copy(opt_encoding, value); + string_ncopy(opt_encoding, value, valuelen); return OK; } @@ -4048,8 +4059,23 @@ load_repo_config(void) } static int +read_repo_info(char *name, size_t namelen, char *value, size_t valuelen) +{ + if (!opt_cdup[0]) + string_ncopy(opt_cdup, name, namelen); + return OK; +} + +static int +load_repo_info(void) +{ + return read_properties(popen("git rev-parse --show-cdup", "r"), + "=", read_repo_info); +} + +static int read_properties(FILE *pipe, const char *separators, - int (*read_property)(char *, int, char *, int)) + int (*read_property)(char *, size_t, char *, size_t)) { char buffer[BUFSIZ]; char *name; @@ -4127,17 +4153,22 @@ main(int argc, char *argv[]) signal(SIGINT, quit); if (setlocale(LC_ALL, "")) { - string_copy(opt_codeset, nl_langinfo(CODESET)); + char *codeset = nl_langinfo(CODESET); + + string_ncopy(opt_codeset, codeset, strlen(codeset)); } if (load_options() == ERR) die("Failed to load user config."); /* Load the repo config file so options can be overwritten from - * the command line. */ + * the command line. */ if (load_repo_config() == ERR) die("Failed to load repo config."); + if (load_repo_info() == ERR) + die("Failed to load repo info."); + if (!parse_options(argc, argv)) return 0; @@ -4207,7 +4238,7 @@ main(int argc, char *argv[]) char *search = read_prompt(prompt); if (search) - string_copy(opt_search, search); + string_ncopy(opt_search, search, strlen(search)); else request = REQ_NONE; break;