[prev in list] [next in list] [prev in thread] [next in thread]
List: gameoftrees
Subject: Re: tog(1) log by default++
From: Martin Pieuchot <mpi () openbsd ! org>
Date: 2020-02-29 11:21:54
Message-ID: 20200229112154.GB70350 () oliva ! grenadille ! net
[Download RAW message or body]
On 28/02/20(Fri) 21:09, Stefan Sperling wrote:
> On Fri, Feb 28, 2020 at 07:42:50PM +0100, Stefan Sperling wrote:
> > Either way, it means that this feature request looks small on the
> > surface but actually creates a lot of work for me.
>
> See? You made me do it :-P
Thank you so much :o)
>
> This diff resolves the specified path upfront. Which is also hacky
> but at least this is not racy and has good error reporting.
>
> I don't think we should have hidden usages so this should be
> documented in plain sight (within the man page and tog -h).
I love being the lazy guy!
> Does this still work as expected?
> Please fetch latest commits before applying this diff.
I does! Thanks \o/
> diff a2f4a3591f215ab55f58ef4ee630b960af87a4d5 /home/stsp/src/got
> blob - bda2731240200f40602cfea8febe058252a6059f
> file + tog/tog.1
> --- tog/tog.1
> +++ tog/tog.1
> @@ -21,9 +21,13 @@
> .Nd Git repository browser
> .Sh SYNOPSIS
> .Nm
> -.Ar command
> +.Op Ar command
> .Op Fl h
> .Op Ar arg ...
> +.Pp
> +.Nm
> +.Ar path
> +.El
> .Sh DESCRIPTION
> .Nm
> is an interactive read-only browser for Git repositories.
> @@ -37,6 +41,8 @@ supports several types of views which display reposito
> Displays commits in the repository's history.
> This view is displayed initially if no
> .Ar command
> +is specified, or if just a
> +.Ar path
> is specified.
> .It Diff view
> Displays changes made in a particular commit.
> blob - c91d11d969cc44a6e226b70fc4c3a355600a9218
> file + tog/tog.c
> --- tog/tog.c
> +++ tog/tog.c
> @@ -26,6 +26,7 @@
> #include <locale.h>
> #include <signal.h>
> #include <stdlib.h>
> +#include <stdarg.h>
> #include <stdio.h>
> #include <getopt.h>
> #include <string.h>
> @@ -5333,34 +5334,133 @@ list_commands(void)
> __dead static void
> usage(int hflag)
> {
> - fprintf(stderr, "usage: %s [-h] [-V | --version] [command] [arg ...]\n",
> - getprogname());
> - if (hflag)
> + fprintf(stderr, "usage: %s [-h] [-V | --version] [command] "
> + "[arg ...]\n", getprogname());
> + if (hflag) {
> + fprintf(stderr, "lazy usage: %s path\n", getprogname());
> list_commands();
> + }
> exit(1);
> }
>
> static char **
> -make_argv(const char *arg0, const char *arg1)
> +make_argv(int argc, ...)
> {
> + va_list ap;
> char **argv;
> - int argc = (arg1 == NULL ? 1 : 2);
> + int i;
>
> + va_start(ap, argc);
> +
> argv = calloc(argc, sizeof(char *));
> if (argv == NULL)
> err(1, "calloc");
> - argv[0] = strdup(arg0);
> - if (argv[0] == NULL)
> - err(1, "strdup");
> - if (arg1) {
> - argv[1] = strdup(arg1);
> - if (argv[1] == NULL)
> + for (i = 0; i < argc; i++) {
> + argv[i] = strdup(va_arg(ap, char *));
> + if (argv[i] == NULL)
> err(1, "strdup");
> }
>
> + va_end(ap);
> return argv;
> }
>
> +/*
> + * Try to convert 'tog path' into a 'tog log path' command.
> + * The user could simply have mistyped the command rather than knowingly
> + * provided a path. So check whether argv[0] can in fact be resolved
> + * to a path in the HEAD commit and print a special error if not.
> + * This hack is for mpi@ <3
> + */
> +const struct got_error *
> +tog_log_with_path(int argc, char *argv[])
> +{
> + const struct got_error *error = NULL;
> + struct tog_cmd *cmd = NULL;
> + struct got_repository *repo = NULL;
> + struct got_worktree *worktree = NULL;
> + struct got_object_id *commit_id = NULL, *id = NULL;
> + char *cwd = NULL, *repo_path = NULL, *in_repo_path = NULL;
> + char *commit_id_str = NULL, **cmd_argv = NULL;
> +
> + cwd = getcwd(NULL, 0);
> + if (cwd == NULL)
> + return got_error_from_errno("getcwd");
> +
> + error = got_worktree_open(&worktree, cwd);
> + if (error && error->code != GOT_ERR_NOT_WORKTREE)
> + goto done;
> +
> + if (worktree)
> + repo_path = strdup(got_worktree_get_repo_path(worktree));
> + else
> + repo_path = strdup(cwd);
> + if (repo_path == NULL) {
> + error = got_error_from_errno("strdup");
> + goto done;
> + }
> +
> + error = got_repo_open(&repo, repo_path, NULL);
> + if (error != NULL)
> + goto done;
> +
> + error = get_in_repo_path_from_argv0(&in_repo_path, argc, argv,
> + repo, worktree);
> + if (error)
> + goto done;
> +
> + error = got_repo_match_object_id(&commit_id, NULL, worktree ?
> + got_worktree_get_head_ref_name(worktree) : GOT_REF_HEAD,
> + GOT_OBJ_TYPE_COMMIT, 1, repo);
> + if (error)
> + goto done;
> +
> + if (worktree) {
> + got_worktree_close(worktree);
> + worktree = NULL;
> + }
> +
> + error = got_object_id_by_path(&id, repo, commit_id, in_repo_path);
> + if (error) {
> + if (error->code != GOT_ERR_NO_TREE_ENTRY)
> + goto done;
> + fprintf(stderr, "%s: '%s' is no known command or path\n",
> + getprogname(), argv[0]);
> + usage(1);
> + /* not reached */
> + }
> +
> + got_repo_close(repo);
> + repo = NULL;
> +
> + error = got_object_id_str(&commit_id_str, commit_id);
> + if (error)
> + goto done;
> +
> + cmd = &tog_commands[0]; /* log */
> + argc = 4;
> + cmd_argv = make_argv(argc, cmd->name, "-c", commit_id_str, argv[0]);
> + error = cmd->cmd_main(argc, cmd_argv);
> +done:
> + if (repo)
> + got_repo_close(repo);
> + if (worktree)
> + got_worktree_close(worktree);
> + free(id);
> + free(commit_id_str);
> + free(commit_id);
> + free(cwd);
> + free(repo_path);
> + free(in_repo_path);
> + if (cmd_argv) {
> + int i;
> + for (i = 0; i < argc; i++)
> + free(cmd_argv[i]);
> + free(cmd_argv);
> + }
> + return error;
> +}
> +
> int
> main(int argc, char *argv[])
> {
> @@ -5404,8 +5504,8 @@ main(int argc, char *argv[])
> usage(hflag);
> /* Build an argument vector which runs a default command. */
> cmd = &tog_commands[0];
> - cmd_argv = make_argv(cmd->name, NULL);
> argc = 1;
> + cmd_argv = make_argv(argc, cmd->name);
> } else {
> int i;
>
> @@ -5417,19 +5517,19 @@ main(int argc, char *argv[])
> break;
> }
> }
> -
> - if (cmd == NULL) {
> - fprintf(stderr, "%s: unknown command '%s'\n",
> - getprogname(), argv[0]);
> - list_commands();
> - return 1;
> - }
> }
>
> - if (hflag)
> - cmd->cmd_usage();
> - else
> - error = cmd->cmd_main(argc, cmd_argv ? cmd_argv : argv);
> + if (cmd == NULL) {
> + if (argc != 1)
> + usage(0);
> + /* No command specified; try log with a path */
> + error = tog_log_with_path(argc, argv);
> + } else {
> + if (hflag)
> + cmd->cmd_usage();
> + else
> + error = cmd->cmd_main(argc, cmd_argv ? cmd_argv : argv);
> + }
>
> endwin();
> if (cmd_argv) {
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic