Skip to content

Commit ea27a18

Browse files
peffgitster
authored andcommitted
spawn pager via run_command interface
This has two important effects: 1. The pager is now the _child_ process, instead of the parent. This means that whatever spawned git (e.g., the shell) will see the exit code of the git process, and not the pager. 2. The mingw and regular code are now unified, which makes the setup_pager function much simpler. There are two caveats: 1. We used to call execlp directly on the pager, followed by trying to exec it via the shall. We now just use the shell (which is what mingw has always done). This may have different results for pager names which contain shell metacharacters. It is also slightly less efficient because we unnecessarily run the shell; however, pager spawning is by definition an interactive task, so it shouldn't be a huge problem. 2. The git process will remain in memory while the user looks through the pager. This is potentially wasteful. We could get around this by turning the parent into a meta-process which spawns _both_ git and the pager, collects the exit status from git, waits for both to end, and then exits with git's exit code. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ccf08bc commit ea27a18

File tree

1 file changed

+11
-44
lines changed

1 file changed

+11
-44
lines changed

pager.c

Lines changed: 11 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "cache.h"
2+
#include "run-command.h"
23

34
/*
45
* This is split up from the rest of git so that we can do
@@ -8,7 +9,7 @@
89
static int spawned_pager;
910

1011
#ifndef __MINGW32__
11-
static void run_pager(const char *pager)
12+
static void pager_preexec(void)
1213
{
1314
/*
1415
* Work around bug in "less" by not starting it until we
@@ -20,17 +21,13 @@ static void run_pager(const char *pager)
2021
FD_SET(0, &in);
2122
select(1, &in, NULL, &in, NULL);
2223

23-
execlp(pager, pager, NULL);
24-
execl("/bin/sh", "sh", "-c", pager, NULL);
24+
setenv("LESS", "FRSX", 0);
2525
}
26-
#else
27-
#include "run-command.h"
26+
#endif
2827

2928
static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
30-
static struct child_process pager_process = {
31-
.argv = pager_argv,
32-
.in = -1
33-
};
29+
static struct child_process pager_process;
30+
3431
static void wait_for_pager(void)
3532
{
3633
fflush(stdout);
@@ -40,14 +37,9 @@ static void wait_for_pager(void)
4037
close(2);
4138
finish_command(&pager_process);
4239
}
43-
#endif
4440

4541
void setup_pager(void)
4642
{
47-
#ifndef __MINGW32__
48-
pid_t pid;
49-
int fd[2];
50-
#endif
5143
const char *pager = getenv("GIT_PAGER");
5244

5345
if (!isatty(1))
@@ -66,37 +58,13 @@ void setup_pager(void)
6658

6759
spawned_pager = 1; /* means we are emitting to terminal */
6860

69-
#ifndef __MINGW32__
70-
if (pipe(fd) < 0)
71-
return;
72-
pid = fork();
73-
if (pid < 0) {
74-
close(fd[0]);
75-
close(fd[1]);
76-
return;
77-
}
78-
79-
/* return in the child */
80-
if (!pid) {
81-
dup2(fd[1], 1);
82-
dup2(fd[1], 2);
83-
close(fd[0]);
84-
close(fd[1]);
85-
return;
86-
}
87-
88-
/* The original process turns into the PAGER */
89-
dup2(fd[0], 0);
90-
close(fd[0]);
91-
close(fd[1]);
92-
93-
setenv("LESS", "FRSX", 0);
94-
run_pager(pager);
95-
die("unable to execute pager '%s'", pager);
96-
exit(255);
97-
#else
9861
/* spawn the pager */
9962
pager_argv[2] = pager;
63+
pager_process.argv = pager_argv;
64+
pager_process.in = -1;
65+
#ifndef __MINGW32__
66+
pager_process.preexec_cb = pager_preexec;
67+
#endif
10068
if (start_command(&pager_process))
10169
return;
10270

@@ -107,7 +75,6 @@ void setup_pager(void)
10775

10876
/* this makes sure that the parent terminates after the pager */
10977
atexit(wait_for_pager);
110-
#endif
11178
}
11279

11380
int pager_in_use(void)

0 commit comments

Comments
 (0)