"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Martin Pieuchot <mpi@openbsd.org>
Subject:
Re: tog(1) log by default++
To:
gameoftrees@openbsd.org
Date:
Sat, 29 Feb 2020 12:21:54 +0100

Download raw body.

Thread
  • Martin Pieuchot:

    tog(1) log by default++

  • 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) {
    
    
    
  • Martin Pieuchot:

    tog(1) log by default++