Mercurial > hg
annotate contrib/chg/util.c @ 35923:efbd04238029
cmdutil: convert _revertprefetch() to a generic stored file hook (API)
This will be used by LFS to fetch required files in a group for multiple
commands, prior to being accessed. That avoids the one-at-a-time fetch when the
filelog wrapper goes to access it, and it is missing locally (which costs two
round trips to the server.) The core command list that needs this is probably
at least:
- annotate
- archive (which is also used by extdiff)
- cat
- diff
- export
- grep
- verify (sadly)
- anything that has the '{data}' template
There are no core users of the revert prefetch hook, and never have been since
it was introduced in 45e02cfad4bd for remotefilelog. Thanks to Yuya for
figuring out a way to reliably trigger the deprecated warning. Unfortunately,
it wanted to blame the caller of revert. Passing along an adjusted stack level
seemed the least bad choice (although it still blames a core function).
One thing to note is that the store lock isn't being held when this is called.
I'm not at all familiar with remotefilelog or its locking requirements, so this
may not be a big deal. Currently, LFS doesn't hold a lock when downloading
files. Even though largefiles doesn't either, I'm starting to think it should,
and maybe the .hg/store/lock isn't good enough to cover the globally shared
cache.
.. api::
The cmdutil._revertprefetch() hook point for prefetching stored files has
been replaced by the command agnostic cmdutil._prefetchfiles(). The new
function takes a list of files, instead of a list of lists of files.
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Sun, 04 Feb 2018 14:14:28 -0500 |
parents | b94db1780365 |
children | 9724f54923ec |
rev | line source |
---|---|
28060 | 1 /* |
2 * Utility functions | |
3 * | |
4 * Copyright (c) 2011 Yuya Nishihara <yuya@tcha.org> | |
5 * | |
6 * This software may be used and distributed according to the terms of the | |
7 * GNU General Public License version 2 or any later version. | |
8 */ | |
9 | |
28788
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
10 #include <errno.h> |
28855
f5764e177bbe
chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents:
28854
diff
changeset
|
11 #include <fcntl.h> |
28060 | 12 #include <signal.h> |
13 #include <stdarg.h> | |
14 #include <stdio.h> | |
15 #include <stdlib.h> | |
28084
3fc45956c978
chg: initialize sigaction fields more reliably
Yuya Nishihara <yuya@tcha.org>
parents:
28060
diff
changeset
|
16 #include <string.h> |
34309
b94db1780365
chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents:
28855
diff
changeset
|
17 #include <sys/time.h> |
28060 | 18 #include <sys/types.h> |
19 #include <sys/wait.h> | |
20 #include <unistd.h> | |
21 | |
22 #include "util.h" | |
23 | |
28787
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
24 static int colorenabled = 0; |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
25 |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
26 static inline void fsetcolor(FILE *fp, const char *code) |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
27 { |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
28 if (!colorenabled) |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
29 return; |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
30 fprintf(fp, "\033[%sm", code); |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
31 } |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
32 |
28788
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
33 static void vabortmsgerrno(int no, const char *fmt, va_list args) |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
34 { |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
35 fsetcolor(stderr, "1;31"); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
36 fputs("chg: abort: ", stderr); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
37 vfprintf(stderr, fmt, args); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
38 if (no != 0) |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
39 fprintf(stderr, " (errno = %d, %s)", no, strerror(no)); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
40 fsetcolor(stderr, ""); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
41 fputc('\n', stderr); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
42 exit(255); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
43 } |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
44 |
28060 | 45 void abortmsg(const char *fmt, ...) |
46 { | |
47 va_list args; | |
48 va_start(args, fmt); | |
28788
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
49 vabortmsgerrno(0, fmt, args); |
28060 | 50 va_end(args); |
28788
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
51 } |
28060 | 52 |
28788
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
53 void abortmsgerrno(const char *fmt, ...) |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
54 { |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
55 int no = errno; |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
56 va_list args; |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
57 va_start(args, fmt); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
58 vabortmsgerrno(no, fmt, args); |
57a78a64de44
chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
59 va_end(args); |
28060 | 60 } |
61 | |
62 static int debugmsgenabled = 0; | |
34309
b94db1780365
chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents:
28855
diff
changeset
|
63 static double debugstart = 0; |
b94db1780365
chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents:
28855
diff
changeset
|
64 |
b94db1780365
chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents:
28855
diff
changeset
|
65 static double now() { |
b94db1780365
chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents:
28855
diff
changeset
|
66 struct timeval t; |
b94db1780365
chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents:
28855
diff
changeset
|
67 gettimeofday(&t, NULL); |
b94db1780365
chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents:
28855
diff
changeset
|
68 return t.tv_usec / 1e6 + t.tv_sec; |
b94db1780365
chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents:
28855
diff
changeset
|
69 } |
28060 | 70 |
28787
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
71 void enablecolor(void) |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
72 { |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
73 colorenabled = 1; |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
74 } |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
75 |
28060 | 76 void enabledebugmsg(void) |
77 { | |
78 debugmsgenabled = 1; | |
34309
b94db1780365
chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents:
28855
diff
changeset
|
79 debugstart = now(); |
28060 | 80 } |
81 | |
82 void debugmsg(const char *fmt, ...) | |
83 { | |
84 if (!debugmsgenabled) | |
85 return; | |
86 | |
87 va_list args; | |
88 va_start(args, fmt); | |
28787
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
89 fsetcolor(stderr, "1;30"); |
34309
b94db1780365
chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents:
28855
diff
changeset
|
90 fprintf(stderr, "chg: debug: %4.6f ", now() - debugstart); |
28060 | 91 vfprintf(stderr, fmt, args); |
28787
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
92 fsetcolor(stderr, ""); |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28165
diff
changeset
|
93 fputc('\n', stderr); |
28060 | 94 va_end(args); |
95 } | |
96 | |
28854
ddef14468952
chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents:
28788
diff
changeset
|
97 void fchdirx(int dirfd) |
ddef14468952
chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents:
28788
diff
changeset
|
98 { |
ddef14468952
chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents:
28788
diff
changeset
|
99 int r = fchdir(dirfd); |
ddef14468952
chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents:
28788
diff
changeset
|
100 if (r == -1) |
ddef14468952
chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents:
28788
diff
changeset
|
101 abortmsgerrno("failed to fchdir"); |
ddef14468952
chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents:
28788
diff
changeset
|
102 } |
ddef14468952
chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents:
28788
diff
changeset
|
103 |
28855
f5764e177bbe
chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents:
28854
diff
changeset
|
104 void fsetcloexec(int fd) |
f5764e177bbe
chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents:
28854
diff
changeset
|
105 { |
f5764e177bbe
chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents:
28854
diff
changeset
|
106 int flags = fcntl(fd, F_GETFD); |
f5764e177bbe
chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents:
28854
diff
changeset
|
107 if (flags < 0) |
f5764e177bbe
chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents:
28854
diff
changeset
|
108 abortmsgerrno("cannot get flags of fd %d", fd); |
f5764e177bbe
chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents:
28854
diff
changeset
|
109 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) |
f5764e177bbe
chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents:
28854
diff
changeset
|
110 abortmsgerrno("cannot set flags of fd %d", fd); |
f5764e177bbe
chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents:
28854
diff
changeset
|
111 } |
f5764e177bbe
chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents:
28854
diff
changeset
|
112 |
28165
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
113 void *mallocx(size_t size) |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
114 { |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
115 void *result = malloc(size); |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
116 if (!result) |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
117 abortmsg("failed to malloc"); |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
118 return result; |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
119 } |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
120 |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
121 void *reallocx(void *ptr, size_t size) |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
122 { |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
123 void *result = realloc(ptr, size); |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
124 if (!result) |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
125 abortmsg("failed to realloc"); |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
126 return result; |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
127 } |
c6705c6303dd
chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents:
28084
diff
changeset
|
128 |
28060 | 129 /* |
130 * Execute a shell command in mostly the same manner as system(), with the | |
131 * give environment variables, after chdir to the given cwd. Returns a status | |
132 * code compatible with the Python subprocess module. | |
133 */ | |
134 int runshellcmd(const char *cmd, const char *envp[], const char *cwd) | |
135 { | |
136 enum { F_SIGINT = 1, F_SIGQUIT = 2, F_SIGMASK = 4, F_WAITPID = 8 }; | |
137 unsigned int doneflags = 0; | |
138 int status = 0; | |
139 struct sigaction newsa, oldsaint, oldsaquit; | |
140 sigset_t oldmask; | |
141 | |
142 /* block or mask signals just as system() does */ | |
28084
3fc45956c978
chg: initialize sigaction fields more reliably
Yuya Nishihara <yuya@tcha.org>
parents:
28060
diff
changeset
|
143 memset(&newsa, 0, sizeof(newsa)); |
28060 | 144 newsa.sa_handler = SIG_IGN; |
145 newsa.sa_flags = 0; | |
146 if (sigemptyset(&newsa.sa_mask) < 0) | |
147 goto done; | |
148 if (sigaction(SIGINT, &newsa, &oldsaint) < 0) | |
149 goto done; | |
150 doneflags |= F_SIGINT; | |
151 if (sigaction(SIGQUIT, &newsa, &oldsaquit) < 0) | |
152 goto done; | |
153 doneflags |= F_SIGQUIT; | |
154 | |
155 if (sigaddset(&newsa.sa_mask, SIGCHLD) < 0) | |
156 goto done; | |
157 if (sigprocmask(SIG_BLOCK, &newsa.sa_mask, &oldmask) < 0) | |
158 goto done; | |
159 doneflags |= F_SIGMASK; | |
160 | |
161 pid_t pid = fork(); | |
162 if (pid < 0) | |
163 goto done; | |
164 if (pid == 0) { | |
165 sigaction(SIGINT, &oldsaint, NULL); | |
166 sigaction(SIGQUIT, &oldsaquit, NULL); | |
167 sigprocmask(SIG_SETMASK, &oldmask, NULL); | |
168 if (cwd && chdir(cwd) < 0) | |
169 _exit(127); | |
170 const char *argv[] = {"sh", "-c", cmd, NULL}; | |
171 if (envp) { | |
172 execve("/bin/sh", (char **)argv, (char **)envp); | |
173 } else { | |
174 execv("/bin/sh", (char **)argv); | |
175 } | |
176 _exit(127); | |
177 } else { | |
178 if (waitpid(pid, &status, 0) < 0) | |
179 goto done; | |
180 doneflags |= F_WAITPID; | |
181 } | |
182 | |
183 done: | |
184 if (doneflags & F_SIGINT) | |
185 sigaction(SIGINT, &oldsaint, NULL); | |
186 if (doneflags & F_SIGQUIT) | |
187 sigaction(SIGQUIT, &oldsaquit, NULL); | |
188 if (doneflags & F_SIGMASK) | |
189 sigprocmask(SIG_SETMASK, &oldmask, NULL); | |
190 | |
191 /* no way to report other errors, use 127 (= shell termination) */ | |
192 if (!(doneflags & F_WAITPID)) | |
193 return 127; | |
194 if (WIFEXITED(status)) | |
195 return WEXITSTATUS(status); | |
196 if (WIFSIGNALED(status)) | |
197 return -WTERMSIG(status); | |
198 return 127; | |
199 } |