1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
From 47548a77525a0f4489c9c420ccc2159079365da8 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Fri, 2 May 2025 12:09:40 +0200
Subject: [PATCH] vc-mtime: Make it work with git versions < 2.28.
* lib/vc-mtime.c (git_version): New variable.
(is_git_present): Read the output of "git --version", and set
git_version.
(max_vc_mtime): Don't pass option --no-relative if the git version
is < 2.28.
---
ChangeLog | 9 ++++++
lib/vc-mtime.c | 82 +++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 83 insertions(+), 8 deletions(-)
--- a/lib/vc-mtime.c
+++ b/lib/vc-mtime.c
@@ -53,7 +53,9 @@
/* ========================================================================== */
-/* Determines whether git is present. */
+static const char *git_version;
+
+/* Determines whether git is present, and sets git_version if so. */
static bool
is_git_present (void)
{
@@ -63,17 +65,67 @@ is_git_present (void)
if (!git_tested)
{
/* Test for presence of git:
- "git --version >/dev/null 2>/dev/null" */
+ "git --version 2>/dev/null" */
const char *argv[3];
- int exitstatus;
+ pid_t child;
+ int fd[1];
argv[0] = "git";
argv[1] = "--version";
argv[2] = NULL;
- exitstatus = execute ("git", "git", argv, NULL, NULL,
- false, false, true, true,
- true, false, NULL);
- git_present = (exitstatus == 0);
+ child = create_pipe_in ("git", "git", argv, NULL, NULL,
+ DEV_NULL, true, true, false, fd);
+ if (child == -1)
+ git_present = false;
+ else
+ {
+ /* Retrieve its result. */
+ FILE *fp = fdopen (fd[0], "r");
+ if (fp == NULL)
+ error (EXIT_FAILURE, errno, _("fdopen() failed"));
+
+ char *line = NULL;
+ size_t linesize = 0;
+ size_t linelen = getline (&line, &linesize, fp);
+ if (linelen == (size_t)(-1))
+ {
+ fclose (fp);
+ wait_subprocess (child, "git", true, true, true, false, NULL);
+ git_present = false;
+ }
+ else
+ {
+ if (linelen > 0 && line[linelen - 1] == '\n')
+ line[linelen - 1] = '\0';
+
+ /* Read until EOF (otherwise the child process may get a SIGPIPE
+ signal). */
+ while (getc (fp) != EOF)
+ ;
+
+ fclose (fp);
+
+ /* Remove zombie process from process list, and retrieve exit
+ status. */
+ int exitstatus =
+ wait_subprocess (child, "git", true, true, true, false, NULL);
+ if (exitstatus != 0)
+ {
+ free (line);
+ git_present = false;
+ }
+ else
+ {
+ /* The version starts at the first digit in the line. */
+ const char *p = line;
+ for (; *p != '0'; p++)
+ if (*p >= '0' && *p <= '9')
+ break;
+ git_version = p;
+ git_present = true;
+ }
+ }
+ }
git_tested = true;
}
@@ -660,7 +712,21 @@ max_vc_mtime (struct timespec *max_of_mt
argv[i++] = "git";
argv[i++] = "diff";
argv[i++] = "--name-only";
- argv[i++] = "--no-relative";
+ /* With git versions >= 2.28, we pass option --no-relative,
+ in order to neutralize any possible customization of the
+ "diff.relative" property. With git versions < 2.28, this
+ is not needed, and the option --no-relative does not
+ exist. */
+ if (!(git_version[0] <= '1'
+ || (git_version[0] == '2' && git_version[1] == '.'
+ && ((git_version[2] >= '0' && git_version[2] <= '9'
+ && !(git_version[3] >= '0' && git_version[3] <= '9'))
+ || (((git_version[2] == '1'
+ && git_version[3] >= '0' && git_version[3] <= '9')
+ || (git_version[2] == '2'
+ && git_version[3] >= '0' && git_version[3] <= '7'))
+ && !(git_version[4] >= '0' && git_version[4] <= '9'))))))
+ argv[i++] = "--no-relative";
argv[i++] = "-z";
argv[i++] = "HEAD";
argv[i++] = "--";
|