aboutsummaryrefslogtreecommitdiff
path: root/tools/gnulib/patches/799-vc-mtime-old-git.patch
blob: 4c2082504b577618bf8252d4d949d897f6169e59 (plain)
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++] = "--";