Re: To page or not to page

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, May 02, 2008 at 11:18:02AM -0700, Junio C Hamano wrote:

> Hmm. How about doing things this way?
> 
>  - at the beginning of handle_options() remember argv[0]
> 
>  - restructure handle_options() so that it does not run setup_pager() and
>    setenv("GIT_PAGER", "cat", 1) inside the loop, but instead remember
>    what we had on the command line;
> 
>  - after the handle_options() loop, if we saw an explicit --pager,
>    --no-pager, that's the decision;

This is actually a bit tricky, since there are two code paths; builtins
called as git-foo never even go to handle_options, but they can still
look up the config value.

So how about this:

 - keep a global use_pager = { 0 (explicit no), 1 (explicit yes), -1
   (unknown) }

 - if git-foo, lookup config for pager.foo

 - otherwise we have "git [options] foo"; look for -p / --no-pager; if
   none found, then lookup config for "foo"

 - before proceeding further, "commit" the pager choice by running it
   (if 1), munging GIT_PAGER=cat (if 0), or doing nothing (if -1)

 - before handling an internal command, if use_pager is -1 and the
   command defaults to a pager, we run it then

The patch below implements this.

It would be nice to actually defer running the pager until we are about
to run a git command. I.e., never "commit" to the pager until we are
actually running an internal command or exec'ing an external command.
That way it would be safe to make an alias that called "--no-pager"
(which is currently disallowed).

That works for internal commands, since we know we are going to run one,
and if it fails, we die.  However, for external commands, we just exec
and hope it works. So if we run the pager beforehand, we are now
committed to it, and a further alias cannot set --no-pager. We could
alternatively run it after deciding that running the command is what
we'll do, but then we have to do the PATH lookup ourselves.

So anyway, here is the less invasive version.

---
 git.c |   48 ++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/git.c b/git.c
index 89b431f..dadca41 100644
--- a/git.c
+++ b/git.c
@@ -6,12 +6,46 @@
 const char git_usage_string[] =
 	"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
 
+static int use_pager = -1;
+static const char *pager_command_key;
+static int pager_command_value;
+
+int pager_command_config(const char *var, const char *value)
+{
+	if (!prefixcmp(var, "pager.") && !strcmp(var + 6, pager_command_key))
+		pager_command_value = git_config_bool(var, value);
+	return 0;
+}
+
+/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
+int check_pager_config(const char *cmd)
+{
+	pager_command_key = cmd;
+	pager_command_value = -1;
+	git_config(pager_command_config);
+	return pager_command_value;
+}
+
+static void commit_pager_choice(void) {
+	switch (use_pager) {
+	case 0:
+		setenv("GIT_PAGER", "cat", 1);
+		break;
+	case 1:
+		setup_pager();
+		break;
+	default:
+		break;
+	}
+}
+
 static int handle_options(const char*** argv, int* argc, int* envchanged)
 {
 	int handled = 0;
+	const char *cmd = NULL;
 
 	while (*argc > 0) {
-		const char *cmd = (*argv)[0];
+		cmd = (*argv)[0];
 		if (cmd[0] != '-')
 			break;
 
@@ -35,9 +69,9 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
 				exit(0);
 			}
 		} else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
-			setup_pager();
+			use_pager = 1;
 		} else if (!strcmp(cmd, "--no-pager")) {
-			setenv("GIT_PAGER", "cat", 1);
+			use_pager = 0;
 			if (envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--git-dir")) {
@@ -84,6 +118,9 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
 		(*argc)--;
 		handled++;
 	}
+
+	if (use_pager == -1 && cmd)
+		use_pager = check_pager_config(cmd);
 	return handled;
 }
 
@@ -239,7 +276,7 @@ static int run_command(struct cmd_struct *p, int argc, const char **argv)
 	prefix = NULL;
 	if (p->option & RUN_SETUP)
 		prefix = setup_git_directory();
-	if (p->option & USE_PAGER)
+	if (use_pager == -1 && p->option & USE_PAGER)
 		setup_pager();
 	if (p->option & NEED_WORK_TREE)
 		setup_work_tree();
@@ -411,6 +448,8 @@ int main(int argc, const char **argv)
 	if (!prefixcmp(cmd, "git-")) {
 		cmd += 4;
 		argv[0] = cmd;
+		use_pager = check_pager_config(cmd);
+		commit_pager_choice();
 		handle_internal_command(argc, argv);
 		die("cannot handle %s internally", cmd);
 	}
@@ -419,6 +458,7 @@ int main(int argc, const char **argv)
 	argv++;
 	argc--;
 	handle_options(&argv, &argc, NULL);
+	commit_pager_choice();
 	if (argc > 0) {
 		if (!prefixcmp(argv[0], "--"))
 			argv[0] += 2;
-- 
1.5.5.1.244.g148a.dirty

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux