clar: update to fix compilation on platforms without PATH_MAX

Update clar to e4172e3 (Merge pull request #134 from clar-test/ethomson/const, 2026-01-10). Besides some changes to "generate.py" which don't have any impact on us, this commit also fixes compilation on platforms that don't have PATH_MAX, like for example GNU/Hurd. Reported-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Mar 16, 2026 at 08:50 UTC 3cf4024117f5c15361e68c5d9b0c3e9dd01ec105
2 files changed +68 -15
t/unit-tests/clar/clar.h
+3 -1
@@ -15,8 +15,10 @@
15 # define CLAR_MAX_PATH 4096
16 #elif defined(_WIN32)
17 # define CLAR_MAX_PATH MAX_PATH
18 -#else
18 +#elif defined(PATH_MAX)
19 # define CLAR_MAX_PATH PATH_MAX
20 +#else
21 +# define CLAR_MAX_PATH 4096
22 #endif
23
24 #ifndef CLAR_SELFTEST
t/unit-tests/clar/generate.py
+65 -14
@@ -8,7 +8,7 @@
8
9 from __future__ import with_statement
10 from string import Template
11 -import re, fnmatch, os, sys, codecs, pickle
11 +import re, fnmatch, os, sys, codecs, pickle, io
12
13 class Module(object):
14 class Template(object):
@@ -147,7 +147,7 @@ class TestSuite(object):
147 self.path = path
148 self.output = output
149
150 - def should_generate(self, path):
150 + def maybe_generate(self, path):
151 if not os.path.isfile(path):
152 return True
153
@@ -223,34 +223,85 @@ class TestSuite(object):
223 return sum(len(module.callbacks) for module in self.modules.values())
224
225 def write(self):
226 - output = os.path.join(self.output, 'clar.suite')
227 - os.makedirs(self.output, exist_ok=True)
226 + if not os.path.exists(self.output):
227 + os.makedirs(self.output)
228
229 - if not self.should_generate(output):
229 + wrote_suite = self.write_suite()
230 + wrote_header = self.write_header()
231 +
232 + if wrote_suite or wrote_header:
233 + self.save_cache()
234 + return True
235 +
236 + return False
237 +
238 + def write_output(self, fn, data):
239 + if not self.maybe_generate(fn):
240 + return False
241 +
242 + current = None
243 +
244 + try:
245 + with open(fn, 'r') as input:
246 + current = input.read()
247 + except OSError:
248 + pass
249 + except IOError:
250 + pass
251 +
252 + if current == data:
253 return False
254
232 - with open(output, 'w') as data:
255 + with open(fn, 'w') as output:
256 + output.write(data)
257 +
258 + return True
259 +
260 + def write_suite(self):
261 + suite_fn = os.path.join(self.output, 'clar.suite')
262 +
263 + with io.StringIO() as suite_file:
264 modules = sorted(self.modules.values(), key=lambda module: module.name)
265
266 for module in modules:
267 t = Module.DeclarationTemplate(module)
237 - data.write(t.render())
268 + suite_file.write(t.render())
269
270 for module in modules:
271 t = Module.CallbacksTemplate(module)
241 - data.write(t.render())
272 + suite_file.write(t.render())
273
274 suites = "static struct clar_suite _clar_suites[] = {" + ','.join(
275 Module.InfoTemplate(module).render() for module in modules
276 ) + "\n};\n"
277
247 - data.write(suites)
278 + suite_file.write(suites)
279
249 - data.write("static const size_t _clar_suite_count = %d;\n" % self.suite_count())
250 - data.write("static const size_t _clar_callback_count = %d;\n" % self.callback_count())
280 + suite_file.write(u"static const size_t _clar_suite_count = %d;\n" % self.suite_count())
281 + suite_file.write(u"static const size_t _clar_callback_count = %d;\n" % self.callback_count())
282
252 - self.save_cache()
253 - return True
283 + return self.write_output(suite_fn, suite_file.getvalue())
284 +
285 + return False
286 +
287 + def write_header(self):
288 + header_fn = os.path.join(self.output, 'clar_suite.h')
289 +
290 + with io.StringIO() as header_file:
291 + header_file.write(u"#ifndef _____clar_suite_h_____\n")
292 + header_file.write(u"#define _____clar_suite_h_____\n")
293 +
294 + modules = sorted(self.modules.values(), key=lambda module: module.name)
295 +
296 + for module in modules:
297 + t = Module.DeclarationTemplate(module)
298 + header_file.write(t.render())
299 +
300 + header_file.write(u"#endif\n")
301 +
302 + return self.write_output(header_fn, header_file.getvalue())
303 +
304 + return False
305
306 if __name__ == '__main__':
307 from optparse import OptionParser
@@ -275,4 +326,4 @@ if __name__ == '__main__':
326 suite.load(options.force)
327 suite.disable(options.excluded)
328 if suite.write():
278 - print("Written `clar.suite` (%d tests in %d suites)" % (suite.callback_count(), suite.suite_count()))
329 + print("Written `clar.suite`, `clar_suite.h` (%d tests in %d suites)" % (suite.callback_count(), suite.suite_count()))