X-Git-Url: https://git.distorted.org.uk/~mdw/tig/blobdiff_plain/468876c9ed00a4d31ce2dca57e7c66dbfbd9c5f3..b5c9e67f19d607d0540404fc8de463a7a3801f0a:/tig.c diff --git a/tig.c b/tig.c index 3b51c5a..c3ed1f1 100644 --- a/tig.c +++ b/tig.c @@ -23,7 +23,7 @@ * Browse changes in a git repository. Additionally, tig(1) can also act * as a pager for output of various git commands. * - * When browsing repositories, tig(1) uses the underlaying git commands + * When browsing repositories, tig(1) uses the underlying git commands * to present the user with various views, such as summarized commit log * and showing the commit with the log message, diffstat, and the diff. * @@ -32,7 +32,7 @@ **/ #ifndef VERSION -#define VERSION "tig-0.1" +#define VERSION "tig-0.3" #endif #ifndef DEBUG @@ -146,7 +146,7 @@ struct commit { */ static inline void -string_ncopy(char *dst, char *src, int dstlen) +string_ncopy(char *dst, const char *src, int dstlen) { strncpy(dst, src, dstlen - 1); dst[dstlen - 1] = 0; @@ -294,8 +294,8 @@ parse_options(int argc, char *argv[]) /** * \--:: - * End of tig(1) options. Useful when specifying commands - * for the main view. Example: + * End of tig(1) options. Useful when specifying command + * options for the main view. Example: * * $ tig -- --since=1.month **/ @@ -305,13 +305,13 @@ parse_options(int argc, char *argv[]) } /** - * log [options]:: + * log [git log options]:: * Open log view using the given git log options. * - * diff [options]:: + * diff [git diff options]:: * Open diff view using the given git diff options. * - * show [options]:: + * show [git show options]:: * Open diff view using the given git show options. **/ if (!strcmp(opt, "log") || @@ -322,11 +322,16 @@ parse_options(int argc, char *argv[]) break; } - /* Make stuff like: + /** + * [git log options]:: + * tig(1) will stop the option parsing when the first + * command line parameter not starting with "-" is + * encountered. All options including this one will be + * passed to git log when loading the main view. + * This makes it possible to say: * * $ tig tag-1.0..HEAD - * - * work. */ + **/ if (opt[0] && opt[0] != '-') break; @@ -367,10 +372,10 @@ parse_options(int argc, char *argv[]) * * $ tig log --pretty=fuller * - * See the "Specifying revisions" section below for an introduction - * to revision options supported by the git commands. For - * details on specific git command options, refer to the man - * page of the command in question. + * See the <> section below + * for an introduction to revision options supported by the git + * commands. For details on specific git command options, refer + * to the man page of the command in question. **/ if (opt_request == REQ_VIEW_MAIN) @@ -453,7 +458,7 @@ enum line_type { }; struct line_info { - char *line; /* The start of line to match. */ + const char *line; /* The start of line to match. */ int linelen; /* Size of string to match. */ int fg, bg, attr; /* Color and text attributes for the lines. */ }; @@ -537,9 +542,10 @@ init_colors(void) **/ #define TIG_LS_REMOTE \ - "git ls-remote ." + "git ls-remote . 2>/dev/null" /** + * [[view-commands]] * View commands * ~~~~~~~~~~~~~ * It is possible to alter which commands are used for the different views. @@ -577,10 +583,10 @@ init_colors(void) #define TIG_MAIN_CMD \ "git log --topo-order --stat --pretty=raw %s" -/* We silently ignore that the following are also exported. */ +/* ... silently ignore that the following are also exported. */ #define TIG_HELP_CMD \ - "man tig 2> /dev/null" + "man tig 2>/dev/null" #define TIG_PAGER_CMD \ "" @@ -618,15 +624,15 @@ init_colors(void) struct view { const char *name; /* View name */ - char *cmd_fmt; /* Default command line format */ - char *cmd_env; /* Command line set via environment */ - char *id; /* Points to either of ref_{head,commit} */ + const char *cmd_fmt; /* Default command line format */ + const char *cmd_env; /* Command line set via environment */ + const char *id; /* Points to either of ref_{head,commit} */ size_t objsize; /* Size of objects in the line index */ struct view_ops { /* What type of content being displayed. Used in the * title bar. */ - char *type; + const char *type; /* Draw one line; @lineno must be < view->height. */ bool (*draw)(struct view *view, unsigned int lineno); /* Read one line; updates view->line. */ @@ -660,8 +666,8 @@ struct view { static struct view_ops pager_ops; static struct view_ops main_ops; -char ref_head[SIZEOF_REF] = "HEAD"; -char ref_commit[SIZEOF_REF] = "HEAD"; +static char ref_head[SIZEOF_REF] = "HEAD"; +static char ref_commit[SIZEOF_REF] = "HEAD"; #define VIEW_STR(name, cmd, env, ref, objsize, ops) \ { name, cmd, #env, ref, objsize, ops } @@ -981,7 +987,7 @@ move_view(struct view *view, enum request request) static bool begin_update(struct view *view) { - char *id = view->id; + const char *id = view->id; if (opt_cmd[0]) { string_copy(view->cmd, opt_cmd); @@ -990,7 +996,7 @@ begin_update(struct view *view) * invalid so clear it. */ view->ref[0] = 0; } else { - char *format = view->cmd_env ? view->cmd_env : view->cmd_fmt; + const char *format = view->cmd_env ? view->cmd_env : view->cmd_fmt; if (snprintf(view->cmd, sizeof(view->cmd), format, id, id, id, id, id) >= sizeof(view->cmd)) @@ -1119,7 +1125,7 @@ update_view(struct view *view) time_t secs = time(NULL) - view->start_time; if (view == VIEW(REQ_VIEW_HELP)) { - char *msg = TIG_HELP; + const char *msg = TIG_HELP; if (view->lines == 0) { /* Slightly ugly, but abusing view->ref keeps @@ -1687,7 +1693,7 @@ struct keymap { int request; }; -struct keymap keymap[] = { +static struct keymap keymap[] = { /** * View switching * ~~~~~~~~~~~~~~ @@ -1702,7 +1708,7 @@ struct keymap keymap[] = { * h:: * Show man page. * Return:: - * If on a commit line show the commit diff. Addiionally, if in + * If on a commit line show the commit diff. Additionally, if in * main or log view this will split the view. To open the commit * diff in full size view either use 'd' or press Return twice. * Tab:: @@ -1721,17 +1727,17 @@ struct keymap keymap[] = { * Cursor navigation * ~~~~~~~~~~~~~~~~~ * Up:: - * Move curser one line up. + * Move cursor one line up. * Down:: * Move cursor one line down. * k:: - * Move curser one line up and enter. When used in the main view + * Move cursor one line up and enter. When used in the main view * this will always show the diff of the current commit in the * split diff view. * j:: * Move cursor one line down and enter. * PgUp:: - * Move curser one page up. + * Move cursor one page up. * PgDown:: * Move cursor one page down. * Home:: @@ -1775,7 +1781,7 @@ struct keymap keymap[] = { * z:: * Stop all background loading. This can be useful if you use * tig(1) in a repository with a long history without limiting - * the log output. + * the revision log. * v:: * Show version. * n:: @@ -1913,7 +1919,7 @@ init_display(void) */ static struct ref *refs; -size_t refs_size; +static size_t refs_size; static struct ref ** get_refs(char *id) @@ -1953,8 +1959,8 @@ get_refs(char *id) static int load_refs(void) { - char *cmd_env = getenv("TIG_LS_REMOTE"); - char *cmd = cmd_env && *cmd_env ? cmd_env : TIG_LS_REMOTE; + const char *cmd_env = getenv("TIG_LS_REMOTE"); + const char *cmd = cmd_env && *cmd_env ? cmd_env : TIG_LS_REMOTE; FILE *pipe = popen(cmd, "r"); char buffer[BUFSIZ]; char *line; @@ -2015,6 +2021,9 @@ load_refs(void) pclose(pipe); + if (refs_size == 0) + die("Not a git repository"); + return OK; } @@ -2022,7 +2031,13 @@ load_refs(void) * Main */ -static void +#if __GNUC__ >= 3 +#define __NORETURN __attribute__((__noreturn__)) +#else +#define __NORETURN +#endif + +static void __NORETURN quit(int sig) { /* XXX: Restore tty modes and let the OS cleanup the rest! */ @@ -2031,7 +2046,7 @@ quit(int sig) exit(0); } -static void die(const char *err, ...) +static void __NORETURN die(const char *err, ...) { va_list args; @@ -2124,10 +2139,36 @@ main(int argc, char *argv[]) } /** - * Specifying revisions - * -------------------- - * This section describes various ways to specify what revisions to - * display or otherwise limit the view to. + * [[refspec]] + * Revision specification + * ---------------------- + * This section describes various ways to specify what revisions to display + * or otherwise limit the view to. tig(1) does not itself parse the described + * revision options so refer to the relevant git man pages for futher + * information. Relevant man pages besides git-log(1) are git-diff(1) and + * git-rev-list(1). + * + * You can tune the interaction with git by making use of the options + * explained in this section. For example, by configuring the environment + * variables described in the <> section. + * + * Limit by path name + * ~~~~~~~~~~~~~~~~~~ + * If you are interested only in those revisions that made changes to a + * specific file (or even several files) list the files like this: + * + * $ tig log Makefile + * + * To avoid ambiguity with repository references such as tag name, be sure + * to separate file names from other git options using "\--". So if you + * have a file named 'master' it will clash with the reference named + * 'master', and thus you will have to use: + * + * $ tig log -- master + * + * NOTE: For the main view, avoiding ambiguity will in some cases require + * you to specify two "\--" options. The first will make tig(1) stop + * option processing and the latter will be passed to git log. * * Limit by date or number * ~~~~~~~~~~~~~~~~~~~~~~~ @@ -2135,14 +2176,17 @@ main(int argc, char *argv[]) * to show both for the log and main view. Either limit by date using * e.g. `--since=1.month` or limit by the number of commits using `-n400`. * - * NOTE: You can tune the interaction with git by making use of the options - * explained in this section. + * If you are only interested in changed that happened between two dates + * you can use: * - * NOTE: tig(1) does not itself parse the revision options - * described in this section. + * $ tig -- --after=May.5th --before=2006-05-16.15:44 * - * Ranges - * ~~~~~~ + * NOTE: The dot (".") is used as a separator instead of a space to avoid + * having to quote the option value. If you prefer use `--after="May 5th"` + * instead of `--after="May 5th"`. + * + * Limiting by commit ranges + * ~~~~~~~~~~~~~~~~~~~~~~~~~ * Alternatively, commits can be limited to a specific range, such as * "all commits between 'tag-1.0' and 'tag-2.0'". For example: * @@ -2161,13 +2205,34 @@ main(int argc, char *argv[]) * ~~~~~~~~~~~~~~~~~~~~~~~~ * Git interprets the range specifier "tag-1.0..tag-2.0" as * "all commits reachable from 'tag-2.0' but not from 'tag-1.0'". + * Where reachability refers to what commits are ancestors (or part of the + * history) of the branch or tagged revision in question. + * * If you prefer to specify which commit to preview in this way use the * following: * * $ tig log tag-2.0 ^tag-1.0 * - * You can think of '^' as a negator. Using this alternate syntax, it is - * possible to furthur prune commits by specifying multiple negators. + * You can think of '^' as a negation operator. Using this alternate syntax, + * it is possible to further prune commits by specifying multiple branch + * cut offs. + * + * Combining revisions specification + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Revisions options can to some degree be combined, which makes it possible + * to say "show at most 20 commits from within the last month that changed + * files under the Documentation/ directory." + * + * $ tig -- --since=1.month -n20 -- Documentation/ + * + * Examining all repository references + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * In some cases, it can be useful to query changes across all references + * in a repository. An example is to ask "did any line of development in + * this repository change a particular file within the last week". This + * can be accomplished using: + * + * $ tig -- --all --since=1.week -- Makefile * * BUGS * ----