[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