Signed-off-by: Rob Browning <
r...@defaultvalue.org>
---
lib/bup/commit.py | 117 ++++++++++++++++++++++++++++++++++++
lib/bup/git.py | 116 +----------------------------------
test/int/test_commit.py | 130 ++++++++++++++++++++++++++++++++++++++++
test/int/test_git.py | 114 -----------------------------------
4 files changed, 250 insertions(+), 227 deletions(-)
create mode 100644 lib/bup/commit.py
create mode 100644 test/int/test_commit.py
diff --git a/lib/bup/commit.py b/lib/bup/commit.py
new file mode 100644
index 00000000..5d863fd4
--- /dev/null
+++ b/lib/bup/commit.py
@@ -0,0 +1,117 @@
+
+from binascii import hexlify
+from collections import namedtuple
+import re
+
+from bup.helpers import utc_offset_str
+
+
+def parse_tz_offset(s):
+ """UTC offset in seconds."""
+ tz_off = (int(s[1:3]) * 60 * 60) + (int(s[3:5]) * 60)
+ if s[0] == b'-'[0]:
+ return - tz_off
+ return tz_off
+
+
+def parse_commit_gpgsig(sig):
+ """Return the original signature bytes.
+
+ i.e. with the "gpgsig " header and the leading space character on
+ each continuation line removed.
+
+ """
+ if not sig:
+ return None
+ assert sig.startswith(b'gpgsig ')
+ sig = sig[7:]
+ return sig.replace(b'\n ', b'\n')
+
+# FIXME: derived from
http://git.rsbx.net/Documents/Git_Data_Formats.txt
+# Make sure that's authoritative.
+
+# See also
+#
https://github.com/git/git/blob/master/Documentation/technical/signature-format.txt
+# The continuation lines have only one leading space.
+
+_start_end_char = br'[^ .,:;<>"\'\0\n]'
+_content_char = br'[^\0\n<>]'
+_safe_str_rx = br'(?:%s{1,2}|(?:%s%s*%s))' \
+ % (_start_end_char,
+ _start_end_char, _content_char, _start_end_char)
+_tz_rx = br'[-+]\d\d[0-5]\d'
+_parent_rx = br'(?:parent [abcdefABCDEF0123456789]{40}\n)'
+# Assumes every following line starting with a space is part of the
+# mergetag. Is there a formal commit blob spec?
+_mergetag_rx = br'(?:\nmergetag object [abcdefABCDEF0123456789]{40}(?:\n [^\0\n]*)*)'
+_commit_rx = re.compile(br'''tree (?P<tree>[abcdefABCDEF0123456789]{40})
+(?P<parents>%s*)author (?P<author_name>%s) <(?P<author_mail>%s)> (?P<asec>\d+) (?P<atz>%s)
+committer (?P<committer_name>%s) <(?P<committer_mail>%s)> (?P<csec>\d+) (?P<ctz>%s)(?P<mergetag>%s?)
+(?P<gpgsig>gpgsig .*\n(?: .*\n)*)?
+(?P<message>(?:.|\n)*)''' % (_parent_rx,
+ _safe_str_rx, _safe_str_rx, _tz_rx,
+ _safe_str_rx, _safe_str_rx, _tz_rx,
+ _mergetag_rx))
+_parent_hash_rx = re.compile(br'\s*parent ([abcdefABCDEF0123456789]{40})\s*')
+
+# Note that the author_sec and committer_sec values are (UTC) epoch
+# seconds, and for now the mergetag is not included.
+CommitInfo = namedtuple('CommitInfo', ['tree', 'parents',
+ 'author_name', 'author_mail',
+ 'author_sec', 'author_offset',
+ 'committer_name', 'committer_mail',
+ 'committer_sec', 'committer_offset',
+ 'gpgsig',
+ 'message'])
+
+def parse_commit(content):
+ commit_match = re.match(_commit_rx, content)
+ if not commit_match:
+ raise Exception('cannot parse commit %r' % content)
+ matches = commit_match.groupdict()
+ return CommitInfo(tree=matches['tree'],
+ parents=re.findall(_parent_hash_rx, matches['parents']),
+ author_name=matches['author_name'],
+ author_mail=matches['author_mail'],
+ author_sec=int(matches['asec']),
+ author_offset=parse_tz_offset(matches['atz']),
+ committer_name=matches['committer_name'],
+ committer_mail=matches['committer_mail'],
+ committer_sec=int(matches['csec']),
+ committer_offset=parse_tz_offset(matches['ctz']),
+ gpgsig=parse_commit_gpgsig(matches['gpgsig']),
+ message=matches['message'])
+
+
+def _local_git_date_str(epoch_sec):
+ return b'%d %s' % (epoch_sec, utc_offset_str(epoch_sec))
+
+def _git_date_str(epoch_sec, tz_offset_sec):
+ offs = tz_offset_sec // 60
+ return b'%d %s%02d%02d' \
+ % (epoch_sec,
+ b'+' if offs >= 0 else b'-',
+ abs(offs) // 60,
+ abs(offs) % 60)
+
+
+def create_commit_blob(tree, parent,
+ author, adate_sec, adate_tz,
+ committer, cdate_sec, cdate_tz,
+ msg):
+ if adate_tz is not None:
+ adate_str = _git_date_str(adate_sec, adate_tz)
+ else:
+ adate_str = _local_git_date_str(adate_sec)
+ if cdate_tz is not None:
+ cdate_str = _git_date_str(cdate_sec, cdate_tz)
+ else:
+ cdate_str = _local_git_date_str(cdate_sec)
+ l = []
+ if tree: l.append(b'tree %s' % hexlify(tree))
+ if parent: l.append(b'parent %s' % hexlify(parent))
+ if author: l.append(b'author %s %s' % (author, adate_str))
+ if committer: l.append(b'committer %s %s' % (committer, cdate_str))
+ l.append(b'')
+ l.append(msg)
+ return b'\n'.join(l)
diff --git a/lib/bup/git.py b/lib/bup/git.py
index b734b190..0fb11da4 100644
--- a/lib/bup/git.py
+++ b/lib/bup/git.py
@@ -6,7 +6,6 @@ interact with the Git data structures.
import os, sys, zlib, subprocess, struct, stat, re, glob
from array import array
from binascii import hexlify, unhexlify
-from collections import namedtuple
from contextlib import ExitStack
from dataclasses import replace
from itertools import islice
@@ -16,6 +15,7 @@ from sys import stderr
from typing import Optional, Union
from bup import _helpers, hashsplit, path, midx, bloom, xstat
+from bup.commit import create_commit_blob, parse_commit
from bup.compat import dataclass, environ
from
bup.io import path_msg
from bup.helpers import (EXIT_FAILURE,
@@ -33,8 +33,7 @@ from bup.helpers import (EXIT_FAILURE,
progress, qprogress, stat_if_exists,
quote,
temp_dir,
- unlink,
- utc_offset_str)
+ unlink)
from bup.midx import open_midx
@@ -103,103 +102,16 @@ def git_config_get(path, option, *, opttype=None):
raise GitError('%r returned %d' % (cmd, rc))
-def parse_tz_offset(s):
- """UTC offset in seconds."""
- tz_off = (int(s[1:3]) * 60 * 60) + (int(s[3:5]) * 60)
- if s[0] == b'-'[0]:
- return - tz_off
- return tz_off
-
-def parse_commit_gpgsig(sig):
- """Return the original signature bytes.
-
- i.e. with the "gpgsig " header and the leading space character on
- each continuation line removed.
-
- """
- if not sig:
- return None
- assert sig.startswith(b'gpgsig ')
- sig = sig[7:]
- return sig.replace(b'\n ', b'\n')
-
-# FIXME: derived from
http://git.rsbx.net/Documents/Git_Data_Formats.txt
-# Make sure that's authoritative.
-
-# See also
-#
https://github.com/git/git/blob/master/Documentation/technical/signature-format.txt
-# The continuation lines have only one leading space.
-
-_start_end_char = br'[^ .,:;<>"\'\0\n]'
-_content_char = br'[^\0\n<>]'
-_safe_str_rx = br'(?:%s{1,2}|(?:%s%s*%s))' \
- % (_start_end_char,
- _start_end_char, _content_char, _start_end_char)
-_tz_rx = br'[-+]\d\d[0-5]\d'
-_parent_rx = br'(?:parent [abcdefABCDEF0123456789]{40}\n)'
-# Assumes every following line starting with a space is part of the
-# mergetag. Is there a formal commit blob spec?
-_mergetag_rx = br'(?:\nmergetag object [abcdefABCDEF0123456789]{40}(?:\n [^\0\n]*)*)'
-_commit_rx = re.compile(br'''tree (?P<tree>[abcdefABCDEF0123456789]{40})
-(?P<parents>%s*)author (?P<author_name>%s) <(?P<author_mail>%s)> (?P<asec>\d+) (?P<atz>%s)
-committer (?P<committer_name>%s) <(?P<committer_mail>%s)> (?P<csec>\d+) (?P<ctz>%s)(?P<mergetag>%s?)
-(?P<gpgsig>gpgsig .*\n(?: .*\n)*)?
-(?P<message>(?:.|\n)*)''' % (_parent_rx,
- _safe_str_rx, _safe_str_rx, _tz_rx,
- _safe_str_rx, _safe_str_rx, _tz_rx,
- _mergetag_rx))
-_parent_hash_rx = re.compile(br'\s*parent ([abcdefABCDEF0123456789]{40})\s*')
-
-# Note that the author_sec and committer_sec values are (UTC) epoch
-# seconds, and for now the mergetag is not included.
-CommitInfo = namedtuple('CommitInfo', ['tree', 'parents',
- 'author_name', 'author_mail',
- 'author_sec', 'author_offset',
- 'committer_name', 'committer_mail',
- 'committer_sec', 'committer_offset',
- 'gpgsig',
- 'message'])
-
-def parse_commit(content):
- commit_match = re.match(_commit_rx, content)
- if not commit_match:
- raise Exception('cannot parse commit %r' % content)
- matches = commit_match.groupdict()
- return CommitInfo(tree=matches['tree'],
- parents=re.findall(_parent_hash_rx, matches['parents']),
- author_name=matches['author_name'],
- author_mail=matches['author_mail'],
- author_sec=int(matches['asec']),
- author_offset=parse_tz_offset(matches['atz']),
- committer_name=matches['committer_name'],
- committer_mail=matches['committer_mail'],
- committer_sec=int(matches['csec']),
- committer_offset=parse_tz_offset(matches['ctz']),
- gpgsig=parse_commit_gpgsig(matches['gpgsig']),
- message=matches['message'])
-
-
def get_cat_data(cat_iterator, expected_type):
_, kind, _ = next(cat_iterator)
if kind != expected_type:
raise Exception('expected %r, saw %r' % (expected_type, kind))
return b''.join(cat_iterator)
+
def get_commit_items(id, cp):
return parse_commit(get_cat_data(cp.get(id), b'commit'))
-def _local_git_date_str(epoch_sec):
- return b'%d %s' % (epoch_sec, utc_offset_str(epoch_sec))
-
-
-def _git_date_str(epoch_sec, tz_offset_sec):
- offs = tz_offset_sec // 60
- return b'%d %s%02d%02d' \
- % (epoch_sec,
- b'+' if offs >= 0 else b'-',
- abs(offs) // 60,
- abs(offs) % 60)
-
def repo(sub = b'', repo_dir=None):
"""Get the path to the git repository or one of its subdirectories."""
@@ -857,28 +769,6 @@ def idxmerge(idxlist, final_progress=True):
return merge_iter(idxlist, 10024, pfunc, pfinal)
-def create_commit_blob(tree, parent,
- author, adate_sec, adate_tz,
- committer, cdate_sec, cdate_tz,
- msg):
- if adate_tz is not None:
- adate_str = _git_date_str(adate_sec, adate_tz)
- else:
- adate_str = _local_git_date_str(adate_sec)
- if cdate_tz is not None:
- cdate_str = _git_date_str(cdate_sec, cdate_tz)
- else:
- cdate_str = _local_git_date_str(cdate_sec)
- l = []
- if tree: l.append(b'tree %s' % hexlify(tree))
- if parent: l.append(b'parent %s' % hexlify(parent))
- if author: l.append(b'author %s %s' % (author, adate_str))
- if committer: l.append(b'committer %s %s' % (committer, cdate_str))
- l.append(b'')
- l.append(msg)
- return b'\n'.join(l)
-
-
# del/exit/close/etc. wrt parent/child?
class LocalPackStore():
diff --git a/test/int/test_commit.py b/test/int/test_commit.py
new file mode 100644
index 00000000..42081c9e
--- /dev/null
+++ b/test/int/test_commit.py
@@ -0,0 +1,130 @@
+
+from os import environb as environ
+from subprocess import check_call
+import sys
+
+from wvpytest import *
+
+from bup import git
+from bup.commit import _git_date_str, parse_commit
+from bup.helpers import readpipe
+
+
+def exc(*cmd):
+ print(repr(cmd), file=sys.stderr)
+ check_call(cmd)
+
+
+def test_commit_parsing(tmpdir):
+ def restore_env_var(name, val):
+ if val is None:
+ del environ[name]
+ else:
+ environ[name] = val
+
+ def showval(commit, val):
+ return readpipe([b'git', b'show', b'-s',
+ b'--pretty=format:%s' % val, commit]).strip()
+
+ orig_cwd = os.getcwd()
+ workdir = tmpdir + b'/work'
+ repodir = workdir + b'/.git'
+ orig_author_name = environ.get(b'GIT_AUTHOR_NAME')
+ orig_author_email = environ.get(b'GIT_AUTHOR_EMAIL')
+ orig_committer_name = environ.get(b'GIT_COMMITTER_NAME')
+ orig_committer_email = environ.get(b'GIT_COMMITTER_EMAIL')
+ environ[b'GIT_AUTHOR_NAME'] = b'bup test'
+ environ[b'GIT_COMMITTER_NAME'] = environ[b'GIT_AUTHOR_NAME']
+ environ[b'GIT_AUTHOR_EMAIL'] = b'bup@a425bc70a02811e49bdf73ee56450e6f'
+ environ[b'GIT_COMMITTER_EMAIL'] = environ[b'GIT_AUTHOR_EMAIL']
+ try:
+ environ[b'GIT_DIR'] = environ[b'BUP_DIR'] = repodir
+ readpipe([b'git', b'init', workdir])
+ exc(b'git', b'symbolic-ref', b'HEAD', b'refs/heads/main')
+ git.check_repo_or_die(repodir)
+ os.chdir(workdir)
+ with open('foo', 'w') as f:
+ print('bar', file=f)
+ readpipe([b'git', b'add', b'.'])
+ readpipe([b'git', b'commit', b'-am', b'Do something',
+ b'--author', b'Someone <someone@somewhere>',
+ b'--date', b'Sat Oct 3 19:48:49 2009 -0400'])
+ commit = readpipe([b'git', b'show-ref', b'-s', b'main']).strip()
+ parents = showval(commit, b'%P')
+ tree = showval(commit, b'%T')
+ cname = showval(commit, b'%cn')
+ cmail = showval(commit, b'%ce')
+ cdate = showval(commit, b'%ct')
+ coffs = showval(commit, b'%ci')
+ coffs = coffs[-5:]
+ coff = (int(coffs[-4:-2]) * 60 * 60) + (int(coffs[-2:]) * 60)
+ if coffs[-5] == b'-'[0]:
+ coff = - coff
+ commit_items = git.get_commit_items(commit, git.cp())
+ WVPASSEQ(commit_items.parents, [])
+ WVPASSEQ(commit_items.tree, tree)
+ WVPASSEQ(commit_items.author_name, b'Someone')
+ WVPASSEQ(commit_items.author_mail, b'someone@somewhere')
+ WVPASSEQ(commit_items.author_sec, 1254613729)
+ WVPASSEQ(commit_items.author_offset, -(4 * 60 * 60))
+ WVPASSEQ(commit_items.committer_name, cname)
+ WVPASSEQ(commit_items.committer_mail, cmail)
+ WVPASSEQ(commit_items.committer_sec, int(cdate))
+ WVPASSEQ(commit_items.committer_offset, coff)
+ WVPASSEQ(commit_items.message, b'Do something\n')
+ with open(b'bar', 'wb') as f:
+ f.write(b'baz\n')
+ readpipe([b'git', b'add', '.'])
+ readpipe([b'git', b'commit', b'-am', b'Do something else'])
+ child = readpipe([b'git', b'show-ref', b'-s', b'main']).strip()
+ parents = showval(child, b'%P')
+ commit_items = git.get_commit_items(child, git.cp())
+ WVPASSEQ(commit_items.parents, [commit])
+ finally:
+ os.chdir(orig_cwd)
+ restore_env_var(b'GIT_AUTHOR_NAME', orig_author_name)
+ restore_env_var(b'GIT_AUTHOR_EMAIL', orig_author_email)
+ restore_env_var(b'GIT_COMMITTER_NAME', orig_committer_name)
+ restore_env_var(b'GIT_COMMITTER_EMAIL', orig_committer_email)
+
+
+gpgsig_example_1 = b'''tree 3fab08ade2fbbda60bef180bb8e0cc5724d6bd4d
+parent 36db87b46a95ca5079f43dfe9b72220acab7c731
+author Rob Browning <
r...@defaultvalue.org> 1633397238 -0500
+committer Rob Browning <
r...@defaultvalue.org> 1633397238 -0500
+gpgsig -----BEGIN PGP SIGNATURE-----
+
+ ...
+ -----END PGP SIGNATURE-----
+
+Sample signed commit.
+'''
+
+gpgsig_example_2 = b'''tree 3fab08ade2fbbda60bef180bb8e0cc5724d6bd4d
+parent 36db87b46a95ca5079f43dfe9b72220acab7c731
+author Rob Browning <
r...@defaultvalue.org> 1633397238 -0500
+committer Rob Browning <
r...@defaultvalue.org> 1633397238 -0500
+gpgsig -----BEGIN PGP SIGNATURE-----
+
+ ...
+ -----END PGP SIGNATURE-----
+
+
+Sample signed commit.
+'''
+
+def test_commit_gpgsig_parsing():
+ c = parse_commit(gpgsig_example_1)
+ assert c.gpgsig
+ assert c.gpgsig.startswith(b'-----BEGIN PGP SIGNATURE-----\n')
+ assert c.gpgsig.endswith(b'\n-----END PGP SIGNATURE-----\n')
+ c = git.parse_commit(gpgsig_example_2)
+ assert c.gpgsig
+ assert c.gpgsig.startswith(b'-----BEGIN PGP SIGNATURE-----')
+ assert c.gpgsig.endswith(b'\n-----END PGP SIGNATURE-----\n\n')
+
+
+def test_git_date_str():
+ WVPASSEQ(b'0 +0000', _git_date_str(0, 0))
+ WVPASSEQ(b'0 -0130', _git_date_str(0, -90 * 60))
+ WVPASSEQ(b'0 +0130', _git_date_str(0, 90 * 60))
diff --git a/test/int/test_git.py b/test/int/test_git.py
index a1385d13..83888621 100644
--- a/test/int/test_git.py
+++ b/test/int/test_git.py
@@ -278,114 +278,6 @@ def test_check_repo_or_die(tmpdir):
git.repodir = None
check_establish_default_repo_variant(tmpdir, git.check_repo_or_die, False)
-def test_commit_parsing(tmpdir):
- def restore_env_var(name, val):
- if val is None:
- del environ[name]
- else:
- environ[name] = val
-
- def showval(commit, val):
- return readpipe([b'git', b'show', b'-s',
- b'--pretty=format:%s' % val, commit]).strip()
-
- orig_cwd = os.getcwd()
- workdir = tmpdir + b'/work'
- repodir = workdir + b'/.git'
- orig_author_name = environ.get(b'GIT_AUTHOR_NAME')
- orig_author_email = environ.get(b'GIT_AUTHOR_EMAIL')
- orig_committer_name = environ.get(b'GIT_COMMITTER_NAME')
- orig_committer_email = environ.get(b'GIT_COMMITTER_EMAIL')
- environ[b'GIT_AUTHOR_NAME'] = b'bup test'
- environ[b'GIT_COMMITTER_NAME'] = environ[b'GIT_AUTHOR_NAME']
- environ[b'GIT_AUTHOR_EMAIL'] = b'bup@a425bc70a02811e49bdf73ee56450e6f'
- environ[b'GIT_COMMITTER_EMAIL'] = environ[b'GIT_AUTHOR_EMAIL']
- try:
- environ[b'GIT_DIR'] = environ[b'BUP_DIR'] = repodir
- readpipe([b'git', b'init', workdir])
- exc(b'git', b'symbolic-ref', b'HEAD', b'refs/heads/main')
- git.check_repo_or_die(repodir)
- os.chdir(workdir)
- with open('foo', 'w') as f:
- print('bar', file=f)
- readpipe([b'git', b'add', b'.'])
- readpipe([b'git', b'commit', b'-am', b'Do something',
- b'--author', b'Someone <someone@somewhere>',
- b'--date', b'Sat Oct 3 19:48:49 2009 -0400'])
- commit = readpipe([b'git', b'show-ref', b'-s', b'main']).strip()
- parents = showval(commit, b'%P')
- tree = showval(commit, b'%T')
- cname = showval(commit, b'%cn')
- cmail = showval(commit, b'%ce')
- cdate = showval(commit, b'%ct')
- coffs = showval(commit, b'%ci')
- coffs = coffs[-5:]
- coff = (int(coffs[-4:-2]) * 60 * 60) + (int(coffs[-2:]) * 60)
- if coffs[-5] == b'-'[0]:
- coff = - coff
- commit_items = git.get_commit_items(commit, git.cp())
- WVPASSEQ(commit_items.parents, [])
- WVPASSEQ(commit_items.tree, tree)
- WVPASSEQ(commit_items.author_name, b'Someone')
- WVPASSEQ(commit_items.author_mail, b'someone@somewhere')
- WVPASSEQ(commit_items.author_sec, 1254613729)
- WVPASSEQ(commit_items.author_offset, -(4 * 60 * 60))
- WVPASSEQ(commit_items.committer_name, cname)
- WVPASSEQ(commit_items.committer_mail, cmail)
- WVPASSEQ(commit_items.committer_sec, int(cdate))
- WVPASSEQ(commit_items.committer_offset, coff)
- WVPASSEQ(commit_items.message, b'Do something\n')
- with open(b'bar', 'wb') as f:
- f.write(b'baz\n')
- readpipe([b'git', b'add', '.'])
- readpipe([b'git', b'commit', b'-am', b'Do something else'])
- child = readpipe([b'git', b'show-ref', b'-s', b'main']).strip()
- parents = showval(child, b'%P')
- commit_items = git.get_commit_items(child, git.cp())
- WVPASSEQ(commit_items.parents, [commit])
- finally:
- os.chdir(orig_cwd)
- restore_env_var(b'GIT_AUTHOR_NAME', orig_author_name)
- restore_env_var(b'GIT_AUTHOR_EMAIL', orig_author_email)
- restore_env_var(b'GIT_COMMITTER_NAME', orig_committer_name)
- restore_env_var(b'GIT_COMMITTER_EMAIL', orig_committer_email)
-
-
-gpgsig_example_1 = b'''tree 3fab08ade2fbbda60bef180bb8e0cc5724d6bd4d
-parent 36db87b46a95ca5079f43dfe9b72220acab7c731
-author Rob Browning <
r...@defaultvalue.org> 1633397238 -0500
-committer Rob Browning <
r...@defaultvalue.org> 1633397238 -0500
-gpgsig -----BEGIN PGP SIGNATURE-----
-
- ...
- -----END PGP SIGNATURE-----
-
-Sample signed commit.
-'''
-
-gpgsig_example_2 = b'''tree 3fab08ade2fbbda60bef180bb8e0cc5724d6bd4d
-parent 36db87b46a95ca5079f43dfe9b72220acab7c731
-author Rob Browning <
r...@defaultvalue.org> 1633397238 -0500
-committer Rob Browning <
r...@defaultvalue.org> 1633397238 -0500
-gpgsig -----BEGIN PGP SIGNATURE-----
-
- ...
- -----END PGP SIGNATURE-----
-
-
-Sample signed commit.
-'''
-
-def test_commit_gpgsig_parsing():
- c = git.parse_commit(gpgsig_example_1)
- assert c.gpgsig
- assert c.gpgsig.startswith(b'-----BEGIN PGP SIGNATURE-----\n')
- assert c.gpgsig.endswith(b'\n-----END PGP SIGNATURE-----\n')
- c = git.parse_commit(gpgsig_example_2)
- assert c.gpgsig
- assert c.gpgsig.startswith(b'-----BEGIN PGP SIGNATURE-----')
- assert c.gpgsig.endswith(b'\n-----END PGP SIGNATURE-----\n\n')
-
def test_new_commit(tmpdir):
environ[b'BUP_DIR'] = bupdir = tmpdir + b'/bup'
@@ -495,12 +387,6 @@ def test_list_refs(tmpdir):
WVPASSEQ(frozenset(git.list_refs(limit_to_tags=True)), expected_tags)
-def test_git_date_str():
- WVPASSEQ(b'0 +0000', git._git_date_str(0, 0))
- WVPASSEQ(b'0 -0130', git._git_date_str(0, -90 * 60))
- WVPASSEQ(b'0 +0130', git._git_date_str(0, 90 * 60))
-
-
def test_cat_pipe(tmpdir):
environ[b'BUP_DIR'] = bupdir = tmpdir + b'/bup'
src = tmpdir + b'/src'
--
2.47.2