2 from __future__ import absolute_import, print_function
4 from binascii import hexlify, unhexlify
5 from subprocess import check_call
6 from functools import partial
10 from wvpytest import *
12 from bup import git, path
13 from bup.compat import bytes_from_byte, environ
14 from bup.helpers import localtime, log, mkdirp, readpipe
21 print(repr(cmd), file=sys.stderr)
26 print(repr(cmd), file=sys.stderr)
30 def test_git_version_detection():
31 # Test version types from git's tag history
32 for expected, ver in \
33 (('insufficient', b'git version 0.99'),
34 ('insufficient', b'git version 0.99.1'),
35 ('insufficient', b'git version 0.99.7a'),
36 ('insufficient', b'git version 1.0rc1'),
37 ('insufficient', b'git version 1.0.1'),
38 ('insufficient', b'git version 1.4.2.1'),
39 ('insufficient', b'git version 1.5.5'),
40 ('insufficient', b'git version 1.5.6-rc0'),
41 ('suitable', b'git version 1.5.6'),
42 ('suitable', b'git version 1.5.6.1'),
43 ('suitable', b'git version 2.14.0-rc0'),
44 ('suitable', b'git version 2.14.0 (something ...)'),
45 ('suitable', b'git version 111.222.333.444-rc555'),
46 ('unrecognized', b'huh?')):
47 assert expected == git.is_suitable_git(ver_str=ver)
49 if expected == 'insufficient':
50 with pytest.raises(SystemExit):
51 git.require_suitable_git(ver)
52 elif expected == 'suitable':
53 git.require_suitable_git(ver_str=ver)
54 elif expected == 'unrecognized':
55 with pytest.raises(git.GitError):
56 git.require_suitable_git(ver)
62 environ[b'BUP_GIT_VERSION_IS_FINE'] = b'true'
63 git.require_suitable_git(ver_str=ver)
65 del environ[b'BUP_GIT_VERSION_IS_FINE']
75 assert git.mangle_name(b'a', adir2, adir) == b'a'
76 assert git.mangle_name(b'.bup', adir2, adir) == b'.bup.bupl'
77 assert git.mangle_name(b'a.bupa', adir2, adir) == b'a.bupa.bupl'
78 WVPASSEQ(git.mangle_name(b'b.bup', alink, alink), b'b.bup.bupl')
79 WVPASSEQ(git.mangle_name(b'b.bu', alink, alink), b'b.bu')
80 WVPASSEQ(git.mangle_name(b'f', afile, afile2), b'f')
81 WVPASSEQ(git.mangle_name(b'f.bup', afile, afile2), b'f.bup.bupl')
82 WVPASSEQ(git.mangle_name(b'f.bup', afile, adir), b'f.bup.bup')
83 WVPASSEQ(git.mangle_name(b'f', afile, adir), b'f.bup')
85 WVPASSEQ(git.demangle_name(b'f.bup', afile), (b'f', git.BUP_CHUNKED))
86 WVPASSEQ(git.demangle_name(b'f.bupl', afile), (b'f', git.BUP_NORMAL))
87 WVPASSEQ(git.demangle_name(b'f.bup.bupl', afile), (b'f.bup', git.BUP_NORMAL))
89 WVPASSEQ(git.demangle_name(b'.bupm', afile), (b'', git.BUP_NORMAL))
90 WVPASSEQ(git.demangle_name(b'.bupm', adir), (b'', git.BUP_CHUNKED))
92 # for safety, we ignore .bup? suffixes we don't recognize. Future
93 # versions might implement a .bup[a-z] extension as something other
95 WVPASSEQ(git.demangle_name(b'f.bupa', afile), (b'f.bupa', git.BUP_NORMAL))
100 packb = b''.join(git._encode_packobj(b'blob', s))
101 packt = b''.join(git._encode_packobj(b'tree', s))
102 packc = b''.join(git._encode_packobj(b'commit', s))
103 packlb = b''.join(git._encode_packobj(b'blob', s * 200))
104 WVPASSEQ(git._decode_packobj(packb), (b'blob', s))
105 WVPASSEQ(git._decode_packobj(packt), (b'tree', s))
106 WVPASSEQ(git._decode_packobj(packc), (b'commit', s))
107 WVPASSEQ(git._decode_packobj(packlb), (b'blob', s * 200))
109 return b''.join(git._encode_packobj(b'blob', s, compression_level=n))
110 WVEXCEPT(ValueError, encode_pobj, -1)
111 WVEXCEPT(ValueError, encode_pobj, 10)
112 WVEXCEPT(ValueError, encode_pobj, b'x')
115 def test_packs(tmpdir):
116 environ[b'BUP_DIR'] = bupdir = tmpdir + b'/bup'
117 git.init_repo(bupdir)
120 with git.PackWriter() as w:
121 w.new_blob(os.urandom(100))
122 w.new_blob(os.urandom(100))
125 with git.PackWriter() as w:
128 for i in range(nobj):
129 hashes.append(w.new_blob(b'%d' % i))
131 nameprefix = w.close()
132 print(repr(nameprefix))
133 WVPASS(os.path.exists(nameprefix + b'.pack'))
134 WVPASS(os.path.exists(nameprefix + b'.idx'))
136 with git.open_idx(nameprefix + b'.idx') as r:
137 print(repr(r.fanout))
139 for i in range(nobj):
140 WVPASS(r.find_offset(hashes[i]) > 0)
141 WVPASS(r.exists(hashes[99]))
142 WVFAIL(r.exists(b'\0'*20))
145 for h in sorted(hashes):
146 WVPASSEQ(hexlify(next(pi)), hexlify(h))
148 WVFAIL(r.find_offset(b'\0'*20))
150 with git.PackIdxList(bupdir + b'/objects/pack') as r:
151 WVPASS(r.exists(hashes[5]))
152 WVPASS(r.exists(hashes[6]))
153 WVFAIL(r.exists(b'\0'*20))
156 def test_pack_name_lookup(tmpdir):
157 environ[b'BUP_DIR'] = bupdir = tmpdir + b'/bup'
158 git.init_repo(bupdir)
160 packdir = git.repo(b'objects/pack')
165 for start in range(0,28,2):
166 with git.PackWriter() as w:
167 for i in range(start, start+2):
168 hashes.append(w.new_blob(b'%d' % i))
170 idxnames.append(os.path.basename(w.close() + b'.idx'))
172 with git.PackIdxList(packdir) as r:
173 WVPASSEQ(len(r.packs), 2)
174 for e,idxname in enumerate(idxnames):
175 for i in range(e*2, (e+1)*2):
176 WVPASSEQ(idxname, r.exists(hashes[i], want_source=True))
179 def test_long_index(tmpdir):
180 environ[b'BUP_DIR'] = bupdir = tmpdir + b'/bup'
181 git.init_repo(bupdir)
182 idx = git.PackIdxV2Writer()
183 obj_bin = struct.pack('!IIIII',
184 0x00112233, 0x44556677, 0x88990011, 0x22334455, 0x66778899)
185 obj2_bin = struct.pack('!IIIII',
186 0x11223344, 0x55667788, 0x99001122, 0x33445566, 0x77889900)
187 obj3_bin = struct.pack('!IIIII',
188 0x22334455, 0x66778899, 0x00112233, 0x44556677, 0x88990011)
189 pack_bin = struct.pack('!IIIII',
190 0x99887766, 0x55443322, 0x11009988, 0x77665544, 0x33221100)
191 idx.add(obj_bin, 1, 0xfffffffff)
192 idx.add(obj2_bin, 2, 0xffffffffff)
193 idx.add(obj3_bin, 3, 0xff)
194 name = tmpdir + b'/tmp.idx'
195 r = idx.write(name, pack_bin)
196 with git.PackIdxV2(name, open(name, 'rb')) as i:
197 WVPASSEQ(i.find_offset(obj_bin), 0xfffffffff)
198 WVPASSEQ(i.find_offset(obj2_bin), 0xffffffffff)
199 WVPASSEQ(i.find_offset(obj3_bin), 0xff)
202 def test_check_repo_or_die(tmpdir):
203 environ[b'BUP_DIR'] = bupdir = tmpdir + b'/bup'
204 orig_cwd = os.getcwd()
207 git.init_repo(bupdir)
208 git.check_repo_or_die()
209 # if we reach this point the call above passed
210 WVPASS('check_repo_or_die')
212 os.rename(bupdir + b'/objects/pack',
213 bupdir + b'/objects/pack.tmp')
214 open(bupdir + b'/objects/pack', 'w').close()
216 git.check_repo_or_die()
217 except SystemExit as e:
221 os.unlink(bupdir + b'/objects/pack')
222 os.rename(bupdir + b'/objects/pack.tmp',
223 bupdir + b'/objects/pack')
226 git.check_repo_or_die(b'nonexistantbup.tmp')
227 except SystemExit as e:
235 def test_commit_parsing(tmpdir):
236 def restore_env_var(name, val):
242 def showval(commit, val):
243 return readpipe([b'git', b'show', b'-s',
244 b'--pretty=format:%s' % val, commit]).strip()
246 orig_cwd = os.getcwd()
247 workdir = tmpdir + b'/work'
248 repodir = workdir + b'/.git'
249 orig_author_name = environ.get(b'GIT_AUTHOR_NAME')
250 orig_author_email = environ.get(b'GIT_AUTHOR_EMAIL')
251 orig_committer_name = environ.get(b'GIT_COMMITTER_NAME')
252 orig_committer_email = environ.get(b'GIT_COMMITTER_EMAIL')
253 environ[b'GIT_AUTHOR_NAME'] = b'bup test'
254 environ[b'GIT_COMMITTER_NAME'] = environ[b'GIT_AUTHOR_NAME']
255 environ[b'GIT_AUTHOR_EMAIL'] = b'bup@a425bc70a02811e49bdf73ee56450e6f'
256 environ[b'GIT_COMMITTER_EMAIL'] = environ[b'GIT_AUTHOR_EMAIL']
258 environ[b'GIT_DIR'] = environ[b'BUP_DIR'] = repodir
259 readpipe([b'git', b'init', workdir])
260 exc(b'git', b'symbolic-ref', b'HEAD', b'refs/heads/main')
261 git.check_repo_or_die(repodir)
263 with open('foo', 'w') as f:
265 readpipe([b'git', b'add', b'.'])
266 readpipe([b'git', b'commit', b'-am', b'Do something',
267 b'--author', b'Someone <someone@somewhere>',
268 b'--date', b'Sat Oct 3 19:48:49 2009 -0400'])
269 commit = readpipe([b'git', b'show-ref', b'-s', b'main']).strip()
270 parents = showval(commit, b'%P')
271 tree = showval(commit, b'%T')
272 cname = showval(commit, b'%cn')
273 cmail = showval(commit, b'%ce')
274 cdate = showval(commit, b'%ct')
275 coffs = showval(commit, b'%ci')
277 coff = (int(coffs[-4:-2]) * 60 * 60) + (int(coffs[-2:]) * 60)
278 if bytes_from_byte(coffs[-5]) == b'-':
280 commit_items = git.get_commit_items(commit, git.cp())
281 WVPASSEQ(commit_items.parents, [])
282 WVPASSEQ(commit_items.tree, tree)
283 WVPASSEQ(commit_items.author_name, b'Someone')
284 WVPASSEQ(commit_items.author_mail, b'someone@somewhere')
285 WVPASSEQ(commit_items.author_sec, 1254613729)
286 WVPASSEQ(commit_items.author_offset, -(4 * 60 * 60))
287 WVPASSEQ(commit_items.committer_name, cname)
288 WVPASSEQ(commit_items.committer_mail, cmail)
289 WVPASSEQ(commit_items.committer_sec, int(cdate))
290 WVPASSEQ(commit_items.committer_offset, coff)
291 WVPASSEQ(commit_items.message, b'Do something\n')
292 with open(b'bar', 'wb') as f:
294 readpipe([b'git', b'add', '.'])
295 readpipe([b'git', b'commit', b'-am', b'Do something else'])
296 child = readpipe([b'git', b'show-ref', b'-s', b'main']).strip()
297 parents = showval(child, b'%P')
298 commit_items = git.get_commit_items(child, git.cp())
299 WVPASSEQ(commit_items.parents, [commit])
302 restore_env_var(b'GIT_AUTHOR_NAME', orig_author_name)
303 restore_env_var(b'GIT_AUTHOR_EMAIL', orig_author_email)
304 restore_env_var(b'GIT_COMMITTER_NAME', orig_committer_name)
305 restore_env_var(b'GIT_COMMITTER_EMAIL', orig_committer_email)
308 gpgsig_example_1 = b'''tree 3fab08ade2fbbda60bef180bb8e0cc5724d6bd4d
309 parent 36db87b46a95ca5079f43dfe9b72220acab7c731
310 author Rob Browning <rlb@defaultvalue.org> 1633397238 -0500
311 committer Rob Browning <rlb@defaultvalue.org> 1633397238 -0500
312 gpgsig -----BEGIN PGP SIGNATURE-----
315 -----END PGP SIGNATURE-----
317 Sample signed commit.
320 gpgsig_example_2 = b'''tree 3fab08ade2fbbda60bef180bb8e0cc5724d6bd4d
321 parent 36db87b46a95ca5079f43dfe9b72220acab7c731
322 author Rob Browning <rlb@defaultvalue.org> 1633397238 -0500
323 committer Rob Browning <rlb@defaultvalue.org> 1633397238 -0500
324 gpgsig -----BEGIN PGP SIGNATURE-----
327 -----END PGP SIGNATURE-----
330 Sample signed commit.
333 def test_commit_gpgsig_parsing():
334 c = git.parse_commit(gpgsig_example_1)
336 assert c.gpgsig.startswith(b'-----BEGIN PGP SIGNATURE-----\n')
337 assert c.gpgsig.endswith(b'\n-----END PGP SIGNATURE-----\n')
338 c = git.parse_commit(gpgsig_example_2)
340 assert c.gpgsig.startswith(b'-----BEGIN PGP SIGNATURE-----')
341 assert c.gpgsig.endswith(b'\n-----END PGP SIGNATURE-----\n\n')
344 def test_new_commit(tmpdir):
345 environ[b'BUP_DIR'] = bupdir = tmpdir + b'/bup'
346 git.init_repo(bupdir)
349 with git.PackWriter() as w:
350 tree = os.urandom(20)
351 parent = os.urandom(20)
352 author_name = b'Author'
353 author_mail = b'author@somewhere'
354 adate_sec = 1439657836
355 cdate_sec = adate_sec + 1
356 committer_name = b'Committer'
357 committer_mail = b'committer@somewhere'
358 adate_tz_sec = cdate_tz_sec = None
359 commit = w.new_commit(tree, parent,
360 b'%s <%s>' % (author_name, author_mail),
361 adate_sec, adate_tz_sec,
362 b'%s <%s>' % (committer_name, committer_mail),
363 cdate_sec, cdate_tz_sec,
364 b'There is a small mailbox here')
365 adate_tz_sec = -60 * 60
366 cdate_tz_sec = 120 * 60
367 commit_off = w.new_commit(tree, parent,
368 b'%s <%s>' % (author_name, author_mail),
369 adate_sec, adate_tz_sec,
370 b'%s <%s>' % (committer_name, committer_mail),
371 cdate_sec, cdate_tz_sec,
372 b'There is a small mailbox here')
374 commit_items = git.get_commit_items(hexlify(commit), git.cp())
375 local_author_offset = localtime(adate_sec).tm_gmtoff
376 local_committer_offset = localtime(cdate_sec).tm_gmtoff
377 WVPASSEQ(tree, unhexlify(commit_items.tree))
378 WVPASSEQ(1, len(commit_items.parents))
379 WVPASSEQ(parent, unhexlify(commit_items.parents[0]))
380 WVPASSEQ(author_name, commit_items.author_name)
381 WVPASSEQ(author_mail, commit_items.author_mail)
382 WVPASSEQ(adate_sec, commit_items.author_sec)
383 WVPASSEQ(local_author_offset, commit_items.author_offset)
384 WVPASSEQ(committer_name, commit_items.committer_name)
385 WVPASSEQ(committer_mail, commit_items.committer_mail)
386 WVPASSEQ(cdate_sec, commit_items.committer_sec)
387 WVPASSEQ(local_committer_offset, commit_items.committer_offset)
389 commit_items = git.get_commit_items(hexlify(commit_off), git.cp())
390 WVPASSEQ(tree, unhexlify(commit_items.tree))
391 WVPASSEQ(1, len(commit_items.parents))
392 WVPASSEQ(parent, unhexlify(commit_items.parents[0]))
393 WVPASSEQ(author_name, commit_items.author_name)
394 WVPASSEQ(author_mail, commit_items.author_mail)
395 WVPASSEQ(adate_sec, commit_items.author_sec)
396 WVPASSEQ(adate_tz_sec, commit_items.author_offset)
397 WVPASSEQ(committer_name, commit_items.committer_name)
398 WVPASSEQ(committer_mail, commit_items.committer_mail)
399 WVPASSEQ(cdate_sec, commit_items.committer_sec)
400 WVPASSEQ(cdate_tz_sec, commit_items.committer_offset)
403 def test_list_refs(tmpdir):
404 environ[b'BUP_DIR'] = bupdir = tmpdir + b'/bup'
405 src = tmpdir + b'/src'
407 with open(src + b'/1', 'wb+') as f:
408 f.write(b'something\n')
409 with open(src + b'/2', 'wb+') as f:
410 f.write(b'something else\n')
411 git.init_repo(bupdir)
412 emptyset = frozenset()
413 WVPASSEQ(frozenset(git.list_refs()), emptyset)
414 WVPASSEQ(frozenset(git.list_refs(limit_to_tags=True)), emptyset)
415 WVPASSEQ(frozenset(git.list_refs(limit_to_heads=True)), emptyset)
416 exc(bup_exe, b'index', src)
417 exc(bup_exe, b'save', b'-n', b'src', b'--strip', src)
418 src_hash = exo(b'git', b'--git-dir', bupdir,
419 b'rev-parse', b'src').strip().split(b'\n')
420 assert(len(src_hash) == 1)
421 src_hash = unhexlify(src_hash[0])
422 tree_hash = unhexlify(exo(b'git', b'--git-dir', bupdir,
424 b'src:').strip().split(b'\n')[0])
425 blob_hash = unhexlify(exo(b'git', b'--git-dir', bupdir,
427 b'src:1').strip().split(b'\n')[0])
428 WVPASSEQ(frozenset(git.list_refs()),
429 frozenset([(b'refs/heads/src', src_hash)]))
430 WVPASSEQ(frozenset(git.list_refs(limit_to_tags=True)), emptyset)
431 WVPASSEQ(frozenset(git.list_refs(limit_to_heads=True)),
432 frozenset([(b'refs/heads/src', src_hash)]))
433 exc(b'git', b'--git-dir', bupdir, b'tag', b'commit-tag', b'src')
434 WVPASSEQ(frozenset(git.list_refs()),
435 frozenset([(b'refs/heads/src', src_hash),
436 (b'refs/tags/commit-tag', src_hash)]))
437 WVPASSEQ(frozenset(git.list_refs(limit_to_tags=True)),
438 frozenset([(b'refs/tags/commit-tag', src_hash)]))
439 WVPASSEQ(frozenset(git.list_refs(limit_to_heads=True)),
440 frozenset([(b'refs/heads/src', src_hash)]))
441 exc(b'git', b'--git-dir', bupdir, b'tag', b'tree-tag', b'src:')
442 exc(b'git', b'--git-dir', bupdir, b'tag', b'blob-tag', b'src:1')
443 os.unlink(bupdir + b'/refs/heads/src')
444 expected_tags = frozenset([(b'refs/tags/commit-tag', src_hash),
445 (b'refs/tags/tree-tag', tree_hash),
446 (b'refs/tags/blob-tag', blob_hash)])
447 WVPASSEQ(frozenset(git.list_refs()), expected_tags)
448 WVPASSEQ(frozenset(git.list_refs(limit_to_heads=True)), frozenset([]))
449 WVPASSEQ(frozenset(git.list_refs(limit_to_tags=True)), expected_tags)
452 def test_git_date_str():
453 WVPASSEQ(b'0 +0000', git._git_date_str(0, 0))
454 WVPASSEQ(b'0 -0130', git._git_date_str(0, -90 * 60))
455 WVPASSEQ(b'0 +0130', git._git_date_str(0, 90 * 60))
458 def test_cat_pipe(tmpdir):
459 environ[b'BUP_DIR'] = bupdir = tmpdir + b'/bup'
460 src = tmpdir + b'/src'
462 with open(src + b'/1', 'wb+') as f:
463 f.write(b'something\n')
464 with open(src + b'/2', 'wb+') as f:
465 f.write(b'something else\n')
466 git.init_repo(bupdir)
467 exc(bup_exe, b'index', src)
468 oidx = exo(bup_exe, b'save', b'-cn', b'src', b'--strip',
470 typ = exo(b'git', b'--git-dir', bupdir,
471 b'cat-file', b'-t', b'src').strip()
472 size = int(exo(b'git', b'--git-dir', bupdir,
473 b'cat-file', b'-s', b'src'))
474 it = git.cp().get(b'src')
478 WVPASSEQ((oidx, typ, size), get_info)
480 def _create_idx(d, i):
481 idx = git.PackIdxV2Writer()
482 # add 255 vaguely reasonable entries
484 idx.add(struct.pack('18xBB', i, s), s, 100 * s)
485 packbin = struct.pack('B19x', i)
486 packname = os.path.join(d, b'pack-%s.idx' % hexlify(packbin))
487 idx.write(packname, packbin)
489 def test_midx_close(tmpdir):
490 fddir = b'/proc/self/fd'
494 # not supported, not Linux, I guess
498 for fd in os.listdir(fddir):
500 yield os.readlink(os.path.join(fddir, fd))
504 def force_midx(objdir):
505 args = [path.exe(), b'midx', b'--auto', b'--dir', objdir]
508 environ[b'BUP_DIR'] = bupdir = tmpdir + b'/bup'
509 git.init_repo(bupdir)
510 # create a few dummy idxes
512 _create_idx(tmpdir, i)
513 git.auto_midx(tmpdir)
514 with git.PackIdxList(tmpdir) as l:
515 # this doesn't exist (yet)
516 WVPASSEQ(None, l.exists(struct.pack('18xBB', 10, 0)))
517 for i in range(10, 15):
518 _create_idx(tmpdir, i)
519 # delete the midx ...
520 # TODO: why do we need to? git.auto_midx() below doesn't?!
521 for fn in os.listdir(tmpdir):
522 if fn.endswith(b'.midx'):
523 os.unlink(os.path.join(tmpdir, fn))
525 git.auto_midx(tmpdir)
526 # check it still doesn't exist - we haven't refreshed
527 WVPASSEQ(None, l.exists(struct.pack('18xBB', 10, 0)))
528 # check that we still have the midx open, this really
529 # just checks more for the kernel API ('deleted' string)
530 for fn in openfiles():
531 if not b'midx-' in fn:
533 WVPASSEQ(True, b'deleted' in fn)
534 # refresh the PackIdxList
536 # and check that an object in pack 10 exists now
537 WVPASSEQ(True, l.exists(struct.pack('18xBB', 10, 0)))
538 for fn in openfiles():
539 if not b'midx-' in fn:
541 # check that we don't have it open anymore
542 WVPASSEQ(False, b'deleted' in fn)
545 cfg_file = os.path.join(os.path.dirname(__file__), 'sample.conf')
546 no_such_file = os.path.join(os.path.dirname(__file__), 'nosuch.conf')
547 git_config_get = partial(git.git_config_get, cfg_file=cfg_file)
548 WVPASSEQ(git_config_get(b'bup.foo'), b'bar')
549 WVPASSEQ(git_config_get(b'bup.bup'), b'is great')
550 WVPASSEQ(git_config_get(b'bup.end'), b'end')
551 WVPASSEQ(git_config_get(b'bup.comments'), None)
552 WVPASSEQ(git_config_get(b'bup.;comments'), None)
553 WVPASSEQ(git_config_get(b'bup.and'), None)
554 WVPASSEQ(git_config_get(b'bup.#and'), None)
556 WVPASSEQ(git.git_config_get(b'bup.foo', cfg_file=no_such_file), None)
558 WVEXCEPT(git.GitError, git_config_get, b'bup.isbad', opttype='bool')
559 WVEXCEPT(git.GitError, git_config_get, b'bup.isbad', opttype='int')
560 WVPASSEQ(git_config_get(b'bup.isbad'), b'ok')
561 WVPASSEQ(True, git_config_get(b'bup.istrue1', opttype='bool'))
562 WVPASSEQ(True, git_config_get(b'bup.istrue2', opttype='bool'))
563 WVPASSEQ(True, git_config_get(b'bup.istrue3', opttype='bool'))
564 WVPASSEQ(False, git_config_get(b'bup.isfalse1', opttype='bool'))
565 WVPASSEQ(False, git_config_get(b'bup.isfalse2', opttype='bool'))
566 WVPASSEQ(None, git_config_get(b'bup.nosuchkey', opttype='bool'))
567 WVPASSEQ(1, git_config_get(b'bup.istrue1', opttype='int'))
568 WVPASSEQ(2, git_config_get(b'bup.istrue2', opttype='int'))
569 WVPASSEQ(0, git_config_get(b'bup.isfalse2', opttype='int'))
570 WVPASSEQ(0x777, git_config_get(b'bup.hex', opttype='int'))