summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/lib/__init__.py7
-rw-r--r--test/lib/helper.py146
-rw-r--r--test/performance/lib.py43
-rw-r--r--test/performance/test_commit.py52
-rw-r--r--test/performance/test_odb.py39
-rw-r--r--test/performance/test_streams.py87
-rw-r--r--test/test_actor.py1
-rw-r--r--test/test_base.py55
-rw-r--r--test/test_blob.py9
-rw-r--r--test/test_clone.py17
-rw-r--r--test/test_commit.py252
-rw-r--r--test/test_config.py289
-rw-r--r--test/test_db.py3
-rw-r--r--test/test_diff.py236
-rw-r--r--test/test_docs.py433
-rw-r--r--test/test_exc.py83
-rw-r--r--test/test_fun.py103
-rw-r--r--test/test_git.py173
-rw-r--r--test/test_index.py311
-rw-r--r--test/test_installation.py61
-rw-r--r--test/test_reflog.py37
-rw-r--r--test/test_refs.py137
-rw-r--r--test/test_remote.py218
-rw-r--r--test/test_repo.py477
-rw-r--r--test/test_stats.py24
-rw-r--r--test/test_submodule.py567
-rw-r--r--test/test_tree.py38
-rw-r--r--test/test_util.py172
-rw-r--r--test/tstrunner.py3
29 files changed, 2470 insertions, 1603 deletions
diff --git a/test/lib/__init__.py b/test/lib/__init__.py
index 1551ce45..ae4c2b67 100644
--- a/test/lib/__init__.py
+++ b/test/lib/__init__.py
@@ -8,5 +8,8 @@
import inspect
from .helper import *
-__all__ = [name for name, obj in locals().items()
- if not (name.startswith('_') or inspect.ismodule(obj))]
+__all__ = [
+ name
+ for name, obj in locals().items()
+ if not (name.startswith("_") or inspect.ismodule(obj))
+]
diff --git a/test/lib/helper.py b/test/lib/helper.py
index 632d6af9..8f4046da 100644
--- a/test/lib/helper.py
+++ b/test/lib/helper.py
@@ -31,29 +31,37 @@ GIT_REPO = os.environ.get("GIT_PYTHON_TEST_GIT_REPO_BASE", ospd(ospd(ospd(__file
GIT_DAEMON_PORT = os.environ.get("GIT_PYTHON_TEST_GIT_DAEMON_PORT", "19418")
__all__ = (
- 'fixture_path', 'fixture', 'StringProcessAdapter',
- 'with_rw_directory', 'with_rw_repo', 'with_rw_and_rw_remote_repo',
- 'TestBase', 'TestCase',
- 'SkipTest', 'skipIf',
- 'GIT_REPO', 'GIT_DAEMON_PORT'
+ "fixture_path",
+ "fixture",
+ "StringProcessAdapter",
+ "with_rw_directory",
+ "with_rw_repo",
+ "with_rw_and_rw_remote_repo",
+ "TestBase",
+ "TestCase",
+ "SkipTest",
+ "skipIf",
+ "GIT_REPO",
+ "GIT_DAEMON_PORT",
)
log = logging.getLogger(__name__)
-#{ Routines
+# { Routines
def fixture_path(name):
- return osp.join(ospd(ospd(__file__)), 'fixtures', name)
+ return osp.join(ospd(ospd(__file__)), "fixtures", name)
def fixture(name):
- with open(fixture_path(name), 'rb') as fd:
+ with open(fixture_path(name), "rb") as fd:
return fd.read()
-#} END routines
-#{ Adapters
+# } END routines
+
+# { Adapters
class StringProcessAdapter(object):
@@ -70,9 +78,10 @@ class StringProcessAdapter(object):
poll = wait
-#} END adapters
-#{ Decorators
+# } END adapters
+
+# { Decorators
def with_rw_directory(func):
@@ -88,8 +97,12 @@ def with_rw_directory(func):
try:
return func(self, path)
except Exception:
- log.info("Test %s.%s failed, output is at %r\n",
- type(self).__name__, func.__name__, path)
+ log.info(
+ "Test %s.%s failed, output is at %r\n",
+ type(self).__name__,
+ func.__name__,
+ path,
+ )
keep = True
raise
finally:
@@ -114,14 +127,16 @@ def with_rw_repo(working_tree_ref, bare=False):
To make working with relative paths easier, the cwd will be set to the working
dir of the repository.
"""
- assert isinstance(working_tree_ref, str), "Decorator requires ref name for working tree checkout"
+ assert isinstance(
+ working_tree_ref, str
+ ), "Decorator requires ref name for working tree checkout"
def argument_passer(func):
@wraps(func)
def repo_creator(self):
- prefix = 'non_'
+ prefix = "non_"
if bare:
- prefix = ''
+ prefix = ""
# END handle prefix
repo_dir = tempfile.mktemp(prefix="%sbare_%s" % (prefix, func.__name__))
rw_repo = self.rorepo.clone(repo_dir, shared=True, bare=bare, n=True)
@@ -151,8 +166,10 @@ def with_rw_repo(working_tree_ref, bare=False):
rmtree(repo_dir)
# END rm test repo if possible
# END cleanup
+
# END rw repo creator
return repo_creator
+
# END argument passer
return argument_passer
@@ -170,24 +187,29 @@ def git_daemon_launched(base_path, ip, port):
# So, invoke it as a single command.
## Cygwin-git has no daemon. But it can use MINGW's.
#
- daemon_cmd = ['git-daemon',
- '--enable=receive-pack',
- '--listen=%s' % ip,
- '--port=%s' % port,
- '--base-path=%s' % base_path,
- base_path]
+ daemon_cmd = [
+ "git-daemon",
+ "--enable=receive-pack",
+ "--listen=%s" % ip,
+ "--port=%s" % port,
+ "--base-path=%s" % base_path,
+ base_path,
+ ]
gd = Git().execute(daemon_cmd, as_process=True)
else:
- gd = Git().daemon(base_path,
- enable='receive-pack',
- listen=ip,
- port=port,
- base_path=base_path,
- as_process=True)
+ gd = Git().daemon(
+ base_path,
+ enable="receive-pack",
+ listen=ip,
+ port=port,
+ base_path=base_path,
+ as_process=True,
+ )
# yes, I know ... fortunately, this is always going to work if sleep time is just large enough
time.sleep(0.5 * (1 + is_win))
except Exception as ex:
- msg = textwrap.dedent("""
+ msg = textwrap.dedent(
+ """
Launching git-daemon failed due to: %s
Probably test will fail subsequently.
@@ -195,14 +217,17 @@ def git_daemon_launched(base_path, ip, port):
git daemon --enable=receive-pack --listen=%s --port=%s --base-path=%s %s
You may also run the daemon on a different port by passing --port=<port>"
and setting the environment variable GIT_PYTHON_TEST_GIT_DAEMON_PORT to <port>
- """)
+ """
+ )
if is_win:
- msg += textwrap.dedent(r"""
+ msg += textwrap.dedent(
+ r"""
On Windows,
the `git-daemon.exe` must be in PATH.
For MINGW, look into .\Git\mingw64\libexec\git-core\), but problems with paths might appear.
- CYGWIN has no daemon, but if one exists, it gets along fine (but has also paths problems).""")
+ CYGWIN has no daemon, but if one exists, it gets along fine (but has also paths problems)."""
+ )
log.warning(msg, ex, ip, port, base_path, base_path, exc_info=1)
yield # OK, assume daemon started manually.
@@ -245,16 +270,23 @@ def with_rw_and_rw_remote_repo(working_tree_ref):
"""
from git import Git, Remote # To avoid circular deps.
- assert isinstance(working_tree_ref, str), "Decorator requires ref name for working tree checkout"
+ assert isinstance(
+ working_tree_ref, str
+ ), "Decorator requires ref name for working tree checkout"
def argument_passer(func):
-
@wraps(func)
def remote_repo_creator(self):
- rw_daemon_repo_dir = tempfile.mktemp(prefix="daemon_repo-%s-" % func.__name__)
- rw_repo_dir = tempfile.mktemp(prefix="daemon_cloned_repo-%s-" % func.__name__)
-
- rw_daemon_repo = self.rorepo.clone(rw_daemon_repo_dir, shared=True, bare=True)
+ rw_daemon_repo_dir = tempfile.mktemp(
+ prefix="daemon_repo-%s-" % func.__name__
+ )
+ rw_repo_dir = tempfile.mktemp(
+ prefix="daemon_cloned_repo-%s-" % func.__name__
+ )
+
+ rw_daemon_repo = self.rorepo.clone(
+ rw_daemon_repo_dir, shared=True, bare=True
+ )
# recursive alternates info ?
rw_repo = rw_daemon_repo.clone(rw_repo_dir, shared=True, bare=False, n=True)
try:
@@ -280,13 +312,19 @@ def with_rw_and_rw_remote_repo(working_tree_ref):
base_daemon_path, rel_repo_dir = osp.split(rw_daemon_repo_dir)
- remote_repo_url = Git.polish_url("git://localhost:%s/%s" % (GIT_DAEMON_PORT, rel_repo_dir))
+ remote_repo_url = Git.polish_url(
+ "git://localhost:%s/%s" % (GIT_DAEMON_PORT, rel_repo_dir)
+ )
with d_remote.config_writer as cw:
- cw.set('url', remote_repo_url)
-
- with git_daemon_launched(Git.polish_url(base_daemon_path, is_cygwin=False), # No daemon in Cygwin.
- '127.0.0.1',
- GIT_DAEMON_PORT):
+ cw.set("url", remote_repo_url)
+
+ with git_daemon_launched(
+ Git.polish_url(
+ base_daemon_path, is_cygwin=False
+ ), # No daemon in Cygwin.
+ "127.0.0.1",
+ GIT_DAEMON_PORT,
+ ):
# Try listing remotes, to diagnose whether the daemon is up.
rw_repo.git.ls_remote(d_remote)
@@ -294,8 +332,11 @@ def with_rw_and_rw_remote_repo(working_tree_ref):
try:
return func(self, rw_repo, rw_daemon_repo)
except: # noqa E722
- log.info("Keeping repos after failure: \n rw_repo_dir: %s \n rw_daemon_repo_dir: %s",
- rw_repo_dir, rw_daemon_repo_dir)
+ log.info(
+ "Keeping repos after failure: \n rw_repo_dir: %s \n rw_daemon_repo_dir: %s",
+ rw_repo_dir,
+ rw_daemon_repo_dir,
+ )
rw_repo_dir = rw_daemon_repo_dir = None
raise
@@ -312,14 +353,17 @@ def with_rw_and_rw_remote_repo(working_tree_ref):
if rw_daemon_repo_dir:
rmtree(rw_daemon_repo_dir)
# END cleanup
+
# END bare repo creator
return remote_repo_creator
# END remote repo creator
+
# END argument parser
return argument_passer
-#} END decorators
+
+# } END decorators
class TestBase(TestCase):
@@ -344,7 +388,10 @@ class TestBase(TestCase):
def _small_repo_url(self):
""":return" a path to a small, clonable repository"""
from git.cmd import Git
- return Git.polish_url(osp.join(self.rorepo.working_tree_dir, 'git/ext/gitdb/gitdb/ext/smmap'))
+
+ return Git.polish_url(
+ osp.join(self.rorepo.working_tree_dir, "git/ext/gitdb/gitdb/ext/smmap")
+ )
@classmethod
def setUpClass(cls):
@@ -353,6 +400,7 @@ class TestBase(TestCase):
each test type has its own repository
"""
from git import Repo
+
gc.collect()
cls.rorepo = Repo(GIT_REPO)
diff --git a/test/performance/lib.py b/test/performance/lib.py
index 86f87757..101e2cd4 100644
--- a/test/performance/lib.py
+++ b/test/performance/lib.py
@@ -3,27 +3,21 @@ import logging
import os
import tempfile
-from git import (
- Repo
-)
-from git.db import (
- GitCmdObjectDB,
- GitDB
-)
-from test.lib import (
- TestBase
-)
+from git import Repo
+from git.db import GitCmdObjectDB, GitDB
+from test.lib import TestBase
from git.util import rmtree
import os.path as osp
-#{ Invariants
+# { Invariants
k_env_git_repo = "GIT_PYTHON_TEST_GIT_REPO_BASE"
-#} END invariants
+# } END invariants
-#{ Base Classes
+# { Base Classes
+
class TestBigRepoR(TestBase):
@@ -39,8 +33,8 @@ class TestBigRepoR(TestBase):
* As gitrepo, but uses pure python implementation
"""
- #{ Invariants
- #} END invariants
+ # { Invariants
+ # } END invariants
def setUp(self):
try:
@@ -51,11 +45,17 @@ class TestBigRepoR(TestBase):
repo_path = os.environ.get(k_env_git_repo)
if repo_path is None:
logging.info(
- ("You can set the %s environment variable to a .git repository of" % k_env_git_repo) +
- "your choice - defaulting to the gitpython repository")
+ (
+ "You can set the %s environment variable to a .git repository of"
+ % k_env_git_repo
+ )
+ + "your choice - defaulting to the gitpython repository"
+ )
repo_path = osp.dirname(__file__)
# end set some repo path
- self.gitrorepo = Repo(repo_path, odbt=GitCmdObjectDB, search_parent_directories=True)
+ self.gitrorepo = Repo(
+ repo_path, odbt=GitCmdObjectDB, search_parent_directories=True
+ )
self.puregitrorepo = Repo(repo_path, odbt=GitDB, search_parent_directories=True)
def tearDown(self):
@@ -79,7 +79,9 @@ class TestBigRepoRW(TestBigRepoR):
pass
dirname = tempfile.mktemp()
os.mkdir(dirname)
- self.gitrwrepo = self.gitrorepo.clone(dirname, shared=True, bare=True, odbt=GitCmdObjectDB)
+ self.gitrwrepo = self.gitrorepo.clone(
+ dirname, shared=True, bare=True, odbt=GitCmdObjectDB
+ )
self.puregitrwrepo = Repo(dirname, odbt=GitDB)
def tearDown(self):
@@ -91,4 +93,5 @@ class TestBigRepoRW(TestBigRepoR):
self.puregitrwrepo.git.clear_cache()
self.puregitrwrepo = None
-#} END base classes
+
+# } END base classes
diff --git a/test/performance/test_commit.py b/test/performance/test_commit.py
index 8158a1e6..25cc34b8 100644
--- a/test/performance/test_commit.py
+++ b/test/performance/test_commit.py
@@ -14,13 +14,13 @@ from test.test_commit import TestCommitSerialization
class TestPerformance(TestBigRepoRW, TestCommitSerialization):
-
def tearDown(self):
import gc
+
gc.collect()
# ref with about 100 commits in its history
- ref_100 = '0.1.6'
+ ref_100 = "0.1.6"
def _query_commit_info(self, c):
c.author
@@ -50,8 +50,11 @@ class TestPerformance(TestBigRepoRW, TestCommitSerialization):
# END for each object
# END for each commit
elapsed_time = time() - st
- print("Traversed %i Trees and a total of %i uncached objects in %s [s] ( %f objs/s )"
- % (nc, no, elapsed_time, no / elapsed_time), file=sys.stderr)
+ print(
+ "Traversed %i Trees and a total of %i uncached objects in %s [s] ( %f objs/s )"
+ % (nc, no, elapsed_time, no / elapsed_time),
+ file=sys.stderr,
+ )
def test_commit_traversal(self):
# bound to cat-file parsing performance
@@ -62,8 +65,11 @@ class TestPerformance(TestBigRepoRW, TestCommitSerialization):
self._query_commit_info(c)
# END for each traversed commit
elapsed_time = time() - st
- print("Traversed %i Commits in %s [s] ( %f commits/s )"
- % (nc, elapsed_time, nc / elapsed_time), file=sys.stderr)
+ print(
+ "Traversed %i Commits in %s [s] ( %f commits/s )"
+ % (nc, elapsed_time, nc / elapsed_time),
+ file=sys.stderr,
+ )
def test_commit_iteration(self):
# bound to stream parsing performance
@@ -74,11 +80,14 @@ class TestPerformance(TestBigRepoRW, TestCommitSerialization):
self._query_commit_info(c)
# END for each traversed commit
elapsed_time = time() - st
- print("Iterated %i Commits in %s [s] ( %f commits/s )"
- % (nc, elapsed_time, nc / elapsed_time), file=sys.stderr)
+ print(
+ "Iterated %i Commits in %s [s] ( %f commits/s )"
+ % (nc, elapsed_time, nc / elapsed_time),
+ file=sys.stderr,
+ )
def test_commit_serialization(self):
- self.assert_commit_serialization(self.gitrwrepo, '58c78e6', True)
+ self.assert_commit_serialization(self.gitrwrepo, "58c78e6", True)
rwrepo = self.gitrwrepo
make_object = rwrepo.odb.store
@@ -89,10 +98,20 @@ class TestPerformance(TestBigRepoRW, TestCommitSerialization):
nc = 5000
st = time()
for i in range(nc):
- cm = Commit(rwrepo, Commit.NULL_BIN_SHA, hc.tree,
- hc.author, hc.authored_date, hc.author_tz_offset,
- hc.committer, hc.committed_date, hc.committer_tz_offset,
- str(i), parents=hc.parents, encoding=hc.encoding)
+ cm = Commit(
+ rwrepo,
+ Commit.NULL_BIN_SHA,
+ hc.tree,
+ hc.author,
+ hc.authored_date,
+ hc.author_tz_offset,
+ hc.committer,
+ hc.committed_date,
+ hc.committer_tz_offset,
+ str(i),
+ parents=hc.parents,
+ encoding=hc.encoding,
+ )
stream = BytesIO()
cm._serialize(stream)
@@ -103,5 +122,8 @@ class TestPerformance(TestBigRepoRW, TestCommitSerialization):
# END commit creation
elapsed = time() - st
- print("Serialized %i commits to loose objects in %f s ( %f commits / s )"
- % (nc, elapsed, nc / elapsed), file=sys.stderr)
+ print(
+ "Serialized %i commits to loose objects in %f s ( %f commits / s )"
+ % (nc, elapsed, nc / elapsed),
+ file=sys.stderr,
+ )
diff --git a/test/performance/test_odb.py b/test/performance/test_odb.py
index c9521c56..680464c9 100644
--- a/test/performance/test_odb.py
+++ b/test/performance/test_odb.py
@@ -2,13 +2,10 @@
import sys
from time import time
-from .lib import (
- TestBigRepoR
-)
+from .lib import TestBigRepoR
class TestObjDBPerformance(TestBigRepoR):
-
def test_random_access(self):
results = [["Iterate Commits"], ["Iterate Blobs"], ["Retrieve Blob Data"]]
for repo in (self.gitrorepo, self.puregitrorepo):
@@ -19,8 +16,11 @@ class TestObjDBPerformance(TestBigRepoR):
nc = len(commits)
elapsed = time() - st
- print("%s: Retrieved %i commits from ObjectStore in %g s ( %f commits / s )"
- % (type(repo.odb), nc, elapsed, nc / elapsed), file=sys.stderr)
+ print(
+ "%s: Retrieved %i commits from ObjectStore in %g s ( %f commits / s )"
+ % (type(repo.odb), nc, elapsed, nc / elapsed),
+ file=sys.stderr,
+ )
results[0].append(elapsed)
# GET TREES
@@ -33,7 +33,7 @@ class TestObjDBPerformance(TestBigRepoR):
blobs = []
for item in tree.traverse():
nt += 1
- if item.type == 'blob':
+ if item.type == "blob":
blobs.append(item)
# direct access for speed
# END while trees are there for walking
@@ -41,8 +41,11 @@ class TestObjDBPerformance(TestBigRepoR):
# END for each commit
elapsed = time() - st
- print("%s: Retrieved %i objects from %i commits in %g s ( %f objects / s )"
- % (type(repo.odb), nt, len(commits), elapsed, nt / elapsed), file=sys.stderr)
+ print(
+ "%s: Retrieved %i objects from %i commits in %g s ( %f objects / s )"
+ % (type(repo.odb), nt, len(commits), elapsed, nt / elapsed),
+ file=sys.stderr,
+ )
results[1].append(elapsed)
# GET BLOBS
@@ -60,13 +63,25 @@ class TestObjDBPerformance(TestBigRepoR):
# END for each bloblist
elapsed = time() - st
- msg = "%s: Retrieved %i blob (%i KiB) and their data in %g s ( %f blobs / s, %f KiB / s )"\
- % (type(repo.odb), nb, data_bytes / 1000, elapsed, nb / elapsed, (data_bytes / 1000) / elapsed)
+ msg = (
+ "%s: Retrieved %i blob (%i KiB) and their data in %g s ( %f blobs / s, %f KiB / s )"
+ % (
+ type(repo.odb),
+ nb,
+ data_bytes / 1000,
+ elapsed,
+ nb / elapsed,
+ (data_bytes / 1000) / elapsed,
+ )
+ )
print(msg, file=sys.stderr)
results[2].append(elapsed)
# END for each repo type
# final results
for test_name, a, b in results:
- print("%s: %f s vs %f s, pure is %f times slower" % (test_name, a, b, b / a), file=sys.stderr)
+ print(
+ "%s: %f s vs %f s, pure is %f times slower" % (test_name, a, b, b / a),
+ file=sys.stderr,
+ )
# END for each result
diff --git a/test/performance/test_streams.py b/test/performance/test_streams.py
index 28e6b13e..2ae94e29 100644
--- a/test/performance/test_streams.py
+++ b/test/performance/test_streams.py
@@ -4,36 +4,29 @@ import subprocess
import sys
from time import time
-from test.lib import (
- with_rw_repo
-)
+from test.lib import with_rw_repo
from git.util import bin_to_hex
-from gitdb import (
- LooseObjectDB,
- IStream
-)
+from gitdb import LooseObjectDB, IStream
from gitdb.test.lib import make_memory_file
import os.path as osp
-from .lib import (
- TestBigRepoR
-)
+from .lib import TestBigRepoR
class TestObjDBPerformance(TestBigRepoR):
- large_data_size_bytes = 1000 * 1000 * 10 # some MiB should do it
- moderate_data_size_bytes = 1000 * 1000 * 1 # just 1 MiB
+ large_data_size_bytes = 1000 * 1000 * 10 # some MiB should do it
+ moderate_data_size_bytes = 1000 * 1000 * 1 # just 1 MiB
- @with_rw_repo('HEAD', bare=True)
+ @with_rw_repo("HEAD", bare=True)
def test_large_data_streaming(self, rwrepo):
# TODO: This part overlaps with the same file in gitdb.test.performance.test_stream
# It should be shared if possible
- ldb = LooseObjectDB(osp.join(rwrepo.git_dir, 'objects'))
+ ldb = LooseObjectDB(osp.join(rwrepo.git_dir, "objects"))
for randomize in range(2):
- desc = (randomize and 'random ') or ''
+ desc = (randomize and "random ") or ""
print("Creating %s data ..." % desc, file=sys.stderr)
st = time()
size, stream = make_memory_file(self.large_data_size_bytes, randomize)
@@ -42,7 +35,7 @@ class TestObjDBPerformance(TestBigRepoR):
# writing - due to the compression it will seem faster than it is
st = time()
- binsha = ldb.store(IStream('blob', size, stream)).binsha
+ binsha = ldb.store(IStream("blob", size, stream)).binsha
elapsed_add = time() - st
assert ldb.has_object(binsha)
db_file = ldb.readable_db_object_path(bin_to_hex(binsha))
@@ -79,33 +72,45 @@ class TestObjDBPerformance(TestBigRepoR):
elapsed_readchunks = time() - st
stream.seek(0)
- assert b''.join(chunks) == stream.getvalue()
+ assert b"".join(chunks) == stream.getvalue()
cs_kib = cs / 1000
- print("Read %i KiB of %s data in %i KiB chunks from loose odb in %f s ( %f Read KiB / s)"
- % (size_kib, desc, cs_kib, elapsed_readchunks, size_kib / elapsed_readchunks), file=sys.stderr)
+ print(
+ "Read %i KiB of %s data in %i KiB chunks from loose odb in %f s ( %f Read KiB / s)"
+ % (
+ size_kib,
+ desc,
+ cs_kib,
+ elapsed_readchunks,
+ size_kib / elapsed_readchunks,
+ ),
+ file=sys.stderr,
+ )
# del db file so git has something to do
ostream = None
import gc
+
gc.collect()
os.remove(db_file)
# VS. CGIT
##########
# CGIT ! Can using the cgit programs be faster ?
- proc = rwrepo.git.hash_object('-w', '--stdin', as_process=True, istream=subprocess.PIPE)
+ proc = rwrepo.git.hash_object(
+ "-w", "--stdin", as_process=True, istream=subprocess.PIPE
+ )
# write file - pump everything in at once to be a fast as possible
- data = stream.getvalue() # cache it
+ data = stream.getvalue() # cache it
st = time()
proc.stdin.write(data)
proc.stdin.close()
gitsha = proc.stdout.read().strip()
proc.wait()
gelapsed_add = time() - st
- del(data)
- assert gitsha == bin_to_hex(binsha) # we do it the same way, right ?
+ del data
+ assert gitsha == bin_to_hex(binsha) # we do it the same way, right ?
# as its the same sha, we reuse our path
fsize_kib = osp.getsize(db_file) / 1000
@@ -114,19 +119,28 @@ class TestObjDBPerformance(TestBigRepoR):
print(msg, file=sys.stderr)
# compare ...
- print("Git-Python is %f %% faster than git when adding big %s files"
- % (100.0 - (elapsed_add / gelapsed_add) * 100, desc), file=sys.stderr)
+ print(
+ "Git-Python is %f %% faster than git when adding big %s files"
+ % (100.0 - (elapsed_add / gelapsed_add) * 100, desc),
+ file=sys.stderr,
+ )
# read all
st = time()
_hexsha, _typename, size, data = rwrepo.git.get_object_data(gitsha)
gelapsed_readall = time() - st
- print("Read %i KiB of %s data at once using git-cat-file in %f s ( %f Read KiB / s)"
- % (size_kib, desc, gelapsed_readall, size_kib / gelapsed_readall), file=sys.stderr)
+ print(
+ "Read %i KiB of %s data at once using git-cat-file in %f s ( %f Read KiB / s)"
+ % (size_kib, desc, gelapsed_readall, size_kib / gelapsed_readall),
+ file=sys.stderr,
+ )
# compare
- print("Git-Python is %f %% faster than git when reading big %sfiles"
- % (100.0 - (elapsed_readall / gelapsed_readall) * 100, desc), file=sys.stderr)
+ print(
+ "Git-Python is %f %% faster than git when reading big %sfiles"
+ % (100.0 - (elapsed_readall / gelapsed_readall) * 100, desc),
+ file=sys.stderr,
+ )
# read chunks
st = time()
@@ -138,10 +152,19 @@ class TestObjDBPerformance(TestBigRepoR):
# END read stream
gelapsed_readchunks = time() - st
msg = "Read %i KiB of %s data in %i KiB chunks from git-cat-file in %f s ( %f Read KiB / s)"
- msg %= (size_kib, desc, cs_kib, gelapsed_readchunks, size_kib / gelapsed_readchunks)
+ msg %= (
+ size_kib,
+ desc,
+ cs_kib,
+ gelapsed_readchunks,
+ size_kib / gelapsed_readchunks,
+ )
print(msg, file=sys.stderr)
# compare
- print("Git-Python is %f %% faster than git when reading big %s files in chunks"
- % (100.0 - (elapsed_readchunks / gelapsed_readchunks) * 100, desc), file=sys.stderr)
+ print(
+ "Git-Python is %f %% faster than git when reading big %s files in chunks"
+ % (100.0 - (elapsed_readchunks / gelapsed_readchunks) * 100, desc),
+ file=sys.stderr,
+ )
# END for each randomization factor
diff --git a/test/test_actor.py b/test/test_actor.py
index 32d16ea7..ce0c74fc 100644
--- a/test/test_actor.py
+++ b/test/test_actor.py
@@ -9,7 +9,6 @@ from git import Actor
class TestActor(TestBase):
-
def test_from_string_should_separate_name_and_email(self):
a = Actor._from_string("Michael Trier <mtrier@example.com>")
self.assertEqual("Michael Trier", a.name)
diff --git a/test/test_base.py b/test/test_base.py
index 68ce6816..a7c034e2 100644
--- a/test/test_base.py
+++ b/test/test_base.py
@@ -9,19 +9,10 @@ import sys
import tempfile
from unittest import SkipTest, skipIf
-from git.objects import (
- Blob,
- Tree,
- Commit,
- TagObject
-)
+from git.objects import Blob, Tree, Commit, TagObject
from git.compat import is_win
from git.objects.util import get_object_type_by_name
-from test.lib import (
- TestBase as _TestBase,
- with_rw_repo,
- with_rw_and_rw_remote_repo
-)
+from test.lib import TestBase as _TestBase, with_rw_repo, with_rw_and_rw_remote_repo
from git.util import hex_to_bin, HIDE_WINDOWS_FREEZE_ERRORS
import git.objects.base as base
@@ -29,15 +20,17 @@ import os.path as osp
class TestBase(_TestBase):
-
def tearDown(self):
import gc
+
gc.collect()
- type_tuples = (("blob", "8741fc1d09d61f02ffd8cded15ff603eff1ec070", "blob.py"),
- ("tree", "3a6a5e3eeed3723c09f1ef0399f81ed6b8d82e79", "directory"),
- ("commit", "4251bd59fb8e11e40c40548cba38180a9536118c", None),
- ("tag", "e56a60e8e9cd333cfba0140a77cd12b0d9398f10", None))
+ type_tuples = (
+ ("blob", "8741fc1d09d61f02ffd8cded15ff603eff1ec070", "blob.py"),
+ ("tree", "3a6a5e3eeed3723c09f1ef0399f81ed6b8d82e79", "directory"),
+ ("commit", "4251bd59fb8e11e40c40548cba38180a9536118c", None),
+ ("tag", "e56a60e8e9cd333cfba0140a77cd12b0d9398f10", None),
+ )
def test_base_object(self):
# test interface of base object classes
@@ -67,8 +60,8 @@ class TestBase(_TestBase):
if isinstance(item, base.IndexObject):
num_index_objs += 1
- if hasattr(item, 'path'): # never runs here
- assert not item.path.startswith("/") # must be relative
+ if hasattr(item, "path"): # never runs here
+ assert not item.path.startswith("/") # must be relative
assert isinstance(item.mode, int)
# END index object check
@@ -77,8 +70,8 @@ class TestBase(_TestBase):
data = data_stream.read()
assert data
- tmpfilename = tempfile.mktemp(suffix='test-stream')
- with open(tmpfilename, 'wb+') as tmpfile:
+ tmpfilename = tempfile.mktemp(suffix="test-stream")
+ with open(tmpfilename, "wb+") as tmpfile:
self.assertEqual(item, item.stream_data(tmpfile))
tmpfile.seek(0)
self.assertEqual(tmpfile.read(), data)
@@ -99,26 +92,28 @@ class TestBase(_TestBase):
def test_object_resolution(self):
# objects must be resolved to shas so they compare equal
- self.assertEqual(self.rorepo.head.reference.object, self.rorepo.active_branch.object)
+ self.assertEqual(
+ self.rorepo.head.reference.object, self.rorepo.active_branch.object
+ )
- @with_rw_repo('HEAD', bare=True)
+ @with_rw_repo("HEAD", bare=True)
def test_with_bare_rw_repo(self, bare_rw_repo):
assert bare_rw_repo.config_reader("repository").getboolean("core", "bare")
- assert osp.isfile(osp.join(bare_rw_repo.git_dir, 'HEAD'))
+ assert osp.isfile(osp.join(bare_rw_repo.git_dir, "HEAD"))
- @with_rw_repo('0.1.6')
+ @with_rw_repo("0.1.6")
def test_with_rw_repo(self, rw_repo):
assert not rw_repo.config_reader("repository").getboolean("core", "bare")
- assert osp.isdir(osp.join(rw_repo.working_tree_dir, 'lib'))
+ assert osp.isdir(osp.join(rw_repo.working_tree_dir, "lib"))
@skipIf(HIDE_WINDOWS_FREEZE_ERRORS, "FIXME: Freezes! sometimes...")
- @with_rw_and_rw_remote_repo('0.1.6')
+ @with_rw_and_rw_remote_repo("0.1.6")
def test_with_rw_remote_and_rw_repo(self, rw_repo, rw_remote_repo):
assert not rw_repo.config_reader("repository").getboolean("core", "bare")
assert rw_remote_repo.config_reader("repository").getboolean("core", "bare")
- assert osp.isdir(osp.join(rw_repo.working_tree_dir, 'lib'))
+ assert osp.isdir(osp.join(rw_repo.working_tree_dir, "lib"))
- @with_rw_repo('0.1.6')
+ @with_rw_repo("0.1.6")
def test_add_unicode(self, rw_repo):
filename = "שלום.txt"
@@ -131,7 +126,7 @@ class TestBase(_TestBase):
raise SkipTest("Environment doesn't support unicode filenames") from e
with open(file_path, "wb") as fp:
- fp.write(b'something')
+ fp.write(b"something")
if is_win:
# on windows, there is no way this works, see images on
@@ -144,4 +139,4 @@ class TestBase(_TestBase):
# on posix, we can just add unicode files without problems
rw_repo.git.add(rw_repo.working_dir)
# end
- rw_repo.index.commit('message')
+ rw_repo.index.commit("message")
diff --git a/test/test_blob.py b/test/test_blob.py
index c9c8c48a..ad5b46c1 100644
--- a/test/test_blob.py
+++ b/test/test_blob.py
@@ -9,14 +9,15 @@ from git import Blob
class TestBlob(TestBase):
-
def test_mime_type_should_return_mime_type_for_known_types(self):
- blob = Blob(self.rorepo, **{'binsha': Blob.NULL_BIN_SHA, 'path': 'foo.png'})
+ blob = Blob(self.rorepo, **{"binsha": Blob.NULL_BIN_SHA, "path": "foo.png"})
self.assertEqual("image/png", blob.mime_type)
def test_mime_type_should_return_text_plain_for_unknown_types(self):
- blob = Blob(self.rorepo, **{'binsha': Blob.NULL_BIN_SHA, 'path': 'something'})
+ blob = Blob(self.rorepo, **{"binsha": Blob.NULL_BIN_SHA, "path": "something"})
self.assertEqual("text/plain", blob.mime_type)
def test_nodict(self):
- self.assertRaises(AttributeError, setattr, self.rorepo.tree()['AUTHORS'], 'someattr', 2)
+ self.assertRaises(
+ AttributeError, setattr, self.rorepo.tree()["AUTHORS"], "someattr", 2
+ )
diff --git a/test/test_clone.py b/test/test_clone.py
index e9f6714d..6bd944f9 100644
--- a/test/test_clone.py
+++ b/test/test_clone.py
@@ -17,16 +17,23 @@ class TestClone(TestBase):
@with_rw_directory
def test_checkout_in_non_empty_dir(self, rw_dir):
non_empty_dir = Path(rw_dir)
- garbage_file = non_empty_dir / 'not-empty'
- garbage_file.write_text('Garbage!')
+ garbage_file = non_empty_dir / "not-empty"
+ garbage_file.write_text("Garbage!")
# Verify that cloning into the non-empty dir fails while complaining about
# the target directory not being empty/non-existent
try:
self.rorepo.clone(non_empty_dir)
except git.GitCommandError as exc:
- self.assertTrue(exc.stderr, "GitCommandError's 'stderr' is unexpectedly empty")
- expr = re.compile(r'(?is).*\bfatal:\s+destination\s+path\b.*\bexists\b.*\bnot\b.*\bempty\s+directory\b')
- self.assertTrue(expr.search(exc.stderr), '"%s" does not match "%s"' % (expr.pattern, exc.stderr))
+ self.assertTrue(
+ exc.stderr, "GitCommandError's 'stderr' is unexpectedly empty"
+ )
+ expr = re.compile(
+ r"(?is).*\bfatal:\s+destination\s+path\b.*\bexists\b.*\bnot\b.*\bempty\s+directory\b"
+ )
+ self.assertTrue(
+ expr.search(exc.stderr),
+ '"%s" does not match "%s"' % (expr.pattern, exc.stderr),
+ )
else:
self.fail("GitCommandError not raised")
diff --git a/test/test_commit.py b/test/test_commit.py
index 40cf7dd2..17a4fe4f 100644
--- a/test/test_commit.py
+++ b/test/test_commit.py
@@ -19,12 +19,7 @@ from git import (
from git import Repo
from git.objects.util import tzoffset, utc
from git.repo.fun import touch
-from test.lib import (
- TestBase,
- with_rw_repo,
- fixture_path,
- StringProcessAdapter
-)
+from test.lib import TestBase, with_rw_repo, fixture_path, StringProcessAdapter
from test.lib import with_rw_directory
from gitdb import IStream
@@ -32,13 +27,14 @@ import os.path as osp
class TestCommitSerialization(TestBase):
-
- def assert_commit_serialization(self, rwrepo, commit_id, print_performance_info=False):
+ def assert_commit_serialization(
+ self, rwrepo, commit_id, print_performance_info=False
+ ):
"""traverse all commits in the history of commit identified by commit_id and check
if the serialization works.
:param print_performance_info: if True, we will show how fast we are"""
- ns = 0 # num serializations
- nds = 0 # num deserializations
+ ns = 0 # num serializations
+ nds = 0 # num deserializations
st = time.time()
for cm in rwrepo.commit(commit_id).traverse():
@@ -53,12 +49,22 @@ class TestCommitSerialization(TestBase):
stream.seek(0)
istream = rwrepo.odb.store(IStream(Commit.type, streamlen, stream))
- self.assertEqual(istream.hexsha, cm.hexsha.encode('ascii'))
-
- nc = Commit(rwrepo, Commit.NULL_BIN_SHA, cm.tree,
- cm.author, cm.authored_date, cm.author_tz_offset,
- cm.committer, cm.committed_date, cm.committer_tz_offset,
- cm.message, cm.parents, cm.encoding)
+ self.assertEqual(istream.hexsha, cm.hexsha.encode("ascii"))
+
+ nc = Commit(
+ rwrepo,
+ Commit.NULL_BIN_SHA,
+ cm.tree,
+ cm.author,
+ cm.authored_date,
+ cm.author_tz_offset,
+ cm.committer,
+ cm.committed_date,
+ cm.committer_tz_offset,
+ cm.message,
+ cm.parents,
+ cm.encoding,
+ )
self.assertEqual(nc.parents, cm.parents)
stream = BytesIO()
@@ -79,55 +85,65 @@ class TestCommitSerialization(TestBase):
elapsed = time.time() - st
if print_performance_info:
- print("Serialized %i and deserialized %i commits in %f s ( (%f, %f) commits / s"
- % (ns, nds, elapsed, ns / elapsed, nds / elapsed), file=sys.stderr)
+ print(
+ "Serialized %i and deserialized %i commits in %f s ( (%f, %f) commits / s"
+ % (ns, nds, elapsed, ns / elapsed, nds / elapsed),
+ file=sys.stderr,
+ )
# END handle performance info
class TestCommit(TestCommitSerialization):
-
def test_bake(self):
- commit = self.rorepo.commit('2454ae89983a4496a445ce347d7a41c0bb0ea7ae')
+ commit = self.rorepo.commit("2454ae89983a4496a445ce347d7a41c0bb0ea7ae")
# commits have no dict
- self.assertRaises(AttributeError, setattr, commit, 'someattr', 1)
+ self.assertRaises(AttributeError, setattr, commit, "someattr", 1)
commit.author # bake
self.assertEqual("Sebastian Thiel", commit.author.name)
self.assertEqual("byronimo@gmail.com", commit.author.email)
self.assertEqual(commit.author, commit.committer)
- assert isinstance(commit.authored_date, int) and isinstance(commit.committed_date, int)
- assert isinstance(commit.author_tz_offset, int) and isinstance(commit.committer_tz_offset, int)
- self.assertEqual(commit.message, "Added missing information to docstrings of commit and stats module\n")
+ assert isinstance(commit.authored_date, int) and isinstance(
+ commit.committed_date, int
+ )
+ assert isinstance(commit.author_tz_offset, int) and isinstance(
+ commit.committer_tz_offset, int
+ )
+ self.assertEqual(
+ commit.message,
+ "Added missing information to docstrings of commit and stats module\n",
+ )
def test_replace_no_changes(self):
- old_commit = self.rorepo.commit('2454ae89983a4496a445ce347d7a41c0bb0ea7ae')
+ old_commit = self.rorepo.commit("2454ae89983a4496a445ce347d7a41c0bb0ea7ae")
new_commit = old_commit.replace()
for attr in old_commit.__slots__:
assert getattr(new_commit, attr) == getattr(old_commit, attr)
def test_replace_new_sha(self):
- commit = self.rorepo.commit('2454ae89983a4496a445ce347d7a41c0bb0ea7ae')
- new_commit = commit.replace(message='Added replace method')
+ commit = self.rorepo.commit("2454ae89983a4496a445ce347d7a41c0bb0ea7ae")
+ new_commit = commit.replace(message="Added replace method")
- assert new_commit.hexsha == 'fc84cbecac1bd4ba4deaac07c1044889edd536e6'
- assert new_commit.message == 'Added replace method'
+ assert new_commit.hexsha == "fc84cbecac1bd4ba4deaac07c1044889edd536e6"
+ assert new_commit.message == "Added replace method"
def test_replace_invalid_attribute(self):
- commit = self.rorepo.commit('2454ae89983a4496a445ce347d7a41c0bb0ea7ae')
+ commit = self.rorepo.commit("2454ae89983a4496a445ce347d7a41c0bb0ea7ae")
with self.assertRaises(ValueError):
- commit.replace(badattr='This will never work')
+ commit.replace(badattr="This will never work")
def test_stats(self):
- commit = self.rorepo.commit('33ebe7acec14b25c5f84f35a664803fcab2f7781')
+ commit = self.rorepo.commit("33ebe7acec14b25c5f84f35a664803fcab2f7781")
stats = commit.stats
def check_entries(d):
assert isinstance(d, dict)
for key in ("insertions", "deletions", "lines"):
assert key in d
+
# END assertion helper
assert stats.files
assert stats.total
@@ -179,19 +195,24 @@ class TestCommit(TestCommitSerialization):
# at some point, both iterations should stop
self.assertEqual(list(bfirst)[-1], first)
- stoptraverse = self.rorepo.commit("254d04aa3180eb8b8daf7b7ff25f010cd69b4e7d").traverse(ignore_self=0,
- as_edge=True)
+ stoptraverse = self.rorepo.commit(
+ "254d04aa3180eb8b8daf7b7ff25f010cd69b4e7d"
+ ).traverse(ignore_self=0, as_edge=True)
stoptraverse_list = list(stoptraverse)
for itemtup in stoptraverse_list:
- self.assertIsInstance(itemtup, (tuple)) and self.assertEqual(len(itemtup), 2) # as_edge=True -> tuple
+ self.assertIsInstance(itemtup, (tuple)) and self.assertEqual(
+ len(itemtup), 2
+ ) # as_edge=True -> tuple
src, item = itemtup
self.assertIsInstance(item, Commit)
if src:
self.assertIsInstance(src, Commit)
else:
- self.assertIsNone(src) # ignore_self=0 -> first is (None, Commit)
+ self.assertIsNone(src) # ignore_self=0 -> first is (None, Commit)
- stoptraverse = self.rorepo.commit("254d04aa3180eb8b8daf7b7ff25f010cd69b4e7d").traverse(as_edge=True)
+ stoptraverse = self.rorepo.commit(
+ "254d04aa3180eb8b8daf7b7ff25f010cd69b4e7d"
+ ).traverse(as_edge=True)
self.assertEqual(len(next(stoptraverse)), 2)
# ignore self
@@ -201,10 +222,14 @@ class TestCommit(TestCommitSerialization):
self.assertEqual(len(list(start.traverse(ignore_self=False, depth=0))), 1)
# prune
- self.assertEqual(next(start.traverse(branch_first=1, prune=lambda i, d: i == p0)), p1)
+ self.assertEqual(
+ next(start.traverse(branch_first=1, prune=lambda i, d: i == p0)), p1
+ )
# predicate
- self.assertEqual(next(start.traverse(branch_first=1, predicate=lambda i, d: i == p1)), p1)
+ self.assertEqual(
+ next(start.traverse(branch_first=1, predicate=lambda i, d: i == p1)), p1
+ )
# traversal should stop when the beginning is reached
self.assertRaises(StopIteration, next, first.traverse())
@@ -220,64 +245,78 @@ class TestCommit(TestCommitSerialization):
self.assertEqual(all_commits, list(self.rorepo.iter_commits()))
# this includes merge commits
- mcomit = self.rorepo.commit('d884adc80c80300b4cc05321494713904ef1df2d')
+ mcomit = self.rorepo.commit("d884adc80c80300b4cc05321494713904ef1df2d")
assert mcomit in all_commits
# we can limit the result to paths
- ltd_commits = list(self.rorepo.iter_commits(paths='CHANGES'))
+ ltd_commits = list(self.rorepo.iter_commits(paths="CHANGES"))
assert ltd_commits and len(ltd_commits) < len(all_commits)
# show commits of multiple paths, resulting in a union of commits
- less_ltd_commits = list(Commit.iter_items(self.rorepo, 'master', paths=('CHANGES', 'AUTHORS')))
+ less_ltd_commits = list(
+ Commit.iter_items(self.rorepo, "master", paths=("CHANGES", "AUTHORS"))
+ )
assert len(ltd_commits) < len(less_ltd_commits)
class Child(Commit):
def __init__(self, *args, **kwargs):
super(Child, self).__init__(*args, **kwargs)
- child_commits = list(Child.iter_items(self.rorepo, 'master', paths=('CHANGES', 'AUTHORS')))
+ child_commits = list(
+ Child.iter_items(self.rorepo, "master", paths=("CHANGES", "AUTHORS"))
+ )
assert type(child_commits[0]) == Child
def test_iter_items(self):
# pretty not allowed
- self.assertRaises(ValueError, Commit.iter_items, self.rorepo, 'master', pretty="raw")
+ self.assertRaises(
+ ValueError, Commit.iter_items, self.rorepo, "master", pretty="raw"
+ )
def test_rev_list_bisect_all(self):
"""
'git rev-list --bisect-all' returns additional information
in the commit header. This test ensures that we properly parse it.
"""
- revs = self.rorepo.git.rev_list('933d23bf95a5bd1624fbcdf328d904e1fa173474',
- first_parent=True,
- bisect_all=True)
+ revs = self.rorepo.git.rev_list(
+ "933d23bf95a5bd1624fbcdf328d904e1fa173474",
+ first_parent=True,
+ bisect_all=True,
+ )
- commits = Commit._iter_from_process_or_stream(self.rorepo, StringProcessAdapter(revs.encode('ascii')))
+ commits = Commit._iter_from_process_or_stream(
+ self.rorepo, StringProcessAdapter(revs.encode("ascii"))
+ )
expected_ids = (
- '7156cece3c49544abb6bf7a0c218eb36646fad6d',
- '1f66cfbbce58b4b552b041707a12d437cc5f400a',
- '33ebe7acec14b25c5f84f35a664803fcab2f7781',
- '933d23bf95a5bd1624fbcdf328d904e1fa173474'
+ "7156cece3c49544abb6bf7a0c218eb36646fad6d",
+ "1f66cfbbce58b4b552b041707a12d437cc5f400a",
+ "33ebe7acec14b25c5f84f35a664803fcab2f7781",
+ "933d23bf95a5bd1624fbcdf328d904e1fa173474",
)
for sha1, commit in zip(expected_ids, commits):
self.assertEqual(sha1, commit.hexsha)
@with_rw_directory
def test_ambiguous_arg_iteration(self, rw_dir):
- rw_repo = Repo.init(osp.join(rw_dir, 'test_ambiguous_arg'))
- path = osp.join(str(rw_repo.working_tree_dir), 'master')
+ rw_repo = Repo.init(osp.join(rw_dir, "test_ambiguous_arg"))
+ path = osp.join(str(rw_repo.working_tree_dir), "master")
touch(path)
rw_repo.index.add([path])
- rw_repo.index.commit('initial commit')
+ rw_repo.index.commit("initial commit")
list(rw_repo.iter_commits(rw_repo.head.ref)) # should fail unless bug is fixed
def test_count(self):
- self.assertEqual(self.rorepo.tag('refs/tags/0.1.5').commit.count(), 143)
+ self.assertEqual(self.rorepo.tag("refs/tags/0.1.5").commit.count(), 143)
def test_list(self):
# This doesn't work anymore, as we will either attempt getattr with bytes, or compare 20 byte string
# with actual 20 byte bytes. This usage makes no sense anyway
- assert isinstance(Commit.list_items(self.rorepo, '0.1.5', max_count=5)[
- '5117c9c8a4d3af19a9958677e45cda9269de1541'], Commit)
+ assert isinstance(
+ Commit.list_items(self.rorepo, "0.1.5", max_count=5)[
+ "5117c9c8a4d3af19a9958677e45cda9269de1541"
+ ],
+ Commit,
+ )
def test_str(self):
commit = Commit(self.rorepo, Commit.NULL_BIN_SHA)
@@ -296,7 +335,7 @@ class TestCommit(TestCommitSerialization):
def test_iter_parents(self):
# should return all but ourselves, even if skip is defined
- c = self.rorepo.commit('0.1.5')
+ c = self.rorepo.commit("0.1.5")
for skip in (0, 1):
piter = c.iter_parents(skip=skip)
first_parent = next(piter)
@@ -308,18 +347,18 @@ class TestCommit(TestCommitSerialization):
name_rev = self.rorepo.head.commit.name_rev
assert isinstance(name_rev, str)
- @with_rw_repo('HEAD', bare=True)
+ @with_rw_repo("HEAD", bare=True)
def test_serialization(self, rwrepo):
# create all commits of our repo
- self.assert_commit_serialization(rwrepo, '0.1.6')
+ self.assert_commit_serialization(rwrepo, "0.1.6")
def test_serialization_unicode_support(self):
- self.assertEqual(Commit.default_encoding.lower(), 'utf-8')
+ self.assertEqual(Commit.default_encoding.lower(), "utf-8")
# create a commit with unicode in the message, and the author's name
# Verify its serialization and deserialization
- cmt = self.rorepo.commit('0.1.6')
- assert isinstance(cmt.message, str) # it automatically decodes it as such
+ cmt = self.rorepo.commit("0.1.6")
+ assert isinstance(cmt.message, str) # it automatically decodes it as such
assert isinstance(cmt.author.name, str) # same here
cmt.message = "üäêèß"
@@ -344,15 +383,15 @@ class TestCommit(TestCommitSerialization):
def test_invalid_commit(self):
cmt = self.rorepo.commit()
- with open(fixture_path('commit_invalid_data'), 'rb') as fd:
+ with open(fixture_path("commit_invalid_data"), "rb") as fd:
cmt._deserialize(fd)
- self.assertEqual(cmt.author.name, 'E.Azer Ko�o�o�oculu', cmt.author.name)
- self.assertEqual(cmt.author.email, 'azer@kodfabrik.com', cmt.author.email)
+ self.assertEqual(cmt.author.name, "E.Azer Ko�o�o�oculu", cmt.author.name)
+ self.assertEqual(cmt.author.email, "azer@kodfabrik.com", cmt.author.email)
def test_gpgsig(self):
cmt = self.rorepo.commit()
- with open(fixture_path('commit_with_gpgsig'), 'rb') as fd:
+ with open(fixture_path("commit_with_gpgsig"), "rb") as fd:
cmt._deserialize(fd)
fixture_sig = """-----BEGIN PGP SIGNATURE-----
@@ -379,7 +418,11 @@ JzJMZDRLQLFvnzqZuCjE
cstream = BytesIO()
cmt._serialize(cstream)
- assert re.search(r"^gpgsig <test\n dummy\n sig>$", cstream.getvalue().decode('ascii'), re.MULTILINE)
+ assert re.search(
+ r"^gpgsig <test\n dummy\n sig>$",
+ cstream.getvalue().decode("ascii"),
+ re.MULTILINE,
+ )
self.assert_gpgsig_deserialization(cstream)
@@ -391,10 +434,12 @@ JzJMZDRLQLFvnzqZuCjE
cmt.gpgsig = None
cstream = BytesIO()
cmt._serialize(cstream)
- assert not re.search(r"^gpgsig ", cstream.getvalue().decode('ascii'), re.MULTILINE)
+ assert not re.search(
+ r"^gpgsig ", cstream.getvalue().decode("ascii"), re.MULTILINE
+ )
def assert_gpgsig_deserialization(self, cstream):
- assert 'gpgsig' in 'precondition: need gpgsig'
+ assert "gpgsig" in "precondition: need gpgsig"
class RepoMock:
def __init__(self, bytestr):
@@ -407,29 +452,40 @@ JzJMZDRLQLFvnzqZuCjE
self.bytestr = bytestr
def stream(self, *args):
- stream = Mock(spec_set=['read'], return_value=self.bytestr)
+ stream = Mock(spec_set=["read"], return_value=self.bytestr)
stream.read.return_value = self.bytestr
- return ('binsha', 'typename', 'size', stream)
+ return ("binsha", "typename", "size", stream)
return ODBMock(self.bytestr)
repo_mock = RepoMock(cstream.getvalue())
for field in Commit.__slots__:
- c = Commit(repo_mock, b'x' * 20)
+ c = Commit(repo_mock, b"x" * 20)
assert getattr(c, field) is not None
def test_datetimes(self):
- commit = self.rorepo.commit('4251bd5')
+ commit = self.rorepo.commit("4251bd5")
self.assertEqual(commit.authored_date, 1255018625)
self.assertEqual(commit.committed_date, 1255026171)
- self.assertEqual(commit.authored_datetime,
- datetime(2009, 10, 8, 18, 17, 5, tzinfo=tzoffset(-7200)), commit.authored_datetime) # noqa
- self.assertEqual(commit.authored_datetime,
- datetime(2009, 10, 8, 16, 17, 5, tzinfo=utc), commit.authored_datetime)
- self.assertEqual(commit.committed_datetime,
- datetime(2009, 10, 8, 20, 22, 51, tzinfo=tzoffset(-7200)))
- self.assertEqual(commit.committed_datetime,
- datetime(2009, 10, 8, 18, 22, 51, tzinfo=utc), commit.committed_datetime)
+ self.assertEqual(
+ commit.authored_datetime,
+ datetime(2009, 10, 8, 18, 17, 5, tzinfo=tzoffset(-7200)),
+ commit.authored_datetime,
+ ) # noqa
+ self.assertEqual(
+ commit.authored_datetime,
+ datetime(2009, 10, 8, 16, 17, 5, tzinfo=utc),
+ commit.authored_datetime,
+ )
+ self.assertEqual(
+ commit.committed_datetime,
+ datetime(2009, 10, 8, 20, 22, 51, tzinfo=tzoffset(-7200)),
+ )
+ self.assertEqual(
+ commit.committed_datetime,
+ datetime(2009, 10, 8, 18, 22, 51, tzinfo=utc),
+ commit.committed_datetime,
+ )
def test_trailers(self):
KEY_1 = "Hello"
@@ -440,12 +496,18 @@ JzJMZDRLQLFvnzqZuCjE
# Check if KEY 1 & 2 with Value 1 & 2 is extracted from multiple msg variations
msgs = []
msgs.append(f"Subject\n\n{KEY_1}: {VALUE_1}\n{KEY_2}: {VALUE_2}\n")
- msgs.append(f"Subject\n \nSome body of a function\n \n{KEY_1}: {VALUE_1}\n{KEY_2}: {VALUE_2}\n")
- msgs.append(f"Subject\n \nSome body of a function\n\nnon-key: non-value\n\n{KEY_1}: {VALUE_1}\n{KEY_2}: {VALUE_2}\n")
- msgs.append(f"Subject\n \nSome multiline\n body of a function\n\nnon-key: non-value\n\n{KEY_1}: {VALUE_1}\n{KEY_2} : {VALUE_2}\n")
+ msgs.append(
+ f"Subject\n \nSome body of a function\n \n{KEY_1}: {VALUE_1}\n{KEY_2}: {VALUE_2}\n"
+ )
+ msgs.append(
+ f"Subject\n \nSome body of a function\n\nnon-key: non-value\n\n{KEY_1}: {VALUE_1}\n{KEY_2}: {VALUE_2}\n"
+ )
+ msgs.append(
+ f"Subject\n \nSome multiline\n body of a function\n\nnon-key: non-value\n\n{KEY_1}: {VALUE_1}\n{KEY_2} : {VALUE_2}\n"
+ )
for msg in msgs:
- commit = self.rorepo.commit('master')
+ commit = self.rorepo.commit("master")
commit = copy.copy(commit)
commit.message = msg
assert KEY_1 in commit.trailers.keys()
@@ -457,21 +519,27 @@ JzJMZDRLQLFvnzqZuCjE
msgs = []
msgs.append(f"Subject\n")
msgs.append(f"Subject\n\nBody with some\nText\n")
- msgs.append(f"Subject\n\nBody with\nText\n\nContinuation but\n doesn't contain colon\n")
- msgs.append(f"Subject\n\nBody with\nText\n\nContinuation but\n only contains one :\n")
+ msgs.append(
+ f"Subject\n\nBody with\nText\n\nContinuation but\n doesn't contain colon\n"
+ )
+ msgs.append(
+ f"Subject\n\nBody with\nText\n\nContinuation but\n only contains one :\n"
+ )
msgs.append(f"Subject\n\nBody with\nText\n\nKey: Value\nLine without colon\n")
msgs.append(f"Subject\n\nBody with\nText\n\nLine without colon\nKey: Value\n")
for msg in msgs:
- commit = self.rorepo.commit('master')
+ commit = self.rorepo.commit("master")
commit = copy.copy(commit)
commit.message = msg
assert len(commit.trailers.keys()) == 0
# check that only the last key value paragraph is evaluated
- commit = self.rorepo.commit('master')
+ commit = self.rorepo.commit("master")
commit = copy.copy(commit)
- commit.message = f"Subject\n\nMultiline\nBody\n\n{KEY_1}: {VALUE_1}\n\n{KEY_2}: {VALUE_2}\n"
+ commit.message = (
+ f"Subject\n\nMultiline\nBody\n\n{KEY_1}: {VALUE_1}\n\n{KEY_2}: {VALUE_2}\n"
+ )
assert KEY_1 not in commit.trailers.keys()
assert KEY_2 in commit.trailers.keys()
assert commit.trailers[KEY_2] == VALUE_2
diff --git a/test/test_config.py b/test/test_config.py
index 50d9b010..45677b0d 100644
--- a/test/test_config.py
+++ b/test/test_config.py
@@ -9,9 +9,7 @@ import io
import os
from unittest import mock
-from git import (
- GitConfigParser
-)
+from git import GitConfigParser
from git.config import _OMD, cp
from test.lib import (
TestCase,
@@ -24,7 +22,7 @@ import os.path as osp
from git.util import rmfile
-_tc_lock_fpaths = osp.join(osp.dirname(__file__), 'fixtures/*.lock')
+_tc_lock_fpaths = osp.join(osp.dirname(__file__), "fixtures/*.lock")
def _rm_lock_files():
@@ -39,7 +37,9 @@ class TestBase(TestCase):
def tearDown(self):
for lfp in glob.glob(_tc_lock_fpaths):
if osp.isfile(lfp):
- raise AssertionError('Previous TC left hanging git-lock file: {}'.format(lfp))
+ raise AssertionError(
+ "Previous TC left hanging git-lock file: {}".format(lfp)
+ )
def _to_memcache(self, file_path):
with open(file_path, "rb") as fp:
@@ -52,13 +52,16 @@ class TestBase(TestCase):
for filename in ("git_config", "git_config_global"):
file_obj = self._to_memcache(fixture_path(filename))
with GitConfigParser(file_obj, read_only=False) as w_config:
- w_config.read() # enforce reading
+ w_config.read() # enforce reading
assert w_config._sections
- w_config.write() # enforce writing
+ w_config.write() # enforce writing
# we stripped lines when reading, so the results differ
assert file_obj.getvalue()
- self.assertEqual(file_obj.getvalue(), self._to_memcache(fixture_path(filename)).getvalue())
+ self.assertEqual(
+ file_obj.getvalue(),
+ self._to_memcache(fixture_path(filename)).getvalue(),
+ )
# creating an additional config writer must fail due to exclusive access
with self.assertRaises(IOError):
@@ -91,29 +94,31 @@ class TestBase(TestCase):
# END for each filename
def test_includes_order(self):
- with GitConfigParser(list(map(fixture_path, ("git_config", "git_config_global")))) as r_config:
- r_config.read() # enforce reading
+ with GitConfigParser(
+ list(map(fixture_path, ("git_config", "git_config_global")))
+ ) as r_config:
+ r_config.read() # enforce reading
# Simple inclusions, again checking them taking precedence
- assert r_config.get_value('sec', 'var0') == "value0_included"
+ assert r_config.get_value("sec", "var0") == "value0_included"
# This one should take the git_config_global value since included
# values must be considered as soon as they get them
- assert r_config.get_value('diff', 'tool') == "meld"
+ assert r_config.get_value("diff", "tool") == "meld"
try:
- assert r_config.get_value('sec', 'var1') == "value1_main"
+ assert r_config.get_value("sec", "var1") == "value1_main"
except AssertionError as e:
raise SkipTest(
- 'Known failure -- included values are not in effect right away'
+ "Known failure -- included values are not in effect right away"
) from e
@with_rw_directory
def test_lock_reentry(self, rw_dir):
- fpl = osp.join(rw_dir, 'l')
+ fpl = osp.join(rw_dir, "l")
gcp = GitConfigParser(fpl, read_only=False)
with gcp as cw:
- cw.set_value('include', 'some_value', 'a')
+ cw.set_value("include", "some_value", "a")
# entering again locks the file again...
with gcp as cw:
- cw.set_value('include', 'some_other_value', 'b')
+ cw.set_value("include", "some_other_value", "b")
# ...so creating an additional config writer must fail due to exclusive access
with self.assertRaises(IOError):
GitConfigParser(fpl, read_only=False)
@@ -136,10 +141,12 @@ class TestBase(TestCase):
ev += " end\n"
ev += " File.open(%(%A), %(w)) {|f| f.write(b)}\n"
ev += " exit 1 if b.include?(%(<)*%L)'"
- self.assertEqual(config.get('merge "railsschema"', 'driver'), ev)
- self.assertEqual(config.get('alias', 'lg'),
- "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset'"
- " --abbrev-commit --date=relative")
+ self.assertEqual(config.get('merge "railsschema"', "driver"), ev)
+ self.assertEqual(
+ config.get("alias", "lg"),
+ "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset'"
+ " --abbrev-commit --date=relative",
+ )
self.assertEqual(len(config.sections()), 23)
def test_base(self):
@@ -186,47 +193,51 @@ class TestBase(TestCase):
@with_rw_directory
def test_config_include(self, rw_dir):
def write_test_value(cw, value):
- cw.set_value(value, 'value', value)
+ cw.set_value(value, "value", value)
+
# end
def check_test_value(cr, value):
- assert cr.get_value(value, 'value') == value
+ assert cr.get_value(value, "value") == value
+
# end
# PREPARE CONFIG FILE A
- fpa = osp.join(rw_dir, 'a')
+ fpa = osp.join(rw_dir, "a")
with GitConfigParser(fpa, read_only=False) as cw:
- write_test_value(cw, 'a')
-
- fpb = osp.join(rw_dir, 'b')
- fpc = osp.join(rw_dir, 'c')
- cw.set_value('include', 'relative_path_b', 'b')
- cw.set_value('include', 'doesntexist', 'foobar')
- cw.set_value('include', 'relative_cycle_a_a', 'a')
- cw.set_value('include', 'absolute_cycle_a_a', fpa)
+ write_test_value(cw, "a")
+
+ fpb = osp.join(rw_dir, "b")
+ fpc = osp.join(rw_dir, "c")
+ cw.set_value("include", "relative_path_b", "b")
+ cw.set_value("include", "doesntexist", "foobar")
+ cw.set_value("include", "relative_cycle_a_a", "a")
+ cw.set_value("include", "absolute_cycle_a_a", fpa)
assert osp.exists(fpa)
# PREPARE CONFIG FILE B
with GitConfigParser(fpb, read_only=False) as cw:
- write_test_value(cw, 'b')
- cw.set_value('include', 'relative_cycle_b_a', 'a')
- cw.set_value('include', 'absolute_cycle_b_a', fpa)
- cw.set_value('include', 'relative_path_c', 'c')
- cw.set_value('include', 'absolute_path_c', fpc)
+ write_test_value(cw, "b")
+ cw.set_value("include", "relative_cycle_b_a", "a")
+ cw.set_value("include", "absolute_cycle_b_a", fpa)
+ cw.set_value("include", "relative_path_c", "c")
+ cw.set_value("include", "absolute_path_c", fpc)
# PREPARE CONFIG FILE C
with GitConfigParser(fpc, read_only=False) as cw:
- write_test_value(cw, 'c')
+ write_test_value(cw, "c")
with GitConfigParser(fpa, read_only=True) as cr:
- for tv in ('a', 'b', 'c'):
+ for tv in ("a", "b", "c"):
check_test_value(cr, tv)
# end for each test to verify
- assert len(cr.items('include')) == 8, "Expected all include sections to be merged"
+ assert (
+ len(cr.items("include")) == 8
+ ), "Expected all include sections to be merged"
# test writable config writers - assure write-back doesn't involve includes
with GitConfigParser(fpa, read_only=False, merge_includes=True) as cw:
- tv = 'x'
+ tv = "x"
write_test_value(cw, tv)
with GitConfigParser(fpa, read_only=True) as cr:
@@ -252,7 +263,7 @@ class TestBase(TestCase):
# Initiate config files.
path1 = osp.join(rw_dir, "config1")
path2 = osp.join(rw_dir, "config2")
- template = "[includeIf \"{}:{}\"]\n path={}\n"
+ template = '[includeIf "{}:{}"]\n path={}\n'
with open(path1, "w") as stream:
stream.write(template.format("gitdir", git_dir, path2))
@@ -319,7 +330,7 @@ class TestBase(TestCase):
# Initiate config files.
path1 = osp.join(rw_dir, "config1")
path2 = osp.join(rw_dir, "config2")
- template = "[includeIf \"onbranch:{}\"]\n path={}\n"
+ template = '[includeIf "onbranch:{}"]\n path={}\n'
# Ensure that config is included is branch is correct.
with open(path1, "w") as stream:
@@ -356,14 +367,14 @@ class TestBase(TestCase):
# Ensure that config is ignored when active branch cannot be found.
with open(path1, "w") as stream:
- stream.write("[includeIf \"onbranch:foo\"]\n path=/path\n")
+ stream.write('[includeIf "onbranch:foo"]\n path=/path\n')
with GitConfigParser(path1, repo=repo) as config:
assert not config._has_includes()
assert config._included_paths() == []
def test_rename(self):
- file_obj = self._to_memcache(fixture_path('git_config'))
+ file_obj = self._to_memcache(fixture_path("git_config"))
with GitConfigParser(file_obj, read_only=False, merge_includes=False) as cw:
with self.assertRaises(ValueError):
cw.rename_section("doesntexist", "foo")
@@ -371,127 +382,161 @@ class TestBase(TestCase):
cw.rename_section("core", "include")
nn = "bee"
- assert cw.rename_section('core', nn) is cw
- assert not cw.has_section('core')
+ assert cw.rename_section("core", nn) is cw
+ assert not cw.has_section("core")
assert len(cw.items(nn)) == 4
def test_complex_aliases(self):
- file_obj = self._to_memcache(fixture_path('.gitconfig'))
+ file_obj = self._to_memcache(fixture_path(".gitconfig"))
with GitConfigParser(file_obj, read_only=False) as w_config:
- self.assertEqual(w_config.get('alias', 'rbi'), '"!g() { git rebase -i origin/${1:-master} ; } ; g"')
- self.assertEqual(file_obj.getvalue(), self._to_memcache(fixture_path('.gitconfig')).getvalue())
+ self.assertEqual(
+ w_config.get("alias", "rbi"),
+ '"!g() { git rebase -i origin/${1:-master} ; } ; g"',
+ )
+ self.assertEqual(
+ file_obj.getvalue(),
+ self._to_memcache(fixture_path(".gitconfig")).getvalue(),
+ )
def test_empty_config_value(self):
- cr = GitConfigParser(fixture_path('git_config_with_empty_value'), read_only=True)
+ cr = GitConfigParser(
+ fixture_path("git_config_with_empty_value"), read_only=True
+ )
- assert cr.get_value('core', 'filemode'), "Should read keys with values"
+ assert cr.get_value("core", "filemode"), "Should read keys with values"
with self.assertRaises(cp.NoOptionError):
- cr.get_value('color', 'ui')
+ cr.get_value("color", "ui")
def test_multiple_values(self):
- file_obj = self._to_memcache(fixture_path('git_config_multiple'))
+ file_obj = self._to_memcache(fixture_path("git_config_multiple"))
with GitConfigParser(file_obj, read_only=False) as cw:
- self.assertEqual(cw.get('section0', 'option0'), 'value0')
- self.assertEqual(cw.get_values('section0', 'option0'), ['value0'])
- self.assertEqual(cw.items('section0'), [('option0', 'value0')])
+ self.assertEqual(cw.get("section0", "option0"), "value0")
+ self.assertEqual(cw.get_values("section0", "option0"), ["value0"])
+ self.assertEqual(cw.items("section0"), [("option0", "value0")])
# Where there are multiple values, "get" returns the last.
- self.assertEqual(cw.get('section1', 'option1'), 'value1b')
- self.assertEqual(cw.get_values('section1', 'option1'),
- ['value1a', 'value1b'])
- self.assertEqual(cw.items('section1'),
- [('option1', 'value1b'),
- ('other_option1', 'other_value1')])
- self.assertEqual(cw.items_all('section1'),
- [('option1', ['value1a', 'value1b']),
- ('other_option1', ['other_value1'])])
+ self.assertEqual(cw.get("section1", "option1"), "value1b")
+ self.assertEqual(
+ cw.get_values("section1", "option1"), ["value1a", "value1b"]
+ )
+ self.assertEqual(
+ cw.items("section1"),
+ [("option1", "value1b"), ("other_option1", "other_value1")],
+ )
+ self.assertEqual(
+ cw.items_all("section1"),
+ [
+ ("option1", ["value1a", "value1b"]),
+ ("other_option1", ["other_value1"]),
+ ],
+ )
with self.assertRaises(KeyError):
- cw.get_values('section1', 'missing')
+ cw.get_values("section1", "missing")
- self.assertEqual(cw.get_values('section1', 'missing', 1), [1])
- self.assertEqual(cw.get_values('section1', 'missing', 's'), ['s'])
+ self.assertEqual(cw.get_values("section1", "missing", 1), [1])
+ self.assertEqual(cw.get_values("section1", "missing", "s"), ["s"])
def test_multiple_values_rename(self):
- file_obj = self._to_memcache(fixture_path('git_config_multiple'))
+ file_obj = self._to_memcache(fixture_path("git_config_multiple"))
with GitConfigParser(file_obj, read_only=False) as cw:
- cw.rename_section('section1', 'section2')
+ cw.rename_section("section1", "section2")
cw.write()
file_obj.seek(0)
cr = GitConfigParser(file_obj, read_only=True)
- self.assertEqual(cr.get_value('section2', 'option1'), 'value1b')
- self.assertEqual(cr.get_values('section2', 'option1'),
- ['value1a', 'value1b'])
- self.assertEqual(cr.items('section2'),
- [('option1', 'value1b'),
- ('other_option1', 'other_value1')])
- self.assertEqual(cr.items_all('section2'),
- [('option1', ['value1a', 'value1b']),
- ('other_option1', ['other_value1'])])
+ self.assertEqual(cr.get_value("section2", "option1"), "value1b")
+ self.assertEqual(
+ cr.get_values("section2", "option1"), ["value1a", "value1b"]
+ )
+ self.assertEqual(
+ cr.items("section2"),
+ [("option1", "value1b"), ("other_option1", "other_value1")],
+ )
+ self.assertEqual(
+ cr.items_all("section2"),
+ [
+ ("option1", ["value1a", "value1b"]),
+ ("other_option1", ["other_value1"]),
+ ],
+ )
def test_multiple_to_single(self):
- file_obj = self._to_memcache(fixture_path('git_config_multiple'))
+ file_obj = self._to_memcache(fixture_path("git_config_multiple"))
with GitConfigParser(file_obj, read_only=False) as cw:
- cw.set_value('section1', 'option1', 'value1c')
+ cw.set_value("section1", "option1", "value1c")
cw.write()
file_obj.seek(0)
cr = GitConfigParser(file_obj, read_only=True)
- self.assertEqual(cr.get_value('section1', 'option1'), 'value1c')
- self.assertEqual(cr.get_values('section1', 'option1'), ['value1c'])
- self.assertEqual(cr.items('section1'),
- [('option1', 'value1c'),
- ('other_option1', 'other_value1')])
- self.assertEqual(cr.items_all('section1'),
- [('option1', ['value1c']),
- ('other_option1', ['other_value1'])])
+ self.assertEqual(cr.get_value("section1", "option1"), "value1c")
+ self.assertEqual(cr.get_values("section1", "option1"), ["value1c"])
+ self.assertEqual(
+ cr.items("section1"),
+ [("option1", "value1c"), ("other_option1", "other_value1")],
+ )
+ self.assertEqual(
+ cr.items_all("section1"),
+ [("option1", ["value1c"]), ("other_option1", ["other_value1"])],
+ )
def test_single_to_multiple(self):
- file_obj = self._to_memcache(fixture_path('git_config_multiple'))
+ file_obj = self._to_memcache(fixture_path("git_config_multiple"))
with GitConfigParser(file_obj, read_only=False) as cw:
- cw.add_value('section1', 'other_option1', 'other_value1a')
+ cw.add_value("section1", "other_option1", "other_value1a")
cw.write()
file_obj.seek(0)
cr = GitConfigParser(file_obj, read_only=True)
- self.assertEqual(cr.get_value('section1', 'option1'), 'value1b')
- self.assertEqual(cr.get_values('section1', 'option1'),
- ['value1a', 'value1b'])
- self.assertEqual(cr.get_value('section1', 'other_option1'),
- 'other_value1a')
- self.assertEqual(cr.get_values('section1', 'other_option1'),
- ['other_value1', 'other_value1a'])
- self.assertEqual(cr.items('section1'),
- [('option1', 'value1b'),
- ('other_option1', 'other_value1a')])
+ self.assertEqual(cr.get_value("section1", "option1"), "value1b")
+ self.assertEqual(
+ cr.get_values("section1", "option1"), ["value1a", "value1b"]
+ )
+ self.assertEqual(cr.get_value("section1", "other_option1"), "other_value1a")
+ self.assertEqual(
+ cr.get_values("section1", "other_option1"),
+ ["other_value1", "other_value1a"],
+ )
self.assertEqual(
- cr.items_all('section1'),
- [('option1', ['value1a', 'value1b']),
- ('other_option1', ['other_value1', 'other_value1a'])])
+ cr.items("section1"),
+ [("option1", "value1b"), ("other_option1", "other_value1a")],
+ )
+ self.assertEqual(
+ cr.items_all("section1"),
+ [
+ ("option1", ["value1a", "value1b"]),
+ ("other_option1", ["other_value1", "other_value1a"]),
+ ],
+ )
def test_add_to_multiple(self):
- file_obj = self._to_memcache(fixture_path('git_config_multiple'))
+ file_obj = self._to_memcache(fixture_path("git_config_multiple"))
with GitConfigParser(file_obj, read_only=False) as cw:
- cw.add_value('section1', 'option1', 'value1c')
+ cw.add_value("section1", "option1", "value1c")
cw.write()
file_obj.seek(0)
cr = GitConfigParser(file_obj, read_only=True)
- self.assertEqual(cr.get_value('section1', 'option1'), 'value1c')
- self.assertEqual(cr.get_values('section1', 'option1'),
- ['value1a', 'value1b', 'value1c'])
- self.assertEqual(cr.items('section1'),
- [('option1', 'value1c'),
- ('other_option1', 'other_value1')])
- self.assertEqual(cr.items_all('section1'),
- [('option1', ['value1a', 'value1b', 'value1c']),
- ('other_option1', ['other_value1'])])
+ self.assertEqual(cr.get_value("section1", "option1"), "value1c")
+ self.assertEqual(
+ cr.get_values("section1", "option1"), ["value1a", "value1b", "value1c"]
+ )
+ self.assertEqual(
+ cr.items("section1"),
+ [("option1", "value1c"), ("other_option1", "other_value1")],
+ )
+ self.assertEqual(
+ cr.items_all("section1"),
+ [
+ ("option1", ["value1a", "value1b", "value1c"]),
+ ("other_option1", ["other_value1"]),
+ ],
+ )
def test_setlast(self):
# Test directly, not covered by higher-level tests.
omd = _OMD()
- omd.setlast('key', 'value1')
- self.assertEqual(omd['key'], 'value1')
- self.assertEqual(omd.getall('key'), ['value1'])
- omd.setlast('key', 'value2')
- self.assertEqual(omd['key'], 'value2')
- self.assertEqual(omd.getall('key'), ['value2'])
+ omd.setlast("key", "value1")
+ self.assertEqual(omd["key"], "value1")
+ self.assertEqual(omd.getall("key"), ["value1"])
+ omd.setlast("key", "value2")
+ self.assertEqual(omd["key"], "value2")
+ self.assertEqual(omd.getall("key"), ["value2"])
diff --git a/test/test_db.py b/test/test_db.py
index f9090fdd..228c70e7 100644
--- a/test/test_db.py
+++ b/test/test_db.py
@@ -12,9 +12,8 @@ import os.path as osp
class TestDB(TestBase):
-
def test_base(self):
- gdb = GitCmdObjectDB(osp.join(self.rorepo.git_dir, 'objects'), self.rorepo.git)
+ gdb = GitCmdObjectDB(osp.join(self.rorepo.git_dir, "objects"), self.rorepo.git)
# partial to complete - works with everything
hexsha = bin_to_hex(gdb.partial_to_complete_sha_hex("0.1.6"))
diff --git a/test/test_diff.py b/test/test_diff.py
index 92e27f5d..10f5d6db 100644
--- a/test/test_diff.py
+++ b/test/test_diff.py
@@ -28,18 +28,18 @@ import os.path as osp
def to_raw(input):
- return input.replace(b'\t', b'\x00')
+ return input.replace(b"\t", b"\x00")
@ddt.ddt
class TestDiff(TestBase):
-
def setUp(self):
self.repo_dir = tempfile.mkdtemp()
self.submodule_dir = tempfile.mkdtemp()
def tearDown(self):
import gc
+
gc.collect()
shutil.rmtree(self.repo_dir)
shutil.rmtree(self.submodule_dir)
@@ -53,9 +53,9 @@ class TestDiff(TestBase):
assert isinstance(diff.b_mode, int)
if diff.a_blob:
- assert not diff.a_blob.path.endswith('\n')
+ assert not diff.a_blob.path.endswith("\n")
if diff.b_blob:
- assert not diff.b_blob.path.endswith('\n')
+ assert not diff.b_blob.path.endswith("\n")
# END for each diff
return diffs
@@ -63,38 +63,47 @@ class TestDiff(TestBase):
def test_diff_with_staged_file(self, rw_dir):
# SETUP INDEX WITH MULTIPLE STAGES
r = Repo.init(rw_dir)
- fp = osp.join(rw_dir, 'hello.txt')
- with open(fp, 'w') as fs:
+ fp = osp.join(rw_dir, "hello.txt")
+ with open(fp, "w") as fs:
fs.write("hello world")
r.git.add(Git.polish_url(fp))
r.git.commit(message="init")
- with open(fp, 'w') as fs:
+ with open(fp, "w") as fs:
fs.write("Hola Mundo")
r.git.add(Git.polish_url(fp))
- self.assertEqual(len(r.index.diff("HEAD", create_patch=True)), 1,
- "create_patch should generate patch of diff to HEAD")
+ self.assertEqual(
+ len(r.index.diff("HEAD", create_patch=True)),
+ 1,
+ "create_patch should generate patch of diff to HEAD",
+ )
r.git.commit(message="change on master")
- self.assertEqual(len(r.index.diff("HEAD", create_patch=True)), 0,
- "create_patch should generate no patch, already on HEAD")
-
- r.git.checkout('HEAD~1', b='topic')
- with open(fp, 'w') as fs:
+ self.assertEqual(
+ len(r.index.diff("HEAD", create_patch=True)),
+ 0,
+ "create_patch should generate no patch, already on HEAD",
+ )
+
+ r.git.checkout("HEAD~1", b="topic")
+ with open(fp, "w") as fs:
fs.write("Hallo Welt")
r.git.commit(all=True, message="change on topic branch")
# there must be a merge-conflict
with self.assertRaises(GitCommandError):
- r.git.cherry_pick('master')
+ r.git.cherry_pick("master")
# Now do the actual testing - this should just work
self.assertEqual(len(r.index.diff(None)), 2)
- self.assertEqual(len(r.index.diff(None, create_patch=True)), 0,
- "This should work, but doesn't right now ... it's OK")
+ self.assertEqual(
+ len(r.index.diff(None, create_patch=True)),
+ 0,
+ "This should work, but doesn't right now ... it's OK",
+ )
def test_list_from_string_new_mode(self):
- output = StringProcessAdapter(fixture('diff_new_mode'))
+ output = StringProcessAdapter(fixture("diff_new_mode"))
diffs = Diff._index_from_patch_format(self.rorepo, output)
self._assert_diff_format(diffs)
@@ -102,7 +111,7 @@ class TestDiff(TestBase):
self.assertEqual(8, len(diffs[0].diff.splitlines()))
def test_diff_with_rename(self):
- output = StringProcessAdapter(fixture('diff_rename'))
+ output = StringProcessAdapter(fixture("diff_rename"))
diffs = Diff._index_from_patch_format(self.rorepo, output)
self._assert_diff_format(diffs)
@@ -111,26 +120,26 @@ class TestDiff(TestBase):
diff = diffs[0]
self.assertTrue(diff.renamed_file)
self.assertTrue(diff.renamed)
- self.assertEqual(diff.rename_from, 'Jérôme')
- self.assertEqual(diff.rename_to, 'müller')
- self.assertEqual(diff.raw_rename_from, b'J\xc3\xa9r\xc3\xb4me')
- self.assertEqual(diff.raw_rename_to, b'm\xc3\xbcller')
+ self.assertEqual(diff.rename_from, "Jérôme")
+ self.assertEqual(diff.rename_to, "müller")
+ self.assertEqual(diff.raw_rename_from, b"J\xc3\xa9r\xc3\xb4me")
+ self.assertEqual(diff.raw_rename_to, b"m\xc3\xbcller")
assert isinstance(str(diff), str)
- output = StringProcessAdapter(to_raw(fixture('diff_rename_raw')))
+ output = StringProcessAdapter(to_raw(fixture("diff_rename_raw")))
diffs = Diff._index_from_raw_format(self.rorepo, output)
self.assertEqual(len(diffs), 1)
diff = diffs[0]
self.assertIsNotNone(diff.renamed_file)
self.assertIsNotNone(diff.renamed)
- self.assertEqual(diff.rename_from, 'this')
- self.assertEqual(diff.rename_to, 'that')
- self.assertEqual(diff.change_type, 'R')
+ self.assertEqual(diff.rename_from, "this")
+ self.assertEqual(diff.rename_to, "that")
+ self.assertEqual(diff.change_type, "R")
self.assertEqual(diff.score, 100)
- self.assertEqual(len(list(diffs.iter_change_type('R'))), 1)
+ self.assertEqual(len(list(diffs.iter_change_type("R"))), 1)
def test_diff_with_copied_file(self):
- output = StringProcessAdapter(fixture('diff_copied_mode'))
+ output = StringProcessAdapter(fixture("diff_copied_mode"))
diffs = Diff._index_from_patch_format(self.rorepo, output)
self._assert_diff_format(diffs)
@@ -138,146 +147,170 @@ class TestDiff(TestBase):
diff = diffs[0]
self.assertTrue(diff.copied_file)
- self.assertTrue(diff.a_path, 'test1.txt')
- self.assertTrue(diff.b_path, 'test2.txt')
+ self.assertTrue(diff.a_path, "test1.txt")
+ self.assertTrue(diff.b_path, "test2.txt")
assert isinstance(str(diff), str)
- output = StringProcessAdapter(to_raw(fixture('diff_copied_mode_raw')))
+ output = StringProcessAdapter(to_raw(fixture("diff_copied_mode_raw")))
diffs = Diff._index_from_raw_format(self.rorepo, output)
self.assertEqual(len(diffs), 1)
diff = diffs[0]
- self.assertEqual(diff.change_type, 'C')
+ self.assertEqual(diff.change_type, "C")
self.assertEqual(diff.score, 100)
- self.assertEqual(diff.a_path, 'test1.txt')
- self.assertEqual(diff.b_path, 'test2.txt')
- self.assertEqual(len(list(diffs.iter_change_type('C'))), 1)
+ self.assertEqual(diff.a_path, "test1.txt")
+ self.assertEqual(diff.b_path, "test2.txt")
+ self.assertEqual(len(list(diffs.iter_change_type("C"))), 1)
def test_diff_with_change_in_type(self):
- output = StringProcessAdapter(fixture('diff_change_in_type'))
+ output = StringProcessAdapter(fixture("diff_change_in_type"))
diffs = Diff._index_from_patch_format(self.rorepo, output)
self._assert_diff_format(diffs)
self.assertEqual(2, len(diffs))
diff = diffs[0]
self.assertIsNotNone(diff.deleted_file)
- self.assertEqual(diff.a_path, 'this')
- self.assertEqual(diff.b_path, 'this')
+ self.assertEqual(diff.a_path, "this")
+ self.assertEqual(diff.b_path, "this")
assert isinstance(str(diff), str)
diff = diffs[1]
self.assertEqual(diff.a_path, None)
- self.assertEqual(diff.b_path, 'this')
+ self.assertEqual(diff.b_path, "this")
self.assertIsNotNone(diff.new_file)
assert isinstance(str(diff), str)
- output = StringProcessAdapter(to_raw(fixture('diff_change_in_type_raw')))
+ output = StringProcessAdapter(to_raw(fixture("diff_change_in_type_raw")))
diffs = Diff._index_from_raw_format(self.rorepo, output)
self.assertEqual(len(diffs), 1)
diff = diffs[0]
self.assertEqual(diff.rename_from, None)
self.assertEqual(diff.rename_to, None)
- self.assertEqual(diff.change_type, 'T')
- self.assertEqual(len(list(diffs.iter_change_type('T'))), 1)
+ self.assertEqual(diff.change_type, "T")
+ self.assertEqual(len(list(diffs.iter_change_type("T"))), 1)
def test_diff_of_modified_files_not_added_to_the_index(self):
- output = StringProcessAdapter(to_raw(fixture('diff_abbrev-40_full-index_M_raw_no-color')))
+ output = StringProcessAdapter(
+ to_raw(fixture("diff_abbrev-40_full-index_M_raw_no-color"))
+ )
diffs = Diff._index_from_raw_format(self.rorepo, output)
- self.assertEqual(len(diffs), 1, 'one modification')
- self.assertEqual(len(list(diffs.iter_change_type('M'))), 1, 'one modification')
- self.assertEqual(diffs[0].change_type, 'M')
- self.assertIsNone(diffs[0].b_blob,)
+ self.assertEqual(len(diffs), 1, "one modification")
+ self.assertEqual(len(list(diffs.iter_change_type("M"))), 1, "one modification")
+ self.assertEqual(diffs[0].change_type, "M")
+ self.assertIsNone(
+ diffs[0].b_blob,
+ )
@ddt.data(
- (Diff._index_from_patch_format, 'diff_patch_binary'),
- (Diff._index_from_raw_format, 'diff_raw_binary')
+ (Diff._index_from_patch_format, "diff_patch_binary"),
+ (Diff._index_from_raw_format, "diff_raw_binary"),
)
def test_binary_diff(self, case):
method, file_name = case
res = method(None, StringProcessAdapter(fixture(file_name)))
self.assertEqual(len(res), 1)
- self.assertEqual(len(list(res.iter_change_type('M'))), 1)
+ self.assertEqual(len(list(res.iter_change_type("M"))), 1)
if res[0].diff:
- self.assertEqual(res[0].diff,
- b"Binary files a/rps and b/rps differ\n",
- "in patch mode, we get a diff text")
+ self.assertEqual(
+ res[0].diff,
+ b"Binary files a/rps and b/rps differ\n",
+ "in patch mode, we get a diff text",
+ )
self.assertIsNotNone(str(res[0]), "This call should just work")
def test_diff_index(self):
- output = StringProcessAdapter(fixture('diff_index_patch'))
+ output = StringProcessAdapter(fixture("diff_index_patch"))
res = Diff._index_from_patch_format(None, output)
self.assertEqual(len(res), 6)
for dr in res:
- self.assertTrue(dr.diff.startswith(b'@@'), dr)
- self.assertIsNotNone(str(dr), "Diff to string conversion should be possible")
+ self.assertTrue(dr.diff.startswith(b"@@"), dr)
+ self.assertIsNotNone(
+ str(dr), "Diff to string conversion should be possible"
+ )
# end for each diff
dr = res[3]
assert dr.diff.endswith(b"+Binary files a/rps and b/rps differ\n")
def test_diff_index_raw_format(self):
- output = StringProcessAdapter(fixture('diff_index_raw'))
+ output = StringProcessAdapter(fixture("diff_index_raw"))
res = Diff._index_from_raw_format(None, output)
self.assertIsNotNone(res[0].deleted_file)
- self.assertIsNone(res[0].b_path,)
+ self.assertIsNone(
+ res[0].b_path,
+ )
- @unittest.skip("This currently fails and would need someone to improve diff parsing")
+ @unittest.skip(
+ "This currently fails and would need someone to improve diff parsing"
+ )
def test_diff_file_with_colon(self):
- output = fixture('diff_file_with_colon')
+ output = fixture("diff_file_with_colon")
res = []
Diff._handle_diff_line(output, None, res)
def test_diff_initial_commit(self):
- initial_commit = self.rorepo.commit('33ebe7acec14b25c5f84f35a664803fcab2f7781')
+ initial_commit = self.rorepo.commit("33ebe7acec14b25c5f84f35a664803fcab2f7781")
# Without creating a patch...
diff_index = initial_commit.diff(NULL_TREE)
- self.assertEqual(diff_index[0].b_path, 'CHANGES')
+ self.assertEqual(diff_index[0].b_path, "CHANGES")
self.assertIsNotNone(diff_index[0].new_file)
- self.assertEqual(diff_index[0].diff, '')
+ self.assertEqual(diff_index[0].diff, "")
# ...and with creating a patch
diff_index = initial_commit.diff(NULL_TREE, create_patch=True)
self.assertIsNone(diff_index[0].a_path, repr(diff_index[0].a_path))
- self.assertEqual(diff_index[0].b_path, 'CHANGES', repr(diff_index[0].b_path))
+ self.assertEqual(diff_index[0].b_path, "CHANGES", repr(diff_index[0].b_path))
self.assertIsNotNone(diff_index[0].new_file)
- self.assertEqual(diff_index[0].diff, fixture('diff_initial'))
+ self.assertEqual(diff_index[0].diff, fixture("diff_initial"))
def test_diff_unsafe_paths(self):
- output = StringProcessAdapter(fixture('diff_patch_unsafe_paths'))
+ output = StringProcessAdapter(fixture("diff_patch_unsafe_paths"))
res = Diff._index_from_patch_format(None, output)
# The "Additions"
- self.assertEqual(res[0].b_path, 'path/ starting with a space')
+ self.assertEqual(res[0].b_path, "path/ starting with a space")
self.assertEqual(res[1].b_path, 'path/"with-quotes"')
self.assertEqual(res[2].b_path, "path/'with-single-quotes'")
- self.assertEqual(res[3].b_path, 'path/ending in a space ')
- self.assertEqual(res[4].b_path, 'path/with\ttab')
- self.assertEqual(res[5].b_path, 'path/with\nnewline')
- self.assertEqual(res[6].b_path, 'path/with spaces')
- self.assertEqual(res[7].b_path, 'path/with-question-mark?')
- self.assertEqual(res[8].b_path, 'path/¯\\_(ツ)_|¯')
- self.assertEqual(res[9].b_path, 'path/💩.txt')
- self.assertEqual(res[9].b_rawpath, b'path/\xf0\x9f\x92\xa9.txt')
- self.assertEqual(res[10].b_path, 'path/�-invalid-unicode-path.txt')
- self.assertEqual(res[10].b_rawpath, b'path/\x80-invalid-unicode-path.txt')
+ self.assertEqual(res[3].b_path, "path/ending in a space ")
+ self.assertEqual(res[4].b_path, "path/with\ttab")
+ self.assertEqual(res[5].b_path, "path/with\nnewline")
+ self.assertEqual(res[6].b_path, "path/with spaces")
+ self.assertEqual(res[7].b_path, "path/with-question-mark?")
+ self.assertEqual(res[8].b_path, "path/¯\\_(ツ)_|¯")
+ self.assertEqual(res[9].b_path, "path/💩.txt")
+ self.assertEqual(res[9].b_rawpath, b"path/\xf0\x9f\x92\xa9.txt")
+ self.assertEqual(res[10].b_path, "path/�-invalid-unicode-path.txt")
+ self.assertEqual(res[10].b_rawpath, b"path/\x80-invalid-unicode-path.txt")
# The "Moves"
# NOTE: The path prefixes a/ and b/ here are legit! We're actually
# verifying that it's not "a/a/" that shows up, see the fixture data.
- self.assertEqual(res[11].a_path, 'a/with spaces') # NOTE: path a/ here legit!
- self.assertEqual(res[11].b_path, 'b/with some spaces') # NOTE: path b/ here legit!
- self.assertEqual(res[12].a_path, 'a/ending in a space ')
- self.assertEqual(res[12].b_path, 'b/ending with space ')
+ self.assertEqual(res[11].a_path, "a/with spaces") # NOTE: path a/ here legit!
+ self.assertEqual(
+ res[11].b_path, "b/with some spaces"
+ ) # NOTE: path b/ here legit!
+ self.assertEqual(res[12].a_path, "a/ending in a space ")
+ self.assertEqual(res[12].b_path, "b/ending with space ")
self.assertEqual(res[13].a_path, 'a/"with-quotes"')
self.assertEqual(res[13].b_path, 'b/"with even more quotes"')
def test_diff_patch_format(self):
# test all of the 'old' format diffs for completeness - it should at least
# be able to deal with it
- fixtures = ("diff_2", "diff_2f", "diff_f", "diff_i", "diff_mode_only",
- "diff_new_mode", "diff_numstat", "diff_p", "diff_rename",
- "diff_tree_numstat_root", "diff_patch_unsafe_paths")
+ fixtures = (
+ "diff_2",
+ "diff_2f",
+ "diff_f",
+ "diff_i",
+ "diff_mode_only",
+ "diff_new_mode",
+ "diff_numstat",
+ "diff_p",
+ "diff_rename",
+ "diff_tree_numstat_root",
+ "diff_patch_unsafe_paths",
+ )
for fixture_name in fixtures:
diff_proc = StringProcessAdapter(fixture(fixture_name))
@@ -285,10 +318,12 @@ class TestDiff(TestBase):
# END for each fixture
def test_diff_with_spaces(self):
- data = StringProcessAdapter(fixture('diff_file_with_spaces'))
+ data = StringProcessAdapter(fixture("diff_file_with_spaces"))
diff_index = Diff._index_from_patch_format(self.rorepo, data)
self.assertIsNone(diff_index[0].a_path, repr(diff_index[0].a_path))
- self.assertEqual(diff_index[0].b_path, 'file with spaces', repr(diff_index[0].b_path))
+ self.assertEqual(
+ diff_index[0].b_path, "file with spaces", repr(diff_index[0].b_path)
+ )
def test_diff_submodule(self):
"""Test that diff is able to correctly diff commits that cover submodule changes"""
@@ -303,13 +338,13 @@ class TestDiff(TestBase):
repo = Repo.init(self.repo_dir)
with open(self.repo_dir + "/test", "w") as foo_test:
foo_test.write("")
- repo.index.add(['test'])
+ repo.index.add(["test"])
Submodule.add(repo, "subtest", "sub", url="file://" + self.submodule_dir)
repo.index.commit("first commit")
- repo.create_tag('1')
+ repo.create_tag("1")
# Add a commit to the submodule
- submodule = repo.submodule('subtest')
+ submodule = repo.submodule("subtest")
with open(self.repo_dir + "/sub/subfile", "w") as foo_sub_subfile:
foo_sub_subfile.write("blub")
submodule.module().index.add(["subfile"])
@@ -319,9 +354,9 @@ class TestDiff(TestBase):
# Commit submodule updates in parent repo
repo.index.add([submodule])
repo.index.commit("submodule changed")
- repo.create_tag('2')
+ repo.create_tag("2")
- diff = repo.commit('1').diff(repo.commit('2'))[0]
+ diff = repo.commit("1").diff(repo.commit("2"))[0]
# If diff is unable to find the commit hashes (looks in wrong repo) the *_blob.size
# property will be a string containing exception text, an int indicates success
self.assertIsInstance(diff.a_blob.size, int)
@@ -330,7 +365,7 @@ class TestDiff(TestBase):
def test_diff_interface(self):
# test a few variations of the main diff routine
assertion_map = {}
- for i, commit in enumerate(self.rorepo.iter_commits('0.1.6', max_count=2)):
+ for i, commit in enumerate(self.rorepo.iter_commits("0.1.6", max_count=2)):
diff_item = commit
if i % 2 == 0:
diff_item = commit.tree
@@ -339,15 +374,19 @@ class TestDiff(TestBase):
for other in (None, NULL_TREE, commit.Index, commit.parents[0]):
for paths in (None, "CHANGES", ("CHANGES", "lib")):
for create_patch in range(2):
- diff_index = diff_item.diff(other=other, paths=paths, create_patch=create_patch)
+ diff_index = diff_item.diff(
+ other=other, paths=paths, create_patch=create_patch
+ )
assert isinstance(diff_index, DiffIndex)
if diff_index:
self._assert_diff_format(diff_index)
for ct in DiffIndex.change_type:
- key = 'ct_%s' % ct
+ key = "ct_%s" % ct
assertion_map.setdefault(key, 0)
- assertion_map[key] = assertion_map[key] + len(list(diff_index.iter_change_type(ct)))
+ assertion_map[key] = assertion_map[key] + len(
+ list(diff_index.iter_change_type(ct))
+ )
# END for each changetype
# check entries
@@ -359,7 +398,10 @@ class TestDiff(TestBase):
self.assertFalse(diff_index[0] != diff_index[0])
for dr in diff_index:
- self.assertIsNotNone(str(dr), "Diff to string conversion should be possible")
+ self.assertIsNotNone(
+ str(dr),
+ "Diff to string conversion should be possible",
+ )
# END diff index checking
# END for each patch option
# END for each path option
diff --git a/test/test_docs.py b/test/test_docs.py
index 08fc8439..b6a0ed31 100644
--- a/test/test_docs.py
+++ b/test/test_docs.py
@@ -13,9 +13,9 @@ import os.path
class Tutorials(TestBase):
-
def tearDown(self):
import gc
+
gc.collect()
# @skipIf(HIDE_WINDOWS_KNOWN_ERRORS, ## ACTUALLY skipped by `git.submodule.base#L869`.
@@ -34,71 +34,102 @@ class Tutorials(TestBase):
# ![1-test_init_repo_object]
# [2-test_init_repo_object]
- bare_repo = Repo.init(os.path.join(rw_dir, 'bare-repo'), bare=True)
+ bare_repo = Repo.init(os.path.join(rw_dir, "bare-repo"), bare=True)
assert bare_repo.bare
# ![2-test_init_repo_object]
# [3-test_init_repo_object]
- repo.config_reader() # get a config reader for read-only access
- with repo.config_writer(): # get a config writer to change configuration
- pass # call release() to be sure changes are written and locks are released
+ repo.config_reader() # get a config reader for read-only access
+ with repo.config_writer(): # get a config writer to change configuration
+ pass # call release() to be sure changes are written and locks are released
# ![3-test_init_repo_object]
# [4-test_init_repo_object]
assert not bare_repo.is_dirty() # check the dirty state
- repo.untracked_files # retrieve a list of untracked files
+ repo.untracked_files # retrieve a list of untracked files
# ['my_untracked_file']
# ![4-test_init_repo_object]
# [5-test_init_repo_object]
- cloned_repo = repo.clone(os.path.join(rw_dir, 'to/this/path'))
- assert cloned_repo.__class__ is Repo # clone an existing repository
- assert Repo.init(os.path.join(rw_dir, 'path/for/new/repo')).__class__ is Repo
+ cloned_repo = repo.clone(os.path.join(rw_dir, "to/this/path"))
+ assert cloned_repo.__class__ is Repo # clone an existing repository
+ assert Repo.init(os.path.join(rw_dir, "path/for/new/repo")).__class__ is Repo
# ![5-test_init_repo_object]
# [6-test_init_repo_object]
- with open(os.path.join(rw_dir, 'repo.tar'), 'wb') as fp:
+ with open(os.path.join(rw_dir, "repo.tar"), "wb") as fp:
repo.archive(fp)
# ![6-test_init_repo_object]
# repository paths
# [7-test_init_repo_object]
- assert os.path.isdir(cloned_repo.working_tree_dir) # directory with your work files
- assert cloned_repo.git_dir.startswith(cloned_repo.working_tree_dir) # directory containing the git repository
- assert bare_repo.working_tree_dir is None # bare repositories have no working tree
+ assert os.path.isdir(
+ cloned_repo.working_tree_dir
+ ) # directory with your work files
+ assert cloned_repo.git_dir.startswith(
+ cloned_repo.working_tree_dir
+ ) # directory containing the git repository
+ assert (
+ bare_repo.working_tree_dir is None
+ ) # bare repositories have no working tree
# ![7-test_init_repo_object]
# heads, tags and references
# heads are branches in git-speak
# [8-test_init_repo_object]
- self.assertEqual(repo.head.ref, repo.heads.master, # head is a sym-ref pointing to master
- "It's ok if TC not running from `master`.")
- self.assertEqual(repo.tags['0.3.5'], repo.tag('refs/tags/0.3.5')) # you can access tags in various ways too
- self.assertEqual(repo.refs.master, repo.heads['master']) # .refs provides all refs, ie heads ...
-
- if 'TRAVIS' not in os.environ:
- self.assertEqual(repo.refs['origin/master'], repo.remotes.origin.refs.master) # ... remotes ...
- self.assertEqual(repo.refs['0.3.5'], repo.tags['0.3.5']) # ... and tags
+ self.assertEqual(
+ repo.head.ref,
+ repo.heads.master, # head is a sym-ref pointing to master
+ "It's ok if TC not running from `master`.",
+ )
+ self.assertEqual(
+ repo.tags["0.3.5"], repo.tag("refs/tags/0.3.5")
+ ) # you can access tags in various ways too
+ self.assertEqual(
+ repo.refs.master, repo.heads["master"]
+ ) # .refs provides all refs, ie heads ...
+
+ if "TRAVIS" not in os.environ:
+ self.assertEqual(
+ repo.refs["origin/master"], repo.remotes.origin.refs.master
+ ) # ... remotes ...
+ self.assertEqual(repo.refs["0.3.5"], repo.tags["0.3.5"]) # ... and tags
# ![8-test_init_repo_object]
# create a new head/branch
# [9-test_init_repo_object]
- new_branch = cloned_repo.create_head('feature') # create a new branch ...
- assert cloned_repo.active_branch != new_branch # which wasn't checked out yet ...
- self.assertEqual(new_branch.commit, cloned_repo.active_branch.commit) # pointing to the checked-out commit
+ new_branch = cloned_repo.create_head("feature") # create a new branch ...
+ assert (
+ cloned_repo.active_branch != new_branch
+ ) # which wasn't checked out yet ...
+ self.assertEqual(
+ new_branch.commit, cloned_repo.active_branch.commit
+ ) # pointing to the checked-out commit
# It's easy to let a branch point to the previous commit, without affecting anything else
# Each reference provides access to the git object it points to, usually commits
- assert new_branch.set_commit('HEAD~1').commit == cloned_repo.active_branch.commit.parents[0]
+ assert (
+ new_branch.set_commit("HEAD~1").commit
+ == cloned_repo.active_branch.commit.parents[0]
+ )
# ![9-test_init_repo_object]
# create a new tag reference
# [10-test_init_repo_object]
- past = cloned_repo.create_tag('past', ref=new_branch,
- message="This is a tag-object pointing to %s" % new_branch.name)
- self.assertEqual(past.commit, new_branch.commit) # the tag points to the specified commit
- assert past.tag.message.startswith("This is") # and its object carries the message provided
-
- now = cloned_repo.create_tag('now') # This is a tag-reference. It may not carry meta-data
+ past = cloned_repo.create_tag(
+ "past",
+ ref=new_branch,
+ message="This is a tag-object pointing to %s" % new_branch.name,
+ )
+ self.assertEqual(
+ past.commit, new_branch.commit
+ ) # the tag points to the specified commit
+ assert past.tag.message.startswith(
+ "This is"
+ ) # and its object carries the message provided
+
+ now = cloned_repo.create_tag(
+ "now"
+ ) # This is a tag-reference. It may not carry meta-data
assert now.tag is None
# ![10-test_init_repo_object]
@@ -106,17 +137,26 @@ class Tutorials(TestBase):
# [11-test_init_repo_object]
assert now.commit.message != past.commit.message
# You can read objects directly through binary streams, no working tree required
- assert (now.commit.tree / 'VERSION').data_stream.read().decode('ascii').startswith('3')
+ assert (
+ (now.commit.tree / "VERSION")
+ .data_stream.read()
+ .decode("ascii")
+ .startswith("3")
+ )
# You can traverse trees as well to handle all contained files of a particular commit
file_count = 0
tree_count = 0
tree = past.commit.tree
for item in tree.traverse():
- file_count += item.type == 'blob'
- tree_count += item.type == 'tree'
- assert file_count and tree_count # we have accumulated all directories and files
- self.assertEqual(len(tree.blobs) + len(tree.trees), len(tree)) # a tree is iterable on its children
+ file_count += item.type == "blob"
+ tree_count += item.type == "tree"
+ assert (
+ file_count and tree_count
+ ) # we have accumulated all directories and files
+ self.assertEqual(
+ len(tree.blobs) + len(tree.trees), len(tree)
+ ) # a tree is iterable on its children
# ![11-test_init_repo_object]
# remotes allow handling push, pull and fetch operations
@@ -124,19 +164,28 @@ class Tutorials(TestBase):
from git import RemoteProgress
class MyProgressPrinter(RemoteProgress):
- def update(self, op_code, cur_count, max_count=None, message=''):
- print(op_code, cur_count, max_count, cur_count / (max_count or 100.0), message or "NO MESSAGE")
+ def update(self, op_code, cur_count, max_count=None, message=""):
+ print(
+ op_code,
+ cur_count,
+ max_count,
+ cur_count / (max_count or 100.0),
+ message or "NO MESSAGE",
+ )
+
# end
- self.assertEqual(len(cloned_repo.remotes), 1) # we have been cloned, so should be one remote
- self.assertEqual(len(bare_repo.remotes), 0) # this one was just initialized
- origin = bare_repo.create_remote('origin', url=cloned_repo.working_tree_dir)
+ self.assertEqual(
+ len(cloned_repo.remotes), 1
+ ) # we have been cloned, so should be one remote
+ self.assertEqual(len(bare_repo.remotes), 0) # this one was just initialized
+ origin = bare_repo.create_remote("origin", url=cloned_repo.working_tree_dir)
assert origin.exists()
for fetch_info in origin.fetch(progress=MyProgressPrinter()):
print("Updated %s to %s" % (fetch_info.ref, fetch_info.commit))
# create a local branch at the latest fetched master. We specify the name statically, but you have all
# information to do it programmatically as well.
- bare_master = bare_repo.create_head('master', origin.refs.master)
+ bare_master = bare_repo.create_head("master", origin.refs.master)
bare_repo.head.set_reference(bare_master)
assert not bare_repo.delete_remote(origin).exists()
# push and pull behave very similarly
@@ -144,28 +193,42 @@ class Tutorials(TestBase):
# index
# [13-test_init_repo_object]
- self.assertEqual(new_branch.checkout(), cloned_repo.active_branch) # checking out branch adjusts the wtree
- self.assertEqual(new_branch.commit, past.commit) # Now the past is checked out
-
- new_file_path = os.path.join(cloned_repo.working_tree_dir, 'my-new-file')
- open(new_file_path, 'wb').close() # create new file in working tree
- cloned_repo.index.add([new_file_path]) # add it to the index
+ self.assertEqual(
+ new_branch.checkout(), cloned_repo.active_branch
+ ) # checking out branch adjusts the wtree
+ self.assertEqual(new_branch.commit, past.commit) # Now the past is checked out
+
+ new_file_path = os.path.join(cloned_repo.working_tree_dir, "my-new-file")
+ open(new_file_path, "wb").close() # create new file in working tree
+ cloned_repo.index.add([new_file_path]) # add it to the index
# Commit the changes to deviate masters history
cloned_repo.index.commit("Added a new file in the past - for later merege")
# prepare a merge
- master = cloned_repo.heads.master # right-hand side is ahead of us, in the future
- merge_base = cloned_repo.merge_base(new_branch, master) # allows for a three-way merge
- cloned_repo.index.merge_tree(master, base=merge_base) # write the merge result into index
- cloned_repo.index.commit("Merged past and now into future ;)",
- parent_commits=(new_branch.commit, master.commit))
+ master = (
+ cloned_repo.heads.master
+ ) # right-hand side is ahead of us, in the future
+ merge_base = cloned_repo.merge_base(
+ new_branch, master
+ ) # allows for a three-way merge
+ cloned_repo.index.merge_tree(
+ master, base=merge_base
+ ) # write the merge result into index
+ cloned_repo.index.commit(
+ "Merged past and now into future ;)",
+ parent_commits=(new_branch.commit, master.commit),
+ )
# now new_branch is ahead of master, which probably should be checked out and reset softly.
# note that all these operations didn't touch the working tree, as we managed it ourselves.
# This definitely requires you to know what you are doing :) !
- assert os.path.basename(new_file_path) in new_branch.commit.tree # new file is now in tree
- master.commit = new_branch.commit # let master point to most recent commit
- cloned_repo.head.reference = master # we adjusted just the reference, not the working tree or index
+ assert (
+ os.path.basename(new_file_path) in new_branch.commit.tree
+ ) # new file is now in tree
+ master.commit = new_branch.commit # let master point to most recent commit
+ cloned_repo.head.reference = (
+ master # we adjusted just the reference, not the working tree or index
+ )
# ![13-test_init_repo_object]
# submodules
@@ -175,110 +238,135 @@ class Tutorials(TestBase):
# As our GitPython repository has submodules already that point to GitHub, make sure we don't
# interact with them
for sm in cloned_repo.submodules:
- assert not sm.remove().exists() # after removal, the sm doesn't exist anymore
- sm = cloned_repo.create_submodule('mysubrepo', 'path/to/subrepo', url=bare_repo.git_dir, branch='master')
+ assert (
+ not sm.remove().exists()
+ ) # after removal, the sm doesn't exist anymore
+ sm = cloned_repo.create_submodule(
+ "mysubrepo", "path/to/subrepo", url=bare_repo.git_dir, branch="master"
+ )
# .gitmodules was written and added to the index, which is now being committed
cloned_repo.index.commit("Added submodule")
- assert sm.exists() and sm.module_exists() # this submodule is defintely available
- sm.remove(module=True, configuration=False) # remove the working tree
- assert sm.exists() and not sm.module_exists() # the submodule itself is still available
+ assert (
+ sm.exists() and sm.module_exists()
+ ) # this submodule is defintely available
+ sm.remove(module=True, configuration=False) # remove the working tree
+ assert (
+ sm.exists() and not sm.module_exists()
+ ) # the submodule itself is still available
# update all submodules, non-recursively to save time, this method is very powerful, go have a look
cloned_repo.submodule_update(recursive=False)
- assert sm.module_exists() # The submodules working tree was checked out by update
+ assert (
+ sm.module_exists()
+ ) # The submodules working tree was checked out by update
# ![14-test_init_repo_object]
@with_rw_directory
def test_references_and_objects(self, rw_dir):
# [1-test_references_and_objects]
import git
- repo = git.Repo.clone_from(self._small_repo_url(), os.path.join(rw_dir, 'repo'), branch='master')
+
+ repo = git.Repo.clone_from(
+ self._small_repo_url(), os.path.join(rw_dir, "repo"), branch="master"
+ )
heads = repo.heads
- master = heads.master # lists can be accessed by name for convenience
- master.commit # the commit pointed to by head called master
- master.rename('new_name') # rename heads
- master.rename('master')
+ master = heads.master # lists can be accessed by name for convenience
+ master.commit # the commit pointed to by head called master
+ master.rename("new_name") # rename heads
+ master.rename("master")
# ![1-test_references_and_objects]
# [2-test_references_and_objects]
tags = repo.tags
tagref = tags[0]
- tagref.tag # tags may have tag objects carrying additional information
- tagref.commit # but they always point to commits
- repo.delete_tag(tagref) # delete or
- repo.create_tag("my_tag") # create tags using the repo for convenience
+ tagref.tag # tags may have tag objects carrying additional information
+ tagref.commit # but they always point to commits
+ repo.delete_tag(tagref) # delete or
+ repo.create_tag("my_tag") # create tags using the repo for convenience
# ![2-test_references_and_objects]
# [3-test_references_and_objects]
- head = repo.head # the head points to the active branch/ref
- master = head.reference # retrieve the reference the head points to
- master.commit # from here you use it as any other reference
+ head = repo.head # the head points to the active branch/ref
+ master = head.reference # retrieve the reference the head points to
+ master.commit # from here you use it as any other reference
# ![3-test_references_and_objects]
-#
+ #
# [4-test_references_and_objects]
log = master.log()
- log[0] # first (i.e. oldest) reflog entry
- log[-1] # last (i.e. most recent) reflog entry
+ log[0] # first (i.e. oldest) reflog entry
+ log[-1] # last (i.e. most recent) reflog entry
# ![4-test_references_and_objects]
# [5-test_references_and_objects]
- new_branch = repo.create_head('new') # create a new one
- new_branch.commit = 'HEAD~10' # set branch to another commit without changing index or working trees
- repo.delete_head(new_branch) # delete an existing head - only works if it is not checked out
+ new_branch = repo.create_head("new") # create a new one
+ new_branch.commit = "HEAD~10" # set branch to another commit without changing index or working trees
+ repo.delete_head(
+ new_branch
+ ) # delete an existing head - only works if it is not checked out
# ![5-test_references_and_objects]
# [6-test_references_and_objects]
- new_tag = repo.create_tag('my_new_tag', message='my message')
+ new_tag = repo.create_tag("my_new_tag", message="my message")
# You cannot change the commit a tag points to. Tags need to be re-created
- self.assertRaises(AttributeError, setattr, new_tag, 'commit', repo.commit('HEAD~1'))
+ self.assertRaises(
+ AttributeError, setattr, new_tag, "commit", repo.commit("HEAD~1")
+ )
repo.delete_tag(new_tag)
# ![6-test_references_and_objects]
# [7-test_references_and_objects]
- new_branch = repo.create_head('another-branch')
+ new_branch = repo.create_head("another-branch")
repo.head.reference = new_branch
# ![7-test_references_and_objects]
# [8-test_references_and_objects]
hc = repo.head.commit
hct = hc.tree
- hc != hct # @NoEffect
- hc != repo.tags[0] # @NoEffect
- hc == repo.head.reference.commit # @NoEffect
+ hc != hct # @NoEffect
+ hc != repo.tags[0] # @NoEffect
+ hc == repo.head.reference.commit # @NoEffect
# ![8-test_references_and_objects]
# [9-test_references_and_objects]
- self.assertEqual(hct.type, 'tree') # preset string type, being a class attribute
- assert hct.size > 0 # size in bytes
+ self.assertEqual(
+ hct.type, "tree"
+ ) # preset string type, being a class attribute
+ assert hct.size > 0 # size in bytes
assert len(hct.hexsha) == 40
assert len(hct.binsha) == 20
# ![9-test_references_and_objects]
# [10-test_references_and_objects]
- self.assertEqual(hct.path, '') # root tree has no path
- assert hct.trees[0].path != '' # the first contained item has one though
- self.assertEqual(hct.mode, 0o40000) # trees have the mode of a linux directory
- self.assertEqual(hct.blobs[0].mode, 0o100644) # blobs have specific mode, comparable to a standard linux fs
+ self.assertEqual(hct.path, "") # root tree has no path
+ assert hct.trees[0].path != "" # the first contained item has one though
+ self.assertEqual(hct.mode, 0o40000) # trees have the mode of a linux directory
+ self.assertEqual(
+ hct.blobs[0].mode, 0o100644
+ ) # blobs have specific mode, comparable to a standard linux fs
# ![10-test_references_and_objects]
# [11-test_references_and_objects]
- hct.blobs[0].data_stream.read() # stream object to read data from
- hct.blobs[0].stream_data(open(os.path.join(rw_dir, 'blob_data'), 'wb')) # write data to given stream
+ hct.blobs[0].data_stream.read() # stream object to read data from
+ hct.blobs[0].stream_data(
+ open(os.path.join(rw_dir, "blob_data"), "wb")
+ ) # write data to given stream
# ![11-test_references_and_objects]
# [12-test_references_and_objects]
- repo.commit('master')
- repo.commit('v0.8.1')
- repo.commit('HEAD~10')
+ repo.commit("master")
+ repo.commit("v0.8.1")
+ repo.commit("HEAD~10")
# ![12-test_references_and_objects]
# [13-test_references_and_objects]
- fifty_first_commits = list(repo.iter_commits('master', max_count=50))
+ fifty_first_commits = list(repo.iter_commits("master", max_count=50))
assert len(fifty_first_commits) == 50
# this will return commits 21-30 from the commit list as traversed backwards master
- ten_commits_past_twenty = list(repo.iter_commits('master', max_count=10, skip=20))
+ ten_commits_past_twenty = list(
+ repo.iter_commits("master", max_count=10, skip=20)
+ )
assert len(ten_commits_past_twenty) == 10
assert fifty_first_commits[20:30] == ten_commits_past_twenty
# ![13-test_references_and_objects]
@@ -287,22 +375,23 @@ class Tutorials(TestBase):
headcommit = repo.head.commit
assert len(headcommit.hexsha) == 40
assert len(headcommit.parents) > 0
- assert headcommit.tree.type == 'tree'
+ assert headcommit.tree.type == "tree"
assert len(headcommit.author.name) != 0
assert isinstance(headcommit.authored_date, int)
assert len(headcommit.committer.name) != 0
assert isinstance(headcommit.committed_date, int)
- assert headcommit.message != ''
+ assert headcommit.message != ""
# ![14-test_references_and_objects]
# [15-test_references_and_objects]
import time
+
time.asctime(time.gmtime(headcommit.committed_date))
time.strftime("%a, %d %b %Y %H:%M", time.gmtime(headcommit.committed_date))
# ![15-test_references_and_objects]
# [16-test_references_and_objects]
- assert headcommit.parents[0].parents[0].parents[0] == repo.commit('master^^^')
+ assert headcommit.parents[0].parents[0].parents[0] == repo.commit("master^^^")
# ![16-test_references_and_objects]
# [17-test_references_and_objects]
@@ -311,33 +400,41 @@ class Tutorials(TestBase):
# ![17-test_references_and_objects]
# [18-test_references_and_objects]
- assert len(tree.trees) > 0 # trees are subdirectories
- assert len(tree.blobs) > 0 # blobs are files
+ assert len(tree.trees) > 0 # trees are subdirectories
+ assert len(tree.blobs) > 0 # blobs are files
assert len(tree.blobs) + len(tree.trees) == len(tree)
# ![18-test_references_and_objects]
# [19-test_references_and_objects]
- self.assertEqual(tree['smmap'], tree / 'smmap') # access by index and by sub-path
- for entry in tree: # intuitive iteration of tree members
+ self.assertEqual(
+ tree["smmap"], tree / "smmap"
+ ) # access by index and by sub-path
+ for entry in tree: # intuitive iteration of tree members
print(entry)
- blob = tree.trees[1].blobs[0] # let's get a blob in a sub-tree
+ blob = tree.trees[1].blobs[0] # let's get a blob in a sub-tree
assert blob.name
assert len(blob.path) < len(blob.abspath)
- self.assertEqual(tree.trees[1].name + '/' + blob.name, blob.path) # this is how relative blob path generated
- self.assertEqual(tree[blob.path], blob) # you can use paths like 'dir/file' in tree
+ self.assertEqual(
+ tree.trees[1].name + "/" + blob.name, blob.path
+ ) # this is how relative blob path generated
+ self.assertEqual(
+ tree[blob.path], blob
+ ) # you can use paths like 'dir/file' in tree
# ![19-test_references_and_objects]
# [20-test_references_and_objects]
- assert tree / 'smmap' == tree['smmap']
+ assert tree / "smmap" == tree["smmap"]
assert tree / blob.path == tree[blob.path]
# ![20-test_references_and_objects]
# [21-test_references_and_objects]
# This example shows the various types of allowed ref-specs
assert repo.tree() == repo.head.commit.tree
- past = repo.commit('HEAD~5')
+ past = repo.commit("HEAD~5")
assert repo.tree(past) == repo.tree(past.hexsha)
- self.assertEqual(repo.tree('v0.8.1').type, 'tree') # yes, you can provide any refspec - works everywhere
+ self.assertEqual(
+ repo.tree("v0.8.1").type, "tree"
+ ) # yes, you can provide any refspec - works everywhere
# ![21-test_references_and_objects]
# [22-test_references_and_objects]
@@ -347,20 +444,27 @@ class Tutorials(TestBase):
# [23-test_references_and_objects]
index = repo.index
# The index contains all blobs in a flat list
- assert len(list(index.iter_blobs())) == len([o for o in repo.head.commit.tree.traverse() if o.type == 'blob'])
+ assert len(list(index.iter_blobs())) == len(
+ [o for o in repo.head.commit.tree.traverse() if o.type == "blob"]
+ )
# Access blob objects
for (_path, _stage), entry in index.entries.items():
pass
- new_file_path = os.path.join(repo.working_tree_dir, 'new-file-name')
- open(new_file_path, 'w').close()
- index.add([new_file_path]) # add a new file to the index
- index.remove(['LICENSE']) # remove an existing one
- assert os.path.isfile(os.path.join(repo.working_tree_dir, 'LICENSE')) # working tree is untouched
-
- self.assertEqual(index.commit("my commit message").type, 'commit') # commit changed index
- repo.active_branch.commit = repo.commit('HEAD~1') # forget last commit
+ new_file_path = os.path.join(repo.working_tree_dir, "new-file-name")
+ open(new_file_path, "w").close()
+ index.add([new_file_path]) # add a new file to the index
+ index.remove(["LICENSE"]) # remove an existing one
+ assert os.path.isfile(
+ os.path.join(repo.working_tree_dir, "LICENSE")
+ ) # working tree is untouched
+
+ self.assertEqual(
+ index.commit("my commit message").type, "commit"
+ ) # commit changed index
+ repo.active_branch.commit = repo.commit("HEAD~1") # forget last commit
from git import Actor
+
author = Actor("An author", "author@example.com")
committer = Actor("A committer", "committer@example.com")
# commit by commit message and author and committer
@@ -369,28 +473,37 @@ class Tutorials(TestBase):
# [24-test_references_and_objects]
from git import IndexFile
+
# loads a tree into a temporary index, which exists just in memory
- IndexFile.from_tree(repo, 'HEAD~1')
+ IndexFile.from_tree(repo, "HEAD~1")
# merge two trees three-way into memory
- merge_index = IndexFile.from_tree(repo, 'HEAD~10', 'HEAD', repo.merge_base('HEAD~10', 'HEAD'))
+ merge_index = IndexFile.from_tree(
+ repo, "HEAD~10", "HEAD", repo.merge_base("HEAD~10", "HEAD")
+ )
# and persist it
- merge_index.write(os.path.join(rw_dir, 'merged_index'))
+ merge_index.write(os.path.join(rw_dir, "merged_index"))
# ![24-test_references_and_objects]
# [25-test_references_and_objects]
- empty_repo = git.Repo.init(os.path.join(rw_dir, 'empty'))
- origin = empty_repo.create_remote('origin', repo.remotes.origin.url)
+ empty_repo = git.Repo.init(os.path.join(rw_dir, "empty"))
+ origin = empty_repo.create_remote("origin", repo.remotes.origin.url)
assert origin.exists()
- assert origin == empty_repo.remotes.origin == empty_repo.remotes['origin']
- origin.fetch() # assure we actually have data. fetch() returns useful information
+ assert origin == empty_repo.remotes.origin == empty_repo.remotes["origin"]
+ origin.fetch() # assure we actually have data. fetch() returns useful information
# Setup a local tracking branch of a remote branch
- empty_repo.create_head('master', origin.refs.master) # create local branch "master" from remote "master"
- empty_repo.heads.master.set_tracking_branch(origin.refs.master) # set local "master" to track remote "master
+ empty_repo.create_head(
+ "master", origin.refs.master
+ ) # create local branch "master" from remote "master"
+ empty_repo.heads.master.set_tracking_branch(
+ origin.refs.master
+ ) # set local "master" to track remote "master
empty_repo.heads.master.checkout() # checkout local "master" to working tree
# Three above commands in one:
- empty_repo.create_head('master', origin.refs.master).set_tracking_branch(origin.refs.master).checkout()
+ empty_repo.create_head("master", origin.refs.master).set_tracking_branch(
+ origin.refs.master
+ ).checkout()
# rename remotes
- origin.rename('new_origin')
+ origin.rename("new_origin")
# push and pull behaves similarly to `git push|pull`
origin.pull()
origin.push() # attempt push, ignore errors
@@ -409,32 +522,32 @@ class Tutorials(TestBase):
# [27-test_references_and_objects]
hcommit = repo.head.commit
- hcommit.diff() # diff tree against index
- hcommit.diff('HEAD~1') # diff tree against previous tree
- hcommit.diff(None) # diff tree against working tree
+ hcommit.diff() # diff tree against index
+ hcommit.diff("HEAD~1") # diff tree against previous tree
+ hcommit.diff(None) # diff tree against working tree
index = repo.index
- index.diff() # diff index against itself yielding empty diff
- index.diff(None) # diff index against working copy
- index.diff('HEAD') # diff index against current HEAD tree
+ index.diff() # diff index against itself yielding empty diff
+ index.diff(None) # diff index against working copy
+ index.diff("HEAD") # diff index against current HEAD tree
# ![27-test_references_and_objects]
# [28-test_references_and_objects]
# Traverse added Diff objects only
- for diff_added in hcommit.diff('HEAD~1').iter_change_type('A'):
+ for diff_added in hcommit.diff("HEAD~1").iter_change_type("A"):
print(diff_added)
# ![28-test_references_and_objects]
# [29-test_references_and_objects]
# Reset our working tree 10 commits into the past
- past_branch = repo.create_head('past_branch', 'HEAD~10')
+ past_branch = repo.create_head("past_branch", "HEAD~10")
repo.head.reference = past_branch
assert not repo.head.is_detached
# reset the index and working tree to match the pointed-to commit
repo.head.reset(index=True, working_tree=True)
# To detach your head, you have to point to a commit directly
- repo.head.reference = repo.commit('HEAD~5')
+ repo.head.reference = repo.commit("HEAD~5")
assert repo.head.is_detached
# now our head points 15 commits into the past, whereas the working tree
# and index are 10 commits in the past
@@ -448,10 +561,12 @@ class Tutorials(TestBase):
# [31-test_references_and_objects]
git = repo.git
- git.checkout('HEAD', b="my_new_branch") # create a new branch
- git.branch('another-new-one')
- git.branch('-D', 'another-new-one') # pass strings for full control over argument order
- git.for_each_ref() # '-' becomes '_' when calling it
+ git.checkout("HEAD", b="my_new_branch") # create a new branch
+ git.branch("another-new-one")
+ git.branch(
+ "-D", "another-new-one"
+ ) # pass strings for full control over argument order
+ git.for_each_ref() # '-' becomes '_' when calling it
# ![31-test_references_and_objects]
repo.git.clear_cache()
@@ -463,31 +578,37 @@ class Tutorials(TestBase):
assert len(sms) == 1
sm = sms[0]
- self.assertEqual(sm.name, 'gitdb') # git-python has gitdb as single submodule ...
- self.assertEqual(sm.children()[0].name, 'smmap') # ... which has smmap as single submodule
+ self.assertEqual(
+ sm.name, "gitdb"
+ ) # git-python has gitdb as single submodule ...
+ self.assertEqual(
+ sm.children()[0].name, "smmap"
+ ) # ... which has smmap as single submodule
# The module is the repository referenced by the submodule
- assert sm.module_exists() # the module is available, which doesn't have to be the case.
- assert sm.module().working_tree_dir.endswith('gitdb')
+ assert (
+ sm.module_exists()
+ ) # the module is available, which doesn't have to be the case.
+ assert sm.module().working_tree_dir.endswith("gitdb")
# the submodule's absolute path is the module's path
assert sm.abspath == sm.module().working_tree_dir
- self.assertEqual(len(sm.hexsha), 40) # Its sha defines the commit to checkout
- assert sm.exists() # yes, this submodule is valid and exists
+ self.assertEqual(len(sm.hexsha), 40) # Its sha defines the commit to checkout
+ assert sm.exists() # yes, this submodule is valid and exists
# read its configuration conveniently
- assert sm.config_reader().get_value('path') == sm.path
- self.assertEqual(len(sm.children()), 1) # query the submodule hierarchy
+ assert sm.config_reader().get_value("path") == sm.path
+ self.assertEqual(len(sm.children()), 1) # query the submodule hierarchy
# ![1-test_submodules]
@with_rw_directory
def test_add_file_and_commit(self, rw_dir):
import git
- repo_dir = os.path.join(rw_dir, 'my-new-repo')
- file_name = os.path.join(repo_dir, 'new-file')
+ repo_dir = os.path.join(rw_dir, "my-new-repo")
+ file_name = os.path.join(repo_dir, "new-file")
r = git.Repo.init(repo_dir)
# This function just creates an empty file ...
- open(file_name, 'wb').close()
+ open(file_name, "wb").close()
r.index.add([file_name])
r.index.commit("initial commit")
diff --git a/test/test_exc.py b/test/test_exc.py
index c77be782..6c3353fc 100644
--- a/test/test_exc.py
+++ b/test/test_exc.py
@@ -29,34 +29,43 @@ import itertools as itt
_cmd_argvs = (
- ('cmd', ),
- ('θνιψοδε', ),
- ('θνιψοδε', 'normal', 'argvs'),
- ('cmd', 'ελληνικα', 'args'),
- ('θνιψοδε', 'κι', 'αλλα', 'strange', 'args'),
- ('θνιψοδε', 'κι', 'αλλα', 'non-unicode', 'args'),
- ('git', 'clone', '-v', 'https://fakeuser:fakepassword1234@fakerepo.example.com/testrepo'),
+ ("cmd",),
+ ("θνιψοδε",),
+ ("θνιψοδε", "normal", "argvs"),
+ ("cmd", "ελληνικα", "args"),
+ ("θνιψοδε", "κι", "αλλα", "strange", "args"),
+ ("θνιψοδε", "κι", "αλλα", "non-unicode", "args"),
+ (
+ "git",
+ "clone",
+ "-v",
+ "https://fakeuser:fakepassword1234@fakerepo.example.com/testrepo",
+ ),
)
_causes_n_substrings = (
- (None, None), # noqa: E241 @IgnorePep8
- (7, "exit code(7)"), # noqa: E241 @IgnorePep8
- ('Some string', "'Some string'"), # noqa: E241 @IgnorePep8
- ('παλιο string', "'παλιο string'"), # noqa: E241 @IgnorePep8
- (Exception("An exc."), "Exception('An exc.')"), # noqa: E241 @IgnorePep8
- (Exception("Κακια exc."), "Exception('Κακια exc.')"), # noqa: E241 @IgnorePep8
- (object(), "<object object at "), # noqa: E241 @IgnorePep8
+ (None, None), # noqa: E241 @IgnorePep8
+ (7, "exit code(7)"), # noqa: E241 @IgnorePep8
+ ("Some string", "'Some string'"), # noqa: E241 @IgnorePep8
+ ("παλιο string", "'παλιο string'"), # noqa: E241 @IgnorePep8
+ (Exception("An exc."), "Exception('An exc.')"), # noqa: E241 @IgnorePep8
+ (Exception("Κακια exc."), "Exception('Κακια exc.')"), # noqa: E241 @IgnorePep8
+ (object(), "<object object at "), # noqa: E241 @IgnorePep8
)
-_streams_n_substrings = (None, 'steram', 'ομορφο stream', )
+_streams_n_substrings = (
+ None,
+ "steram",
+ "ομορφο stream",
+)
@ddt.ddt
class TExc(TestBase):
-
def test_ExceptionsHaveBaseClass(self):
from git.exc import GitError
+
self.assertIsInstance(GitError(), Exception)
-
+
exception_classes = [
InvalidGitRepositoryError,
WorkTreeRepositoryUnsupported,
@@ -73,7 +82,9 @@ class TExc(TestBase):
for ex_class in exception_classes:
self.assertTrue(issubclass(ex_class, GitError))
- @ddt.data(*list(itt.product(_cmd_argvs, _causes_n_substrings, _streams_n_substrings)))
+ @ddt.data(
+ *list(itt.product(_cmd_argvs, _causes_n_substrings, _streams_n_substrings))
+ )
def test_CommandError_unicode(self, case):
argv, (cause, subs), stream = case
cls = CommandError
@@ -81,7 +92,7 @@ class TExc(TestBase):
s = str(c)
self.assertIsNotNone(c._msg)
- self.assertIn(' cmdline: ', s)
+ self.assertIn(" cmdline: ", s)
for a in remove_password_if_present(argv):
self.assertIn(a, s)
@@ -112,17 +123,17 @@ class TExc(TestBase):
self.assertIn(" stdout:", s)
self.assertIn(stream, s)
- c = cls(argv, cause, stream, stream + 'no2')
+ c = cls(argv, cause, stream, stream + "no2")
s = str(c)
self.assertIn(" stderr:", s)
self.assertIn(stream, s)
self.assertIn(" stdout:", s)
- self.assertIn(stream + 'no2', s)
+ self.assertIn(stream + "no2", s)
@ddt.data(
- (['cmd1'], None),
- (['cmd1'], "some cause"),
- (['cmd1'], Exception()),
+ (["cmd1"], None),
+ (["cmd1"], "some cause"),
+ (["cmd1"], Exception()),
)
def test_GitCommandNotFound(self, init_args):
argv, cause = init_args
@@ -131,15 +142,15 @@ class TExc(TestBase):
self.assertIn(argv[0], s)
if cause:
- self.assertIn(' not found due to: ', s)
+ self.assertIn(" not found due to: ", s)
self.assertIn(str(cause), s)
else:
- self.assertIn(' not found!', s)
+ self.assertIn(" not found!", s)
@ddt.data(
- (['cmd1'], None),
- (['cmd1'], "some cause"),
- (['cmd1', 'https://fakeuser@fakerepo.example.com/testrepo'], Exception()),
+ (["cmd1"], None),
+ (["cmd1"], "some cause"),
+ (["cmd1", "https://fakeuser@fakerepo.example.com/testrepo"], Exception()),
)
def test_GitCommandError(self, init_args):
argv, cause = init_args
@@ -149,15 +160,15 @@ class TExc(TestBase):
for arg in remove_password_if_present(argv):
self.assertIn(arg, s)
if cause:
- self.assertIn(' failed due to: ', s)
+ self.assertIn(" failed due to: ", s)
self.assertIn(str(cause), s)
else:
- self.assertIn(' failed!', s)
+ self.assertIn(" failed!", s)
@ddt.data(
- (['cmd1'], None),
- (['cmd1'], "some cause"),
- (['cmd1'], Exception()),
+ (["cmd1"], None),
+ (["cmd1"], "some cause"),
+ (["cmd1"], Exception()),
)
def test_HookExecutionError(self, init_args):
argv, cause = init_args
@@ -166,7 +177,7 @@ class TExc(TestBase):
self.assertIn(argv[0], s)
if cause:
- self.assertTrue(s.startswith('Hook('), s)
+ self.assertTrue(s.startswith("Hook("), s)
self.assertIn(str(cause), s)
else:
- self.assertIn(' failed!', s)
+ self.assertIn(" failed!", s)
diff --git a/test/test_fun.py b/test/test_fun.py
index e3d07194..7c99a4a1 100644
--- a/test/test_fun.py
+++ b/test/test_fun.py
@@ -16,23 +16,19 @@ from git.objects.fun import (
tree_to_stream,
tree_entries_from_data,
)
-from git.repo.fun import (
- find_worktree_git_dir
-)
-from test.lib import (
- TestBase,
- with_rw_repo,
- with_rw_directory
-)
+from git.repo.fun import find_worktree_git_dir
+from test.lib import TestBase, with_rw_repo, with_rw_directory
from git.util import bin_to_hex, cygpath, join_path_native
from gitdb.base import IStream
from gitdb.typ import str_tree_type
class TestFun(TestBase):
-
def _assert_index_entries(self, entries, trees):
- index = IndexFile.from_tree(self.rorepo, *[self.rorepo.tree(bin_to_hex(t).decode('ascii')) for t in trees])
+ index = IndexFile.from_tree(
+ self.rorepo,
+ *[self.rorepo.tree(bin_to_hex(t).decode("ascii")) for t in trees]
+ )
assert entries
assert len(index.entries) == len(entries)
for entry in entries:
@@ -80,7 +76,7 @@ class TestFun(TestBase):
istream = odb.store(IStream(str_tree_type, len(sio.getvalue()), sio))
return istream.binsha
- @with_rw_repo('0.1.6')
+ @with_rw_repo("0.1.6")
def test_three_way_merge(self, rwrepo):
def mkfile(name, sha, executable=0):
return (sha, S_IFREG | 0o644 | executable * 0o111, name)
@@ -91,6 +87,7 @@ class TestFun(TestBase):
def assert_entries(entries, num_entries, has_conflict=False):
assert len(entries) == num_entries
assert has_conflict == (len([e for e in entries if e.stage != 0]) > 0)
+
mktree = self.mktree
shaa = b"\1" * 20
@@ -100,14 +97,14 @@ class TestFun(TestBase):
odb = rwrepo.odb
# base tree
- bfn = 'basefile'
+ bfn = "basefile"
fbase = mkfile(bfn, shaa)
tb = mktree(odb, [fbase])
# non-conflicting new files, same data
- fa = mkfile('1', shab)
+ fa = mkfile("1", shab)
th = mktree(odb, [fbase, fa])
- fb = mkfile('2', shac)
+ fb = mkfile("2", shac)
tm = mktree(odb, [fbase, fb])
# two new files, same base file
@@ -115,9 +112,9 @@ class TestFun(TestBase):
assert_entries(aggressive_tree_merge(odb, trees), 3)
# both delete same file, add own one
- fa = mkfile('1', shab)
+ fa = mkfile("1", shab)
th = mktree(odb, [fa])
- fb = mkfile('2', shac)
+ fb = mkfile("2", shac)
tm = mktree(odb, [fb])
# two new files
@@ -125,9 +122,9 @@ class TestFun(TestBase):
assert_entries(aggressive_tree_merge(odb, trees), 2)
# same file added in both, differently
- fa = mkfile('1', shab)
+ fa = mkfile("1", shab)
th = mktree(odb, [fa])
- fb = mkfile('1', shac)
+ fb = mkfile("1", shac)
tm = mktree(odb, [fb])
# expect conflict
@@ -135,9 +132,9 @@ class TestFun(TestBase):
assert_entries(aggressive_tree_merge(odb, trees), 2, True)
# same file added, different mode
- fa = mkfile('1', shab)
+ fa = mkfile("1", shab)
th = mktree(odb, [fa])
- fb = mkcommit('1', shab)
+ fb = mkcommit("1", shab)
tm = mktree(odb, [fb])
# expect conflict
@@ -145,9 +142,9 @@ class TestFun(TestBase):
assert_entries(aggressive_tree_merge(odb, trees), 2, True)
# same file added in both
- fa = mkfile('1', shab)
+ fa = mkfile("1", shab)
th = mktree(odb, [fa])
- fb = mkfile('1', shab)
+ fb = mkfile("1", shab)
tm = mktree(odb, [fb])
# expect conflict
@@ -194,7 +191,11 @@ class TestFun(TestBase):
if is_them:
trees = [tb, tb, th]
entries = aggressive_tree_merge(odb, trees)
- assert len(entries) == 1 and entries[0].binsha == shaa and entries[0].mode == fa[1]
+ assert (
+ len(entries) == 1
+ and entries[0].binsha == shaa
+ and entries[0].mode == fa[1]
+ )
# one side deletes, the other changes = conflict
fa = mkfile(bfn, shab)
@@ -209,8 +210,20 @@ class TestFun(TestBase):
def test_stat_mode_to_index_mode(self):
modes = (
- 0o600, 0o611, 0o640, 0o641, 0o644, 0o650, 0o651,
- 0o700, 0o711, 0o740, 0o744, 0o750, 0o751, 0o755,
+ 0o600,
+ 0o611,
+ 0o640,
+ 0o641,
+ 0o644,
+ 0o650,
+ 0o651,
+ 0o700,
+ 0o711,
+ 0o740,
+ 0o744,
+ 0o750,
+ 0o751,
+ 0o755,
)
for mode in modes:
expected_mode = S_IFREG | (mode & S_IXUSR and 0o755 or 0o644)
@@ -229,42 +242,46 @@ class TestFun(TestBase):
def test_tree_traversal(self):
# low level tree tarversal
odb = self.rorepo.odb
- H = self.rorepo.tree('29eb123beb1c55e5db4aa652d843adccbd09ae18') # head tree
- M = self.rorepo.tree('e14e3f143e7260de9581aee27e5a9b2645db72de') # merge tree
- B = self.rorepo.tree('f606937a7a21237c866efafcad33675e6539c103') # base tree
- B_old = self.rorepo.tree('1f66cfbbce58b4b552b041707a12d437cc5f400a') # old base tree
+ H = self.rorepo.tree("29eb123beb1c55e5db4aa652d843adccbd09ae18") # head tree
+ M = self.rorepo.tree("e14e3f143e7260de9581aee27e5a9b2645db72de") # merge tree
+ B = self.rorepo.tree("f606937a7a21237c866efafcad33675e6539c103") # base tree
+ B_old = self.rorepo.tree(
+ "1f66cfbbce58b4b552b041707a12d437cc5f400a"
+ ) # old base tree
# two very different trees
- entries = traverse_trees_recursive(odb, [B_old.binsha, H.binsha], '')
+ entries = traverse_trees_recursive(odb, [B_old.binsha, H.binsha], "")
self._assert_tree_entries(entries, 2)
- oentries = traverse_trees_recursive(odb, [H.binsha, B_old.binsha], '')
+ oentries = traverse_trees_recursive(odb, [H.binsha, B_old.binsha], "")
assert len(oentries) == len(entries)
self._assert_tree_entries(oentries, 2)
# single tree
- is_no_tree = lambda i, d: i.type != 'tree'
- entries = traverse_trees_recursive(odb, [B.binsha], '')
+ is_no_tree = lambda i, d: i.type != "tree"
+ entries = traverse_trees_recursive(odb, [B.binsha], "")
assert len(entries) == len(list(B.traverse(predicate=is_no_tree)))
self._assert_tree_entries(entries, 1)
# two trees
- entries = traverse_trees_recursive(odb, [B.binsha, H.binsha], '')
+ entries = traverse_trees_recursive(odb, [B.binsha, H.binsha], "")
self._assert_tree_entries(entries, 2)
# tree trees
- entries = traverse_trees_recursive(odb, [B.binsha, H.binsha, M.binsha], '')
+ entries = traverse_trees_recursive(odb, [B.binsha, H.binsha, M.binsha], "")
self._assert_tree_entries(entries, 3)
def test_tree_traversal_single(self):
max_count = 50
count = 0
odb = self.rorepo.odb
- for commit in self.rorepo.commit("29eb123beb1c55e5db4aa652d843adccbd09ae18").traverse():
+ for commit in self.rorepo.commit(
+ "29eb123beb1c55e5db4aa652d843adccbd09ae18"
+ ).traverse():
if count >= max_count:
break
count += 1
- entries = traverse_tree_recursive(odb, commit.tree.binsha, '')
+ entries = traverse_tree_recursive(odb, commit.tree.binsha, "")
assert entries
# END for each commit
@@ -275,12 +292,12 @@ class TestFun(TestBase):
if git.version_info[:3] < (2, 5, 1):
raise SkipTest("worktree feature unsupported")
- rw_master = self.rorepo.clone(join_path_native(rw_dir, 'master_repo'))
- branch = rw_master.create_head('aaaaaaaa')
- worktree_path = join_path_native(rw_dir, 'worktree_repo')
+ rw_master = self.rorepo.clone(join_path_native(rw_dir, "master_repo"))
+ branch = rw_master.create_head("aaaaaaaa")
+ worktree_path = join_path_native(rw_dir, "worktree_repo")
if Git.is_cygwin():
worktree_path = cygpath(worktree_path)
- rw_master.git.worktree('add', worktree_path, branch.name)
+ rw_master.git.worktree("add", worktree_path, branch.name)
dotgit = osp.join(worktree_path, ".git")
statbuf = stat(dotgit)
@@ -292,5 +309,5 @@ class TestFun(TestBase):
self.assertTrue(statbuf.st_mode & S_IFDIR)
def test_tree_entries_from_data_with_failing_name_decode_py3(self):
- r = tree_entries_from_data(b'100644 \x9f\0aaa')
- assert r == [(b'aaa', 33188, '\udc9f')], r
+ r = tree_entries_from_data(b"100644 \x9f\0aaa")
+ assert r == [(b"aaa", 33188, "\udc9f")], r
diff --git a/test/test_git.py b/test/test_git.py
index 10e21487..2a034e41 100644
--- a/test/test_git.py
+++ b/test/test_git.py
@@ -10,18 +10,8 @@ import sys
from tempfile import TemporaryFile
from unittest import mock
-from git import (
- Git,
- refresh,
- GitCommandError,
- GitCommandNotFound,
- Repo,
- cmd
-)
-from test.lib import (
- TestBase,
- fixture_path
-)
+from git import Git, refresh, GitCommandError, GitCommandNotFound, Repo, cmd
+from test.lib import TestBase, fixture_path
from test.lib import with_rw_directory
from git.util import finalize_process
@@ -31,7 +21,6 @@ from git.compat import is_win
class TestGit(TestBase):
-
@classmethod
def setUpClass(cls):
super(TestGit, cls).setUpClass()
@@ -39,56 +28,72 @@ class TestGit(TestBase):
def tearDown(self):
import gc
+
gc.collect()
- @mock.patch.object(Git, 'execute')
+ @mock.patch.object(Git, "execute")
def test_call_process_calls_execute(self, git):
- git.return_value = ''
+ git.return_value = ""
self.git.version()
self.assertTrue(git.called)
- self.assertEqual(git.call_args, ((['git', 'version'],), {}))
+ self.assertEqual(git.call_args, ((["git", "version"],), {}))
def test_call_unpack_args_unicode(self):
- args = Git._Git__unpack_args('Unicode€™')
- mangled_value = 'Unicode\u20ac\u2122'
+ args = Git._Git__unpack_args("Unicode€™")
+ mangled_value = "Unicode\u20ac\u2122"
self.assertEqual(args, [mangled_value])
def test_call_unpack_args(self):
- args = Git._Git__unpack_args(['git', 'log', '--', 'Unicode€™'])
- mangled_value = 'Unicode\u20ac\u2122'
- self.assertEqual(args, ['git', 'log', '--', mangled_value])
+ args = Git._Git__unpack_args(["git", "log", "--", "Unicode€™"])
+ mangled_value = "Unicode\u20ac\u2122"
+ self.assertEqual(args, ["git", "log", "--", mangled_value])
def test_it_raises_errors(self):
self.assertRaises(GitCommandError, self.git.this_does_not_exist)
def test_it_transforms_kwargs_into_git_command_arguments(self):
- self.assertEqual(["-s"], self.git.transform_kwargs(**{'s': True}))
- self.assertEqual(["-s", "5"], self.git.transform_kwargs(**{'s': 5}))
- self.assertEqual([], self.git.transform_kwargs(**{'s': None}))
+ self.assertEqual(["-s"], self.git.transform_kwargs(**{"s": True}))
+ self.assertEqual(["-s", "5"], self.git.transform_kwargs(**{"s": 5}))
+ self.assertEqual([], self.git.transform_kwargs(**{"s": None}))
- self.assertEqual(["--max-count"], self.git.transform_kwargs(**{'max_count': True}))
- self.assertEqual(["--max-count=5"], self.git.transform_kwargs(**{'max_count': 5}))
- self.assertEqual(["--max-count=0"], self.git.transform_kwargs(**{'max_count': 0}))
- self.assertEqual([], self.git.transform_kwargs(**{'max_count': None}))
+ self.assertEqual(
+ ["--max-count"], self.git.transform_kwargs(**{"max_count": True})
+ )
+ self.assertEqual(
+ ["--max-count=5"], self.git.transform_kwargs(**{"max_count": 5})
+ )
+ self.assertEqual(
+ ["--max-count=0"], self.git.transform_kwargs(**{"max_count": 0})
+ )
+ self.assertEqual([], self.git.transform_kwargs(**{"max_count": None}))
# Multiple args are supported by using lists/tuples
- self.assertEqual(["-L", "1-3", "-L", "12-18"], self.git.transform_kwargs(**{'L': ('1-3', '12-18')}))
- self.assertEqual(["-C", "-C"], self.git.transform_kwargs(**{'C': [True, True, None, False]}))
+ self.assertEqual(
+ ["-L", "1-3", "-L", "12-18"],
+ self.git.transform_kwargs(**{"L": ("1-3", "12-18")}),
+ )
+ self.assertEqual(
+ ["-C", "-C"], self.git.transform_kwargs(**{"C": [True, True, None, False]})
+ )
# order is undefined
- res = self.git.transform_kwargs(**{'s': True, 't': True})
- self.assertEqual({'-s', '-t'}, set(res))
+ res = self.git.transform_kwargs(**{"s": True, "t": True})
+ self.assertEqual({"-s", "-t"}, set(res))
def test_it_executes_git_to_shell_and_returns_result(self):
- self.assertRegex(self.git.execute(["git", "version"]), r'^git version [\d\.]{2}.*$')
+ self.assertRegex(
+ self.git.execute(["git", "version"]), r"^git version [\d\.]{2}.*$"
+ )
def test_it_accepts_stdin(self):
filename = fixture_path("cat_file_blob")
- with open(filename, 'r') as fh:
- self.assertEqual("70c379b63ffa0795fdbfbc128e5a2818397b7ef8",
- self.git.hash_object(istream=fh, stdin=True))
+ with open(filename, "r") as fh:
+ self.assertEqual(
+ "70c379b63ffa0795fdbfbc128e5a2818397b7ef8",
+ self.git.hash_object(istream=fh, stdin=True),
+ )
- @mock.patch.object(Git, 'execute')
+ @mock.patch.object(Git, "execute")
def test_it_ignores_false_kwargs(self, git):
# this_should_not_be_ignored=False implies it *should* be ignored
self.git.version(pass_this_kwarg=False)
@@ -96,22 +101,27 @@ class TestGit(TestBase):
def test_it_raises_proper_exception_with_output_stream(self):
tmp_file = TemporaryFile()
- self.assertRaises(GitCommandError, self.git.checkout, 'non-existent-branch', output_stream=tmp_file)
+ self.assertRaises(
+ GitCommandError,
+ self.git.checkout,
+ "non-existent-branch",
+ output_stream=tmp_file,
+ )
def test_it_accepts_environment_variables(self):
filename = fixture_path("ls_tree_empty")
- with open(filename, 'r') as fh:
+ with open(filename, "r") as fh:
tree = self.git.mktree(istream=fh)
env = {
- 'GIT_AUTHOR_NAME': 'Author Name',
- 'GIT_AUTHOR_EMAIL': 'author@example.com',
- 'GIT_AUTHOR_DATE': '1400000000+0000',
- 'GIT_COMMITTER_NAME': 'Committer Name',
- 'GIT_COMMITTER_EMAIL': 'committer@example.com',
- 'GIT_COMMITTER_DATE': '1500000000+0000',
+ "GIT_AUTHOR_NAME": "Author Name",
+ "GIT_AUTHOR_EMAIL": "author@example.com",
+ "GIT_AUTHOR_DATE": "1400000000+0000",
+ "GIT_COMMITTER_NAME": "Committer Name",
+ "GIT_COMMITTER_EMAIL": "committer@example.com",
+ "GIT_COMMITTER_DATE": "1500000000+0000",
}
- commit = self.git.commit_tree(tree, m='message', env=env)
- self.assertEqual(commit, '4cfd6b0314682d5a58f80be39850bad1640e9241')
+ commit = self.git.commit_tree(tree, m="message", env=env)
+ self.assertEqual(commit, "4cfd6b0314682d5a58f80be39850bad1640e9241")
def test_persistent_cat_file_command(self):
# read header only
@@ -124,9 +134,7 @@ class TestGit(TestBase):
obj_info = g.stdout.readline()
# read header + data
- g = self.git.cat_file(
- batch=True, istream=subprocess.PIPE, as_process=True
- )
+ g = self.git.cat_file(batch=True, istream=subprocess.PIPE, as_process=True)
g.stdin.write(b"b2339455342180c7cc1e9bba3e9f181f7baa5167\n")
g.stdin.flush()
obj_info_two = g.stdout.readline()
@@ -161,7 +169,8 @@ class TestGit(TestBase):
try:
# set it to something that doesn't exist, assure it raises
type(self.git).GIT_PYTHON_GIT_EXECUTABLE = osp.join(
- "some", "path", "which", "doesn't", "exist", "gitbinary")
+ "some", "path", "which", "doesn't", "exist", "gitbinary"
+ )
self.assertRaises(exc, self.git.version)
finally:
type(self.git).GIT_PYTHON_GIT_EXECUTABLE = prev_cmd
@@ -173,7 +182,7 @@ class TestGit(TestBase):
# test a good path refresh
which_cmd = "where" if is_win else "which"
- path = os.popen("{0} git".format(which_cmd)).read().strip().split('\n')[0]
+ path = os.popen("{0} git".format(which_cmd)).read().strip().split("\n")[0]
refresh(path)
def test_options_are_passed_to_git(self):
@@ -197,8 +206,10 @@ class TestGit(TestBase):
self.assertRaises(GitCommandError, self.git.NoOp)
def test_single_char_git_options_are_passed_to_git(self):
- input_value = 'TestValue'
- output_value = self.git(c='user.name=%s' % input_value).config('--get', 'user.name')
+ input_value = "TestValue"
+ output_value = self.git(c="user.name=%s" % input_value).config(
+ "--get", "user.name"
+ )
self.assertEqual(input_value, output_value)
def test_change_to_transform_kwargs_does_not_break_command_options(self):
@@ -206,11 +217,13 @@ class TestGit(TestBase):
def test_insert_after_kwarg_raises(self):
# This isn't a complete add command, which doesn't matter here
- self.assertRaises(ValueError, self.git.remote, 'add', insert_kwargs_after='foo')
+ self.assertRaises(ValueError, self.git.remote, "add", insert_kwargs_after="foo")
def test_env_vars_passed_to_git(self):
- editor = 'non_existent_editor'
- with mock.patch.dict('os.environ', {'GIT_EDITOR': editor}): # @UndefinedVariable
+ editor = "non_existent_editor"
+ with mock.patch.dict(
+ "os.environ", {"GIT_EDITOR": editor}
+ ): # @UndefinedVariable
self.assertEqual(self.git.var("GIT_EDITOR"), editor)
@with_rw_directory
@@ -219,35 +232,34 @@ class TestGit(TestBase):
self.assertEqual(self.git.environment(), {})
# make sure the context manager works and cleans up after itself
- with self.git.custom_environment(PWD='/tmp'):
- self.assertEqual(self.git.environment(), {'PWD': '/tmp'})
+ with self.git.custom_environment(PWD="/tmp"):
+ self.assertEqual(self.git.environment(), {"PWD": "/tmp"})
self.assertEqual(self.git.environment(), {})
- old_env = self.git.update_environment(VARKEY='VARVALUE')
+ old_env = self.git.update_environment(VARKEY="VARVALUE")
# The returned dict can be used to revert the change, hence why it has
# an entry with value 'None'.
- self.assertEqual(old_env, {'VARKEY': None})
- self.assertEqual(self.git.environment(), {'VARKEY': 'VARVALUE'})
+ self.assertEqual(old_env, {"VARKEY": None})
+ self.assertEqual(self.git.environment(), {"VARKEY": "VARVALUE"})
new_env = self.git.update_environment(**old_env)
- self.assertEqual(new_env, {'VARKEY': 'VARVALUE'})
+ self.assertEqual(new_env, {"VARKEY": "VARVALUE"})
self.assertEqual(self.git.environment(), {})
- path = osp.join(rw_dir, 'failing-script.sh')
- with open(path, 'wt') as stream:
- stream.write("#!/usr/bin/env sh\n"
- "echo FOO\n")
+ path = osp.join(rw_dir, "failing-script.sh")
+ with open(path, "wt") as stream:
+ stream.write("#!/usr/bin/env sh\n" "echo FOO\n")
os.chmod(path, 0o777)
- rw_repo = Repo.init(osp.join(rw_dir, 'repo'))
- remote = rw_repo.create_remote('ssh-origin', "ssh://git@server/foo")
+ rw_repo = Repo.init(osp.join(rw_dir, "repo"))
+ remote = rw_repo.create_remote("ssh-origin", "ssh://git@server/foo")
with rw_repo.git.custom_environment(GIT_SSH=path):
try:
remote.fetch()
except GitCommandError as err:
- self.assertIn('FOO', str(err))
+ self.assertIn("FOO", str(err))
def test_handle_process_output(self):
from git.cmd import handle_process_output
@@ -261,14 +273,19 @@ class TestGit(TestBase):
def counter_stderr(line):
count[2] += 1
- cmdline = [sys.executable, fixture_path('cat_file.py'), str(fixture_path('issue-301_stderr'))]
- proc = subprocess.Popen(cmdline,
- stdin=None,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- shell=False,
- creationflags=cmd.PROC_CREATIONFLAGS,
- )
+ cmdline = [
+ sys.executable,
+ fixture_path("cat_file.py"),
+ str(fixture_path("issue-301_stderr")),
+ ]
+ proc = subprocess.Popen(
+ cmdline,
+ stdin=None,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ shell=False,
+ creationflags=cmd.PROC_CREATIONFLAGS,
+ )
handle_process_output(proc, counter_stdout, counter_stderr, finalize_process)
diff --git a/test/test_index.py b/test/test_index.py
index 4a20a8f6..3f88f5c5 100644
--- a/test/test_index.py
+++ b/test/test_index.py
@@ -7,10 +7,7 @@
from io import BytesIO
import os
-from stat import (
- S_ISLNK,
- ST_MODE
-)
+from stat import S_ISLNK, ST_MODE
import tempfile
from unittest import skipIf
import shutil
@@ -27,22 +24,11 @@ from git import (
CheckoutError,
)
from git.compat import is_win
-from git.exc import (
- HookExecutionError,
- InvalidGitRepositoryError
-)
+from git.exc import HookExecutionError, InvalidGitRepositoryError
from git.index.fun import hook_path
-from git.index.typ import (
- BaseIndexEntry,
- IndexEntry
-)
+from git.index.typ import BaseIndexEntry, IndexEntry
from git.objects import Blob
-from test.lib import (
- TestBase,
- fixture_path,
- fixture,
- with_rw_repo
-)
+from test.lib import TestBase, fixture_path, fixture, with_rw_repo
from test.lib import with_rw_directory
from git.util import Actor, rmtree
from git.util import HIDE_WINDOWS_KNOWN_ERRORS, hex_to_bin
@@ -53,7 +39,7 @@ from git.cmd import Git
HOOKS_SHEBANG = "#!/usr/bin/env sh\n"
-is_win_without_bash = is_win and not shutil.which('bash.exe')
+is_win_without_bash = is_win and not shutil.which("bash.exe")
def _make_hook(git_dir, name, content, make_exec=True):
@@ -70,7 +56,6 @@ def _make_hook(git_dir, name, content, make_exec=True):
class TestIndex(TestBase):
-
def __init__(self, *args):
super(TestIndex, self).__init__(*args)
self._reset_progress()
@@ -116,8 +101,20 @@ class TestIndex(TestBase):
# test entry
entry = next(iter(index.entries.values()))
- for attr in ("path", "ctime", "mtime", "dev", "inode", "mode", "uid",
- "gid", "size", "binsha", "hexsha", "stage"):
+ for attr in (
+ "path",
+ "ctime",
+ "mtime",
+ "dev",
+ "inode",
+ "mode",
+ "uid",
+ "gid",
+ "size",
+ "binsha",
+ "hexsha",
+ "stage",
+ ):
getattr(entry, attr)
# END for each method
@@ -134,7 +131,7 @@ class TestIndex(TestBase):
# write the data - it must match the original
tmpfile = tempfile.mktemp()
index_merge.write(tmpfile)
- with open(tmpfile, 'rb') as fp:
+ with open(tmpfile, "rb") as fp:
self.assertEqual(fp.read(), fixture("index_merge"))
os.remove(tmpfile)
@@ -144,21 +141,25 @@ class TestIndex(TestBase):
tree = self.rorepo.commit(tree).tree
blist = []
- for blob in tree.traverse(predicate=lambda e, d: e.type == "blob", branch_first=False):
+ for blob in tree.traverse(
+ predicate=lambda e, d: e.type == "blob", branch_first=False
+ ):
assert (blob.path, 0) in index.entries
blist.append(blob)
# END for each blob in tree
if len(blist) != len(index.entries):
iset = {k[0] for k in index.entries.keys()}
bset = {b.path for b in blist}
- raise AssertionError("CMP Failed: Missing entries in index: %s, missing in tree: %s" %
- (bset - iset, iset - bset))
+ raise AssertionError(
+ "CMP Failed: Missing entries in index: %s, missing in tree: %s"
+ % (bset - iset, iset - bset)
+ )
# END assertion message
- @with_rw_repo('0.1.6')
+ @with_rw_repo("0.1.6")
def test_index_lock_handling(self, rw_repo):
def add_bad_blob():
- rw_repo.index.add([Blob(rw_repo, b'f' * 20, 'bad-permissions', 'foo')])
+ rw_repo.index.add([Blob(rw_repo, b"f" * 20, "bad-permissions", "foo")])
try:
## 1st fail on purpose adding into index.
@@ -174,7 +175,7 @@ class TestIndex(TestBase):
except Exception as ex:
assert "index.lock' could not be obtained" not in str(ex)
- @with_rw_repo('0.1.6')
+ @with_rw_repo("0.1.6")
def test_index_file_from_tree(self, rw_repo):
common_ancestor_sha = "5117c9c8a4d3af19a9958677e45cda9269de1541"
cur_sha = "4b43ca7ff72d5f535134241e7c797ddc9c7a3573"
@@ -191,7 +192,9 @@ class TestIndex(TestBase):
self._cmp_tree_index(cur_sha, two_way_index)
# merge three trees - here we have a merge conflict
- three_way_index = IndexFile.from_tree(rw_repo, common_ancestor_sha, cur_sha, other_sha)
+ three_way_index = IndexFile.from_tree(
+ rw_repo, common_ancestor_sha, cur_sha, other_sha
+ )
assert len([e for e in three_way_index.entries.values() if e.stage != 0])
# ITERATE BLOBS
@@ -202,7 +205,7 @@ class TestIndex(TestBase):
assert isinstance(merge_blobs[0][1], Blob)
# test BlobFilter
- prefix = 'lib/git'
+ prefix = "lib/git"
for _stage, blob in base_index.iter_blobs(BlobFilter([prefix])):
assert blob.path.startswith(prefix)
@@ -224,7 +227,7 @@ class TestIndex(TestBase):
# END for each blob
self.assertEqual(num_blobs, len(three_way_index.entries))
- @with_rw_repo('0.1.6')
+ @with_rw_repo("0.1.6")
def test_index_merge_tree(self, rw_repo):
# A bit out of place, but we need a different repo for this:
self.assertNotEqual(self.rorepo, rw_repo)
@@ -234,21 +237,25 @@ class TestIndex(TestBase):
# current index is at the (virtual) cur_commit
next_commit = "4c39f9da792792d4e73fc3a5effde66576ae128c"
parent_commit = rw_repo.head.commit.parents[0]
- manifest_key = IndexFile.entry_key('MANIFEST.in', 0)
+ manifest_key = IndexFile.entry_key("MANIFEST.in", 0)
manifest_entry = rw_repo.index.entries[manifest_key]
rw_repo.index.merge_tree(next_commit)
# only one change should be recorded
assert manifest_entry.binsha != rw_repo.index.entries[manifest_key].binsha
rw_repo.index.reset(rw_repo.head)
- self.assertEqual(rw_repo.index.entries[manifest_key].binsha, manifest_entry.binsha)
+ self.assertEqual(
+ rw_repo.index.entries[manifest_key].binsha, manifest_entry.binsha
+ )
# FAKE MERGE
#############
# Add a change with a NULL sha that should conflict with next_commit. We
# pretend there was a change, but we do not even bother adding a proper
# sha for it ( which makes things faster of course )
- manifest_fake_entry = BaseIndexEntry((manifest_entry[0], b"\0" * 20, 0, manifest_entry[3]))
+ manifest_fake_entry = BaseIndexEntry(
+ (manifest_entry[0], b"\0" * 20, 0, manifest_entry[3])
+ )
# try write flag
self._assert_entries(rw_repo.index.add([manifest_fake_entry], write=False))
# add actually resolves the null-hex-sha for us as a feature, but we can
@@ -267,7 +274,9 @@ class TestIndex(TestBase):
# a three way merge would result in a conflict and fails as the command will
# not overwrite any entries in our index and hence leave them unmerged. This is
# mainly a protection feature as the current index is not yet in a tree
- self.assertRaises(GitCommandError, index.merge_tree, next_commit, base=parent_commit)
+ self.assertRaises(
+ GitCommandError, index.merge_tree, next_commit, base=parent_commit
+ )
# the only way to get the merged entries is to safe the current index away into a tree,
# which is like a temporary commit for us. This fails as well as the NULL sha deos not
@@ -277,7 +286,9 @@ class TestIndex(TestBase):
# if missing objects are okay, this would work though ( they are always okay now )
# As we can't read back the tree with NULL_SHA, we rather set it to something else
- index.entries[manifest_key] = IndexEntry(manifest_entry[:1] + (hex_to_bin('f' * 40),) + manifest_entry[2:])
+ index.entries[manifest_key] = IndexEntry(
+ manifest_entry[:1] + (hex_to_bin("f" * 40),) + manifest_entry[2:]
+ )
tree = index.write_tree()
# now make a proper three way merge with unmerged entries
@@ -286,7 +297,7 @@ class TestIndex(TestBase):
self.assertEqual(len(unmerged_blobs), 1)
self.assertEqual(list(unmerged_blobs.keys())[0], manifest_key[0])
- @with_rw_repo('0.1.6')
+ @with_rw_repo("0.1.6")
def test_index_file_diffing(self, rw_repo):
# default Index instance points to our index
index = IndexFile(rw_repo)
@@ -302,14 +313,14 @@ class TestIndex(TestBase):
# resetting the head will leave the index in a different state, and the
# diff will yield a few changes
cur_head_commit = rw_repo.head.reference.commit
- rw_repo.head.reset('HEAD~6', index=True, working_tree=False)
+ rw_repo.head.reset("HEAD~6", index=True, working_tree=False)
# diff against same index is 0
diff = index.diff()
self.assertEqual(len(diff), 0)
# against HEAD as string, must be the same as it matches index
- diff = index.diff('HEAD')
+ diff = index.diff("HEAD")
self.assertEqual(len(diff), 0)
# against previous head, there must be a difference
@@ -318,9 +329,9 @@ class TestIndex(TestBase):
# we reverse the result
adiff = index.diff(str(cur_head_commit), R=True)
- odiff = index.diff(cur_head_commit, R=False) # now its not reversed anymore
+ odiff = index.diff(cur_head_commit, R=False) # now its not reversed anymore
assert adiff != odiff
- self.assertEqual(odiff, diff) # both unreversed diffs against HEAD
+ self.assertEqual(odiff, diff) # both unreversed diffs against HEAD
# against working copy - its still at cur_commit
wdiff = index.diff(None)
@@ -333,7 +344,7 @@ class TestIndex(TestBase):
# adjust the index to match an old revision
cur_branch = rw_repo.active_branch
cur_commit = cur_branch.commit
- rev_head_parent = 'HEAD~1'
+ rev_head_parent = "HEAD~1"
assert index.reset(rev_head_parent) is index
self.assertEqual(cur_branch, rw_repo.active_branch)
@@ -351,28 +362,28 @@ class TestIndex(TestBase):
assert not index.diff(None)
self.assertEqual(cur_branch, rw_repo.active_branch)
self.assertEqual(cur_commit, rw_repo.head.commit)
- with open(file_path, 'rb') as fp:
+ with open(file_path, "rb") as fp:
assert fp.read() != new_data
# test full checkout
test_file = osp.join(rw_repo.working_tree_dir, "CHANGES")
- with open(test_file, 'ab') as fd:
+ with open(test_file, "ab") as fd:
fd.write(b"some data")
rval = index.checkout(None, force=True, fprogress=self._fprogress)
- assert 'CHANGES' in list(rval)
+ assert "CHANGES" in list(rval)
self._assert_fprogress([None])
assert osp.isfile(test_file)
os.remove(test_file)
rval = index.checkout(None, force=False, fprogress=self._fprogress)
- assert 'CHANGES' in list(rval)
+ assert "CHANGES" in list(rval)
self._assert_fprogress([None])
assert osp.isfile(test_file)
# individual file
os.remove(test_file)
rval = index.checkout(test_file, fprogress=self._fprogress)
- self.assertEqual(list(rval)[0], 'CHANGES')
+ self.assertEqual(list(rval)[0], "CHANGES")
self._assert_fprogress([test_file])
assert osp.exists(test_file)
@@ -394,7 +405,7 @@ class TestIndex(TestBase):
self.assertEqual(len(e.failed_files), len(e.failed_reasons))
self.assertIsInstance(e.failed_reasons[0], str)
self.assertEqual(len(e.valid_files), 0)
- with open(test_file, 'rb') as fd:
+ with open(test_file, "rb") as fd:
s = fd.read()
self.assertTrue(s.endswith(append_data), s)
else:
@@ -402,11 +413,11 @@ class TestIndex(TestBase):
# if we force it it should work
index.checkout(test_file, force=True)
- assert not open(test_file, 'rb').read().endswith(append_data)
+ assert not open(test_file, "rb").read().endswith(append_data)
# checkout directory
rmtree(osp.join(rw_repo.working_tree_dir, "lib"))
- rval = index.checkout('lib')
+ rval = index.checkout("lib")
assert len(list(rval)) > 1
def _count_existing(self, repo, files):
@@ -419,15 +430,18 @@ class TestIndex(TestBase):
existing += osp.isfile(osp.join(basedir, f))
# END for each deleted file
return existing
+
# END num existing helper
- @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and Git.is_cygwin(),
- """FIXME: File "C:\\projects\\gitpython\\git\\test\\test_index.py", line 642, in test_index_mutation
+ @skipIf(
+ HIDE_WINDOWS_KNOWN_ERRORS and Git.is_cygwin(),
+ """FIXME: File "C:\\projects\\gitpython\\git\\test\\test_index.py", line 642, in test_index_mutation
self.assertEqual(fd.read(), link_target)
AssertionError: '!<symlink>\xff\xfe/\x00e\x00t\x00c\x00/\x00t\x00h\x00a\x00t\x00\x00\x00'
!= '/etc/that'
- """)
- @with_rw_repo('0.1.6')
+ """,
+ )
+ @with_rw_repo("0.1.6")
def test_index_mutation(self, rw_repo):
index = rw_repo.index
num_entries = len(index.entries)
@@ -446,7 +460,7 @@ class TestIndex(TestBase):
count = 0
for entry in index.entries.values():
type_id = count % 4
- if type_id == 0: # path
+ if type_id == 0: # path
yield entry.path
elif type_id == 1: # blob
yield Blob(rw_repo, entry.binsha, entry.mode, entry.path)
@@ -458,10 +472,13 @@ class TestIndex(TestBase):
raise AssertionError("Invalid Type")
count += 1
# END for each entry
+
# END mixed iterator
deleted_files = index.remove(mixed_iterator(), working_tree=False)
assert deleted_files
- self.assertEqual(self._count_existing(rw_repo, deleted_files), len(deleted_files))
+ self.assertEqual(
+ self._count_existing(rw_repo, deleted_files), len(deleted_files)
+ )
self.assertEqual(len(index.entries), 0)
# reset the index to undo our changes
@@ -475,13 +492,17 @@ class TestIndex(TestBase):
# reset everything
index.reset(working_tree=True)
- self.assertEqual(self._count_existing(rw_repo, deleted_files), len(deleted_files))
+ self.assertEqual(
+ self._count_existing(rw_repo, deleted_files), len(deleted_files)
+ )
# invalid type
self.assertRaises(TypeError, index.remove, [1])
# absolute path
- deleted_files = index.remove([osp.join(rw_repo.working_tree_dir, "lib")], r=True)
+ deleted_files = index.remove(
+ [osp.join(rw_repo.working_tree_dir, "lib")], r=True
+ )
assert len(deleted_files) > 1
self.assertRaises(ValueError, index.remove, ["/doesnt/exists"])
@@ -506,7 +527,9 @@ class TestIndex(TestBase):
my_author = Actor("Frèderic Çaufl€", "author@example.com")
my_committer = Actor("Committing Frèderic Çaufl€", "committer@example.com")
- commit_actor = index.commit(commit_message, author=my_author, committer=my_committer)
+ commit_actor = index.commit(
+ commit_message, author=my_author, committer=my_committer
+ )
assert cur_commit != commit_actor
self.assertEqual(commit_actor.author.name, "Frèderic Çaufl€")
self.assertEqual(commit_actor.author.email, "author@example.com")
@@ -522,7 +545,11 @@ class TestIndex(TestBase):
cur_commit = cur_head.commit
commit_message = "commit with dates by Avinash Sajjanshetty"
- new_commit = index.commit(commit_message, author_date="2006-04-07T22:13:13", commit_date="2005-04-07T22:13:13")
+ new_commit = index.commit(
+ commit_message,
+ author_date="2006-04-07T22:13:13",
+ commit_date="2005-04-07T22:13:13",
+ )
assert cur_commit != new_commit
print(new_commit.authored_date, new_commit.committed_date)
self.assertEqual(new_commit.message, commit_message)
@@ -538,7 +565,9 @@ class TestIndex(TestBase):
# same index, multiple parents
commit_message = "Index with multiple parents\n commit with another line"
- commit_multi_parent = index.commit(commit_message, parent_commits=(commit_no_parents, new_commit))
+ commit_multi_parent = index.commit(
+ commit_message, parent_commits=(commit_no_parents, new_commit)
+ )
self.assertEqual(commit_multi_parent.message, commit_message)
self.assertEqual(len(commit_multi_parent.parents), 2)
self.assertEqual(commit_multi_parent.parents[0], commit_no_parents)
@@ -547,26 +576,32 @@ class TestIndex(TestBase):
# re-add all files in lib
# get the lib folder back on disk, but get an index without it
- index.reset(new_commit.parents[0], working_tree=True).reset(new_commit, working_tree=False)
+ index.reset(new_commit.parents[0], working_tree=True).reset(
+ new_commit, working_tree=False
+ )
lib_file_path = osp.join("lib", "git", "__init__.py")
assert (lib_file_path, 0) not in index.entries
assert osp.isfile(osp.join(rw_repo.working_tree_dir, lib_file_path))
# directory
- entries = index.add(['lib'], fprogress=self._fprogress_add)
+ entries = index.add(["lib"], fprogress=self._fprogress_add)
self._assert_entries(entries)
self._assert_fprogress(entries)
assert len(entries) > 1
# glob
- entries = index.reset(new_commit).add([osp.join('lib', 'git', '*.py')], fprogress=self._fprogress_add)
+ entries = index.reset(new_commit).add(
+ [osp.join("lib", "git", "*.py")], fprogress=self._fprogress_add
+ )
self._assert_entries(entries)
self._assert_fprogress(entries)
self.assertEqual(len(entries), 14)
# same file
entries = index.reset(new_commit).add(
- [osp.join(rw_repo.working_tree_dir, 'lib', 'git', 'head.py')] * 2, fprogress=self._fprogress_add)
+ [osp.join(rw_repo.working_tree_dir, "lib", "git", "head.py")] * 2,
+ fprogress=self._fprogress_add,
+ )
self._assert_entries(entries)
self.assertEqual(entries[0].mode & 0o644, 0o644)
# would fail, test is too primitive to handle this case
@@ -575,7 +610,9 @@ class TestIndex(TestBase):
self.assertEqual(len(entries), 2)
# missing path
- self.assertRaises(OSError, index.reset(new_commit).add, ['doesnt/exist/must/raise'])
+ self.assertRaises(
+ OSError, index.reset(new_commit).add, ["doesnt/exist/must/raise"]
+ )
# blob from older revision overrides current index revision
old_blob = new_commit.parents[0].tree.blobs[0]
@@ -588,14 +625,19 @@ class TestIndex(TestBase):
# mode 0 not allowed
null_hex_sha = Diff.NULL_HEX_SHA
null_bin_sha = b"\0" * 20
- self.assertRaises(ValueError, index.reset(
- new_commit).add, [BaseIndexEntry((0, null_bin_sha, 0, "doesntmatter"))])
+ self.assertRaises(
+ ValueError,
+ index.reset(new_commit).add,
+ [BaseIndexEntry((0, null_bin_sha, 0, "doesntmatter"))],
+ )
# add new file
new_file_relapath = "my_new_file"
self._make_file(new_file_relapath, "hello world", rw_repo)
entries = index.reset(new_commit).add(
- [BaseIndexEntry((0o10644, null_bin_sha, 0, new_file_relapath))], fprogress=self._fprogress_add)
+ [BaseIndexEntry((0o10644, null_bin_sha, 0, new_file_relapath))],
+ fprogress=self._fprogress_add,
+ )
self._assert_entries(entries)
self._assert_fprogress(entries)
self.assertEqual(len(entries), 1)
@@ -603,20 +645,27 @@ class TestIndex(TestBase):
# add symlink
if not is_win:
- for target in ('/etc/nonexisting', '/etc/passwd', '/etc'):
+ for target in ("/etc/nonexisting", "/etc/passwd", "/etc"):
basename = "my_real_symlink"
link_file = osp.join(rw_repo.working_tree_dir, basename)
os.symlink(target, link_file)
- entries = index.reset(new_commit).add([link_file], fprogress=self._fprogress_add)
+ entries = index.reset(new_commit).add(
+ [link_file], fprogress=self._fprogress_add
+ )
self._assert_entries(entries)
self._assert_fprogress(entries)
self.assertEqual(len(entries), 1)
self.assertTrue(S_ISLNK(entries[0].mode))
- self.assertTrue(S_ISLNK(index.entries[index.entry_key("my_real_symlink", 0)].mode))
+ self.assertTrue(
+ S_ISLNK(index.entries[index.entry_key("my_real_symlink", 0)].mode)
+ )
# we expect only the target to be written
- self.assertEqual(index.repo.odb.stream(entries[0].binsha).read().decode('ascii'), target)
+ self.assertEqual(
+ index.repo.odb.stream(entries[0].binsha).read().decode("ascii"),
+ target,
+ )
os.remove(link_file)
# end for each target
@@ -627,7 +676,9 @@ class TestIndex(TestBase):
link_target = "/etc/that"
fake_symlink_path = self._make_file(fake_symlink_relapath, link_target, rw_repo)
fake_entry = BaseIndexEntry((0o120000, null_bin_sha, 0, fake_symlink_relapath))
- entries = index.reset(new_commit).add([fake_entry], fprogress=self._fprogress_add)
+ entries = index.reset(new_commit).add(
+ [fake_entry], fprogress=self._fprogress_add
+ )
self._assert_entries(entries)
self._assert_fprogress(entries)
assert entries[0].hexsha != null_hex_sha
@@ -635,7 +686,9 @@ class TestIndex(TestBase):
self.assertTrue(S_ISLNK(entries[0].mode))
# assure this also works with an alternate method
- full_index_entry = IndexEntry.from_base(BaseIndexEntry((0o120000, entries[0].binsha, 0, entries[0].path)))
+ full_index_entry = IndexEntry.from_base(
+ BaseIndexEntry((0o120000, entries[0].binsha, 0, entries[0].path))
+ )
entry_key = index.entry_key(full_index_entry)
index.reset(new_commit)
@@ -649,7 +702,7 @@ class TestIndex(TestBase):
# a tree created from this should contain the symlink
tree = index.write_tree()
assert fake_symlink_relapath in tree
- index.write() # flush our changes for the checkout
+ index.write() # flush our changes for the checkout
# checkout the fakelink, should be a link then
assert not S_ISLNK(os.stat(fake_symlink_path)[ST_MODE])
@@ -660,7 +713,7 @@ class TestIndex(TestBase):
if is_win:
# simlinks should contain the link as text ( which is what a
# symlink actually is )
- with open(fake_symlink_path, 'rt') as fd:
+ with open(fake_symlink_path, "rt") as fd:
self.assertEqual(fd.read(), link_target)
else:
self.assertTrue(S_ISLNK(os.lstat(fake_symlink_path)[ST_MODE]))
@@ -670,18 +723,19 @@ class TestIndex(TestBase):
for source, dest in rval:
assert not osp.exists(source) and osp.exists(dest)
# END for each renamed item
+
# END move assertion utility
- self.assertRaises(ValueError, index.move, ['just_one_path'])
+ self.assertRaises(ValueError, index.move, ["just_one_path"])
# file onto existing file
- files = ['AUTHORS', 'LICENSE']
+ files = ["AUTHORS", "LICENSE"]
self.assertRaises(GitCommandError, index.move, files)
# again, with force
assert_mv_rval(index.move(files, f=True))
# files into directory - dry run
- paths = ['LICENSE', 'VERSION', 'doc']
+ paths = ["LICENSE", "VERSION", "doc"]
rval = index.move(paths, dry_run=True)
self.assertEqual(len(rval), 2)
assert osp.exists(paths[0])
@@ -691,7 +745,7 @@ class TestIndex(TestBase):
assert_mv_rval(rval)
# dir into dir
- rval = index.move(['doc', 'test'])
+ rval = index.move(["doc", "test"])
assert_mv_rval(rval)
# TEST PATH REWRITING
@@ -702,21 +756,23 @@ class TestIndex(TestBase):
rval = str(count[0])
count[0] += 1
return rval
+
# END rewriter
def make_paths():
# two existing ones, one new one
- yield 'CHANGES'
- yield 'ez_setup.py'
- yield index.entries[index.entry_key('README', 0)]
- yield index.entries[index.entry_key('.gitignore', 0)]
+ yield "CHANGES"
+ yield "ez_setup.py"
+ yield index.entries[index.entry_key("README", 0)]
+ yield index.entries[index.entry_key(".gitignore", 0)]
for fid in range(3):
- fname = 'newfile%i' % fid
- with open(fname, 'wb') as fd:
+ fname = "newfile%i" % fid
+ with open(fname, "wb") as fd:
fd.write(b"abcd")
yield Blob(rw_repo, Blob.NULL_BIN_SHA, 0o100644, fname)
# END for each new file
+
# END path producer
paths = list(make_paths())
self._assert_entries(index.add(paths, path_rewriter=rewriter))
@@ -762,7 +818,7 @@ class TestIndex(TestBase):
for absfile in absfiles:
assert osp.isfile(absfile)
- @with_rw_repo('HEAD')
+ @with_rw_repo("HEAD")
def test_compare_write_tree(self, rw_repo):
# write all trees and compare them
# its important to have a few submodules in there too
@@ -776,16 +832,16 @@ class TestIndex(TestBase):
orig_tree = commit.tree
self.assertEqual(index.write_tree(), orig_tree)
# END for each commit
-
- @with_rw_repo('HEAD', bare=False)
+
+ @with_rw_repo("HEAD", bare=False)
def test_index_single_addremove(self, rw_repo):
- fp = osp.join(rw_repo.working_dir, 'testfile.txt')
- with open(fp, 'w') as fs:
- fs.write('content of testfile')
+ fp = osp.join(rw_repo.working_dir, "testfile.txt")
+ with open(fp, "w") as fs:
+ fs.write("content of testfile")
self._assert_entries(rw_repo.index.add(fp))
deleted_files = rw_repo.index.remove(fp)
assert deleted_files
-
+
def test_index_new(self):
B = self.rorepo.tree("6d9b1f4f9fa8c9f030e3207e7deacc5d5f8bba4e")
H = self.rorepo.tree("25dca42bac17d511b7e2ebdd9d1d679e7626db5f")
@@ -796,7 +852,7 @@ class TestIndex(TestBase):
assert isinstance(index, IndexFile)
# END for each arg tuple
- @with_rw_repo('HEAD', bare=True)
+ @with_rw_repo("HEAD", bare=True)
def test_index_bare_add(self, rw_bare_repo):
# Something is wrong after cloning to a bare repo, reading the
# property rw_bare_repo.working_tree_dir will return '/tmp'
@@ -804,12 +860,11 @@ class TestIndex(TestBase):
# a quick hack to make this test fail when expected.
assert rw_bare_repo.working_tree_dir is None
assert rw_bare_repo.bare
- contents = b'This is a BytesIO file'
+ contents = b"This is a BytesIO file"
filesize = len(contents)
fileobj = BytesIO(contents)
- filename = 'my-imaginary-file'
- istream = rw_bare_repo.odb.store(
- IStream(Blob.type, filesize, fileobj))
+ filename = "my-imaginary-file"
+ istream = rw_bare_repo.odb.store(IStream(Blob.type, filesize, fileobj))
entry = BaseIndexEntry((0o100644, istream.binsha, 0, filename))
try:
rw_bare_repo.index.add([entry])
@@ -818,7 +873,7 @@ class TestIndex(TestBase):
# Adding using a path should still require a non-bare repository.
asserted = False
- path = osp.join('git', 'test', 'test_index.py')
+ path = osp.join("git", "test", "test_index.py")
try:
rw_bare_repo.index.add([path])
except InvalidGitRepositoryError:
@@ -828,24 +883,24 @@ class TestIndex(TestBase):
@with_rw_directory
def test_add_utf8P_path(self, rw_dir):
# NOTE: fp is not a Unicode object in python 2 (which is the source of the problem)
- fp = osp.join(rw_dir, 'ø.txt')
- with open(fp, 'wb') as fs:
- fs.write('content of ø'.encode('utf-8'))
+ fp = osp.join(rw_dir, "ø.txt")
+ with open(fp, "wb") as fs:
+ fs.write("content of ø".encode("utf-8"))
r = Repo.init(rw_dir)
r.index.add([fp])
- r.index.commit('Added orig and prestable')
+ r.index.commit("Added orig and prestable")
@with_rw_directory
def test_add_a_file_with_wildcard_chars(self, rw_dir):
# see issue #407
- fp = osp.join(rw_dir, '[.exe')
+ fp = osp.join(rw_dir, "[.exe")
with open(fp, "wb") as f:
- f.write(b'something')
+ f.write(b"something")
r = Repo.init(rw_dir)
r.index.add([fp])
- r.index.commit('Added [.exe')
+ r.index.commit("Added [.exe")
def test__to_relative_path_at_root(self):
root = osp.abspath(os.sep)
@@ -856,29 +911,23 @@ class TestIndex(TestBase):
working_tree_dir = root
repo = Mocked()
- path = os.path.join(root, 'file')
+ path = os.path.join(root, "file")
index = IndexFile(repo)
rel = index._to_relative_path(path)
self.assertEqual(rel, os.path.relpath(path, root))
- @with_rw_repo('HEAD', bare=True)
+ @with_rw_repo("HEAD", bare=True)
def test_pre_commit_hook_success(self, rw_repo):
index = rw_repo.index
- _make_hook(
- index.repo.git_dir,
- 'pre-commit',
- "exit 0"
- )
+ _make_hook(index.repo.git_dir, "pre-commit", "exit 0")
index.commit("This should not fail")
- @with_rw_repo('HEAD', bare=True)
+ @with_rw_repo("HEAD", bare=True)
def test_pre_commit_hook_fail(self, rw_repo):
index = rw_repo.index
hp = _make_hook(
- index.repo.git_dir,
- 'pre-commit',
- "echo stdout; echo stderr 1>&2; exit 1"
+ index.repo.git_dir, "pre-commit", "echo stdout; echo stderr 1>&2; exit 1"
)
try:
index.commit("This should fail")
@@ -886,8 +935,8 @@ class TestIndex(TestBase):
if is_win_without_bash:
self.assertIsInstance(err.status, OSError)
self.assertEqual(err.command, [hp])
- self.assertEqual(err.stdout, '')
- self.assertEqual(err.stderr, '')
+ self.assertEqual(err.stdout, "")
+ self.assertEqual(err.stderr, "")
assert str(err)
else:
self.assertEqual(err.status, 1)
@@ -899,26 +948,26 @@ class TestIndex(TestBase):
raise AssertionError("Should have caught a HookExecutionError")
@skipIf(HIDE_WINDOWS_KNOWN_ERRORS, "TODO: fix hooks execution on Windows: #703")
- @with_rw_repo('HEAD', bare=True)
+ @with_rw_repo("HEAD", bare=True)
def test_commit_msg_hook_success(self, rw_repo):
commit_message = "commit default head by Frèderic Çaufl€"
from_hook_message = "from commit-msg"
index = rw_repo.index
_make_hook(
index.repo.git_dir,
- 'commit-msg',
- 'printf " {}" >> "$1"'.format(from_hook_message)
+ "commit-msg",
+ 'printf " {}" >> "$1"'.format(from_hook_message),
)
new_commit = index.commit(commit_message)
- self.assertEqual(new_commit.message, "{} {}".format(commit_message, from_hook_message))
+ self.assertEqual(
+ new_commit.message, "{} {}".format(commit_message, from_hook_message)
+ )
- @with_rw_repo('HEAD', bare=True)
+ @with_rw_repo("HEAD", bare=True)
def test_commit_msg_hook_fail(self, rw_repo):
index = rw_repo.index
hp = _make_hook(
- index.repo.git_dir,
- 'commit-msg',
- "echo stdout; echo stderr 1>&2; exit 1"
+ index.repo.git_dir, "commit-msg", "echo stdout; echo stderr 1>&2; exit 1"
)
try:
index.commit("This should fail")
@@ -926,8 +975,8 @@ class TestIndex(TestBase):
if is_win_without_bash:
self.assertIsInstance(err.status, OSError)
self.assertEqual(err.command, [hp])
- self.assertEqual(err.stdout, '')
- self.assertEqual(err.stderr, '')
+ self.assertEqual(err.stdout, "")
+ self.assertEqual(err.stderr, "")
assert str(err)
else:
self.assertEqual(err.status, 1)
diff --git a/test/test_installation.py b/test/test_installation.py
index 6117be98..2607ff4e 100644
--- a/test/test_installation.py
+++ b/test/test_installation.py
@@ -11,9 +11,9 @@ from test.lib.helper import with_rw_directory
class TestInstallation(TestBase):
def setUp_venv(self, rw_dir):
self.venv = rw_dir
- subprocess.run(['virtualenv', self.venv], stdout=subprocess.PIPE)
- self.python = os.path.join(self.venv, 'bin/python3')
- self.pip = os.path.join(self.venv, 'bin/pip3')
+ subprocess.run(["virtualenv", self.venv], stdout=subprocess.PIPE)
+ self.python = os.path.join(self.venv, "bin/python3")
+ self.pip = os.path.join(self.venv, "bin/pip3")
self.sources = os.path.join(self.venv, "src")
self.cwd = os.path.dirname(os.path.dirname(__file__))
os.symlink(self.cwd, self.sources, target_is_directory=True)
@@ -21,17 +21,46 @@ class TestInstallation(TestBase):
@with_rw_directory
def test_installation(self, rw_dir):
self.setUp_venv(rw_dir)
- result = subprocess.run([self.pip, 'install', '-r', 'requirements.txt'],
- stdout=subprocess.PIPE, cwd=self.sources)
- self.assertEqual(0, result.returncode, msg=result.stderr or result.stdout or "Can't install requirements")
- result = subprocess.run([self.python, 'setup.py', 'install'], stdout=subprocess.PIPE, cwd=self.sources)
- self.assertEqual(0, result.returncode, msg=result.stderr or result.stdout or "Can't build - setup.py failed")
- result = subprocess.run([self.python, '-c', 'import git'], stdout=subprocess.PIPE, cwd=self.sources)
- self.assertEqual(0, result.returncode, msg=result.stderr or result.stdout or "Selftest failed")
- result = subprocess.run([self.python, '-c', 'import sys;import git; print(sys.path)'],
- stdout=subprocess.PIPE, cwd=self.sources)
- syspath = result.stdout.decode('utf-8').splitlines()[0]
+ result = subprocess.run(
+ [self.pip, "install", "-r", "requirements.txt"],
+ stdout=subprocess.PIPE,
+ cwd=self.sources,
+ )
+ self.assertEqual(
+ 0,
+ result.returncode,
+ msg=result.stderr or result.stdout or "Can't install requirements",
+ )
+ result = subprocess.run(
+ [self.python, "setup.py", "install"],
+ stdout=subprocess.PIPE,
+ cwd=self.sources,
+ )
+ self.assertEqual(
+ 0,
+ result.returncode,
+ msg=result.stderr or result.stdout or "Can't build - setup.py failed",
+ )
+ result = subprocess.run(
+ [self.python, "-c", "import git"], stdout=subprocess.PIPE, cwd=self.sources
+ )
+ self.assertEqual(
+ 0,
+ result.returncode,
+ msg=result.stderr or result.stdout or "Selftest failed",
+ )
+ result = subprocess.run(
+ [self.python, "-c", "import sys;import git; print(sys.path)"],
+ stdout=subprocess.PIPE,
+ cwd=self.sources,
+ )
+ syspath = result.stdout.decode("utf-8").splitlines()[0]
syspath = ast.literal_eval(syspath)
- self.assertEqual('', syspath[0],
- msg='Failed to follow the conventions for https://docs.python.org/3/library/sys.html#sys.path')
- self.assertTrue(syspath[1].endswith('gitdb'), msg='Failed to add gitdb to sys.path')
+ self.assertEqual(
+ "",
+ syspath[0],
+ msg="Failed to follow the conventions for https://docs.python.org/3/library/sys.html#sys.path",
+ )
+ self.assertTrue(
+ syspath[1].endswith("gitdb"), msg="Failed to add gitdb to sys.path"
+ )
diff --git a/test/test_reflog.py b/test/test_reflog.py
index a6c15950..c126d3dc 100644
--- a/test/test_reflog.py
+++ b/test/test_reflog.py
@@ -2,28 +2,23 @@ import os
import tempfile
from git.objects import IndexObject
-from git.refs import (
- RefLogEntry,
- RefLog
-)
-from test.lib import (
- TestBase,
- fixture_path
-)
+from git.refs import RefLogEntry, RefLog
+from test.lib import TestBase, fixture_path
from git.util import Actor, rmtree, hex_to_bin
import os.path as osp
class TestRefLog(TestBase):
-
def test_reflogentry(self):
nullhexsha = IndexObject.NULL_HEX_SHA
- hexsha = 'F' * 40
- actor = Actor('name', 'email')
+ hexsha = "F" * 40
+ actor = Actor("name", "email")
msg = "message"
- self.assertRaises(ValueError, RefLogEntry.new, nullhexsha, hexsha, 'noactor', 0, 0, "")
+ self.assertRaises(
+ ValueError, RefLogEntry.new, nullhexsha, hexsha, "noactor", 0, 0, ""
+ )
e = RefLogEntry.new(nullhexsha, hexsha, actor, 0, 1, msg)
assert e.oldhexsha == nullhexsha
@@ -37,8 +32,8 @@ class TestRefLog(TestBase):
assert repr(e).startswith(nullhexsha)
def test_base(self):
- rlp_head = fixture_path('reflog_HEAD')
- rlp_master = fixture_path('reflog_master')
+ rlp_head = fixture_path("reflog_HEAD")
+ rlp_master = fixture_path("reflog_master")
tdir = tempfile.mktemp(suffix="test_reflogs")
os.mkdir(tdir)
@@ -52,13 +47,13 @@ class TestRefLog(TestBase):
assert len(reflog)
# iter_entries works with path and with stream
- assert len(list(RefLog.iter_entries(open(rlp_master, 'rb'))))
+ assert len(list(RefLog.iter_entries(open(rlp_master, "rb"))))
assert len(list(RefLog.iter_entries(rlp_master)))
# raise on invalid revlog
# TODO: Try multiple corrupted ones !
- pp = 'reflog_invalid_'
- for suffix in ('oldsha', 'newsha', 'email', 'date', 'sep'):
+ pp = "reflog_invalid_"
+ for suffix in ("oldsha", "newsha", "email", "date", "sep"):
self.assertRaises(ValueError, RefLog.from_file, fixture_path(pp + suffix))
# END for each invalid file
@@ -66,7 +61,7 @@ class TestRefLog(TestBase):
self.assertRaises(ValueError, RefLog().write)
# test serialize and deserialize - results must match exactly
- binsha = hex_to_bin(('f' * 40).encode('ascii'))
+ binsha = hex_to_bin(("f" * 40).encode("ascii"))
msg = "my reflog message"
cr = self.rorepo.config_reader()
for rlp in (rlp_head, rlp_master):
@@ -83,9 +78,11 @@ class TestRefLog(TestBase):
assert open(tfile).read() == open(rlp).read()
# append an entry
- entry = RefLog.append_entry(cr, tfile, IndexObject.NULL_BIN_SHA, binsha, msg)
+ entry = RefLog.append_entry(
+ cr, tfile, IndexObject.NULL_BIN_SHA, binsha, msg
+ )
assert entry.oldhexsha == IndexObject.NULL_HEX_SHA
- assert entry.newhexsha == 'f' * 40
+ assert entry.newhexsha == "f" * 40
assert entry.message == msg
assert RefLog.from_file(tfile)[-1] == entry
diff --git a/test/test_refs.py b/test/test_refs.py
index ab760a6f..ee4ec86f 100644
--- a/test/test_refs.py
+++ b/test/test_refs.py
@@ -14,13 +14,10 @@ from git import (
Commit,
SymbolicReference,
GitCommandError,
- RefLog
+ RefLog,
)
from git.objects.tag import TagObject
-from test.lib import (
- TestBase,
- with_rw_repo
-)
+from test.lib import TestBase, with_rw_repo
from git.util import Actor
import git.refs as refs
@@ -28,11 +25,10 @@ import os.path as osp
class TestRefs(TestBase):
-
def test_from_path(self):
# should be able to create any reference directly
for ref_type in (Reference, Head, TagReference, RemoteReference):
- for name in ('rela_name', 'path/rela_name'):
+ for name in ("rela_name", "path/rela_name"):
full_path = ref_type.to_full_path(name)
instance = ref_type.from_path(self.rorepo, full_path)
assert isinstance(instance, ref_type)
@@ -54,7 +50,7 @@ class TestRefs(TestBase):
tag_object_refs.append(tag)
tagobj = tag.tag
# have no dict
- self.assertRaises(AttributeError, setattr, tagobj, 'someattr', 1)
+ self.assertRaises(AttributeError, setattr, tagobj, "someattr", 1)
assert isinstance(tagobj, TagObject)
assert tagobj.tag == tag.name
assert isinstance(tagobj.tagger, Actor)
@@ -63,18 +59,18 @@ class TestRefs(TestBase):
assert tagobj.message
assert tag.object == tagobj
# can't assign the object
- self.assertRaises(AttributeError, setattr, tag, 'object', tagobj)
+ self.assertRaises(AttributeError, setattr, tag, "object", tagobj)
# END if we have a tag object
# END for tag in repo-tags
assert tag_object_refs
- assert isinstance(self.rorepo.tags['0.1.5'], TagReference)
+ assert isinstance(self.rorepo.tags["0.1.5"], TagReference)
def test_tags_author(self):
tag = self.rorepo.tags[0]
tagobj = tag.tag
assert isinstance(tagobj.tagger, Actor)
tagger_name = tagobj.tagger.name
- assert tagger_name == 'Michael Trier'
+ assert tagger_name == "Michael Trier"
def test_tags(self):
# tag refs can point to tag objects or to commits
@@ -92,7 +88,7 @@ class TestRefs(TestBase):
assert len(s) == ref_count
assert len(s | s) == ref_count
- @with_rw_repo('HEAD', bare=False)
+ @with_rw_repo("HEAD", bare=False)
def test_heads(self, rwrepo):
for head in rwrepo.heads:
assert head.name
@@ -100,8 +96,8 @@ class TestRefs(TestBase):
assert "refs/heads" in head.path
prev_object = head.object
cur_object = head.object
- assert prev_object == cur_object # represent the same git object
- assert prev_object is not cur_object # but are different instances
+ assert prev_object == cur_object # represent the same git object
+ assert prev_object is not cur_object # but are different instances
with head.config_writer() as writer:
tv = "testopt"
@@ -120,17 +116,23 @@ class TestRefs(TestBase):
head.set_tracking_branch(None)
assert head.tracking_branch() is None
- special_name = 'feature#123'
- special_name_remote_ref = SymbolicReference.create(rwrepo, 'refs/remotes/origin/%s' % special_name)
- gp_tracking_branch = rwrepo.create_head('gp_tracking#123')
- special_name_remote_ref = rwrepo.remotes[0].refs[special_name] # get correct type
+ special_name = "feature#123"
+ special_name_remote_ref = SymbolicReference.create(
+ rwrepo, "refs/remotes/origin/%s" % special_name
+ )
+ gp_tracking_branch = rwrepo.create_head("gp_tracking#123")
+ special_name_remote_ref = rwrepo.remotes[0].refs[
+ special_name
+ ] # get correct type
gp_tracking_branch.set_tracking_branch(special_name_remote_ref)
TBranch = gp_tracking_branch.tracking_branch()
if TBranch is not None:
assert TBranch.path == special_name_remote_ref.path
- git_tracking_branch = rwrepo.create_head('git_tracking#123')
- rwrepo.git.branch('-u', special_name_remote_ref.name, git_tracking_branch.name)
+ git_tracking_branch = rwrepo.create_head("git_tracking#123")
+ rwrepo.git.branch(
+ "-u", special_name_remote_ref.name, git_tracking_branch.name
+ )
TBranch = gp_tracking_branch.tracking_branch()
if TBranch is not None:
assert TBranch.name == special_name_remote_ref.name
@@ -143,7 +145,7 @@ class TestRefs(TestBase):
pcommit = cur_head.commit.parents[0].parents[0]
hlog_len = len(head.log())
blog_len = len(cur_head.log())
- assert head.set_reference(pcommit, 'detached head') is head
+ assert head.set_reference(pcommit, "detached head") is head
# one new log-entry
thlog = head.log()
assert len(thlog) == hlog_len + 1
@@ -154,23 +156,25 @@ class TestRefs(TestBase):
assert len(cur_head.log()) == blog_len
# head changes once again, cur_head doesn't change
- head.set_reference(cur_head, 'reattach head')
+ head.set_reference(cur_head, "reattach head")
assert len(head.log()) == hlog_len + 2
assert len(cur_head.log()) == blog_len
# adjusting the head-ref also adjust the head, so both reflogs are
# altered
- cur_head.set_commit(pcommit, 'changing commit')
+ cur_head.set_commit(pcommit, "changing commit")
assert len(cur_head.log()) == blog_len + 1
assert len(head.log()) == hlog_len + 3
# with automatic dereferencing
- assert head.set_commit(cur_commit, 'change commit once again') is head
+ assert head.set_commit(cur_commit, "change commit once again") is head
assert len(head.log()) == hlog_len + 4
assert len(cur_head.log()) == blog_len + 2
# a new branch has just a single entry
- other_head = Head.create(rwrepo, 'mynewhead', pcommit, logmsg='new head created')
+ other_head = Head.create(
+ rwrepo, "mynewhead", pcommit, logmsg="new head created"
+ )
log = other_head.log()
assert len(log) == 1
assert log[0].oldhexsha == pcommit.NULL_HEX_SHA
@@ -183,21 +187,21 @@ class TestRefs(TestBase):
assert len(types_found) >= 3
def test_is_valid(self):
- assert not Reference(self.rorepo, 'refs/doesnt/exist').is_valid()
+ assert not Reference(self.rorepo, "refs/doesnt/exist").is_valid()
assert self.rorepo.head.is_valid()
assert self.rorepo.head.reference.is_valid()
- assert not SymbolicReference(self.rorepo, 'hellothere').is_valid()
+ assert not SymbolicReference(self.rorepo, "hellothere").is_valid()
def test_orig_head(self):
assert type(self.rorepo.head.orig_head()) == SymbolicReference
- @with_rw_repo('0.1.6')
+ @with_rw_repo("0.1.6")
def test_head_checkout_detached_head(self, rw_repo):
res = rw_repo.remotes.origin.refs.master.checkout()
assert isinstance(res, SymbolicReference)
- assert res.name == 'HEAD'
+ assert res.name == "HEAD"
- @with_rw_repo('0.1.6')
+ @with_rw_repo("0.1.6")
def test_head_reset(self, rw_repo):
cur_head = rw_repo.head
old_head_commit = cur_head.commit
@@ -205,7 +209,9 @@ class TestRefs(TestBase):
cur_head.reset(new_head_commit, index=True) # index only
assert cur_head.reference.commit == new_head_commit
- self.assertRaises(ValueError, cur_head.reset, new_head_commit, index=False, working_tree=True)
+ self.assertRaises(
+ ValueError, cur_head.reset, new_head_commit, index=False, working_tree=True
+ )
new_head_commit = new_head_commit.parents[0]
cur_head.reset(new_head_commit, index=True, working_tree=True) # index + wt
assert cur_head.reference.commit == new_head_commit
@@ -215,7 +221,13 @@ class TestRefs(TestBase):
cur_head.reset(cur_head, paths="test")
cur_head.reset(new_head_commit, paths="lib")
# hard resets with paths don't work, its all or nothing
- self.assertRaises(GitCommandError, cur_head.reset, new_head_commit, working_tree=True, paths="lib")
+ self.assertRaises(
+ GitCommandError,
+ cur_head.reset,
+ new_head_commit,
+ working_tree=True,
+ paths="lib",
+ )
# we can do a mixed reset, and then checkout from the index though
cur_head.reset(new_head_commit)
@@ -255,7 +267,7 @@ class TestRefs(TestBase):
self.assertRaises(ValueError, setattr, cur_head, "reference", "that")
# head handling
- commit = 'HEAD'
+ commit = "HEAD"
prev_head_commit = cur_head.commit
for count, new_name in enumerate(("my_new_head", "feature/feature1")):
actual_commit = commit + "^" * count
@@ -267,7 +279,9 @@ class TestRefs(TestBase):
Head.create(rw_repo, new_name, new_head.commit)
# its not fine with a different value
- self.assertRaises(OSError, Head.create, rw_repo, new_name, new_head.commit.parents[0])
+ self.assertRaises(
+ OSError, Head.create, rw_repo, new_name, new_head.commit.parents[0]
+ )
# force it
new_head = Head.create(rw_repo, new_name, actual_commit, force=True)
@@ -276,7 +290,9 @@ class TestRefs(TestBase):
assert new_head.rename("hello").name == "hello"
assert new_head.rename("hello/world").name == "hello/world"
- assert new_head.rename(old_name).name == old_name and new_head.path == old_path
+ assert (
+ new_head.rename(old_name).name == old_name and new_head.path == old_path
+ )
# rename with force
tmp_head = Head.create(rw_repo, "tmphead")
@@ -330,7 +346,7 @@ class TestRefs(TestBase):
remote_head_name = "HEAD"
if remote_head_name in refs:
RemoteReference.delete(rw_repo, refs[remote_head_name])
- del(refs[remote_head_name])
+ del refs[remote_head_name]
# END handle HEAD deletion
RemoteReference.delete(rw_repo, *refs)
@@ -358,13 +374,13 @@ class TestRefs(TestBase):
# setting a non-commit as commit fails, but succeeds as object
head_tree = head.commit.tree
- self.assertRaises(ValueError, setattr, head, 'commit', head_tree)
- assert head.commit == old_commit # and the ref did not change
+ self.assertRaises(ValueError, setattr, head, "commit", head_tree)
+ assert head.commit == old_commit # and the ref did not change
# we allow heds to point to any object
head.object = head_tree
assert head.object == head_tree
# cannot query tree as commit
- self.assertRaises(TypeError, getattr, head, 'commit')
+ self.assertRaises(TypeError, getattr, head, "commit")
# set the commit directly using the head. This would never detach the head
assert not cur_head.is_detached
@@ -396,25 +412,25 @@ class TestRefs(TestBase):
# checkout with force as we have a changed a file
# clear file
- open(new_head.commit.tree.blobs[-1].abspath, 'w').close()
+ open(new_head.commit.tree.blobs[-1].abspath, "w").close()
assert len(new_head.commit.diff(None))
# create a new branch that is likely to touch the file we changed
- far_away_head = rw_repo.create_head("far_head", 'HEAD~100')
+ far_away_head = rw_repo.create_head("far_head", "HEAD~100")
self.assertRaises(GitCommandError, far_away_head.checkout)
assert active_branch == active_branch.checkout(force=True)
assert rw_repo.head.reference != far_away_head
# test reference creation
- partial_ref = 'sub/ref'
- full_ref = 'refs/%s' % partial_ref
+ partial_ref = "sub/ref"
+ full_ref = "refs/%s" % partial_ref
ref = Reference.create(rw_repo, partial_ref)
assert ref.path == full_ref
assert ref.object == rw_repo.head.commit
- self.assertRaises(OSError, Reference.create, rw_repo, full_ref, 'HEAD~20')
+ self.assertRaises(OSError, Reference.create, rw_repo, full_ref, "HEAD~20")
# it works if it is at the same spot though and points to the same reference
- assert Reference.create(rw_repo, full_ref, 'HEAD').path == full_ref
+ assert Reference.create(rw_repo, full_ref, "HEAD").path == full_ref
Reference.delete(rw_repo, full_ref)
# recreate the reference using a full_ref
@@ -423,13 +439,13 @@ class TestRefs(TestBase):
assert ref.object == rw_repo.head.commit
# recreate using force
- ref = Reference.create(rw_repo, partial_ref, 'HEAD~1', force=True)
+ ref = Reference.create(rw_repo, partial_ref, "HEAD~1", force=True)
assert ref.path == full_ref
assert ref.object == rw_repo.head.commit.parents[0]
# rename it
orig_obj = ref.object
- for name in ('refs/absname', 'rela_name', 'feature/rela_name'):
+ for name in ("refs/absname", "rela_name", "feature/rela_name"):
ref_new_name = ref.rename(name)
assert isinstance(ref_new_name, Reference)
assert name in ref_new_name.path
@@ -438,7 +454,9 @@ class TestRefs(TestBase):
# END for each name type
# References that don't exist trigger an error if we want to access them
- self.assertRaises(ValueError, getattr, Reference(rw_repo, "refs/doesntexist"), 'commit')
+ self.assertRaises(
+ ValueError, getattr, Reference(rw_repo, "refs/doesntexist"), "commit"
+ )
# exists, fail unless we force
ex_ref_path = far_away_head.path
@@ -455,9 +473,18 @@ class TestRefs(TestBase):
assert symref.path == symref_path
assert symref.reference == cur_head.reference
- self.assertRaises(OSError, SymbolicReference.create, rw_repo, symref_path, cur_head.reference.commit)
+ self.assertRaises(
+ OSError,
+ SymbolicReference.create,
+ rw_repo,
+ symref_path,
+ cur_head.reference.commit,
+ )
# it works if the new ref points to the same reference
- assert SymbolicReference.create(rw_repo, symref.path, symref.reference).path == symref.path # @NoEffect
+ assert (
+ SymbolicReference.create(rw_repo, symref.path, symref.reference).path
+ == symref.path
+ ) # @NoEffect
SymbolicReference.delete(rw_repo, symref)
# would raise if the symref wouldn't have been deletedpbl
symref = SymbolicReference.create(rw_repo, symref_path, cur_head.reference)
@@ -475,7 +502,7 @@ class TestRefs(TestBase):
assert osp.isfile(symbol_ref_abspath)
assert symref.commit == new_head.commit
- for name in ('absname', 'folder/rela_name'):
+ for name in ("absname", "folder/rela_name"):
symref_new_name = symref.rename(name)
assert isinstance(symref_new_name, SymbolicReference)
assert name in symref_new_name.path
@@ -524,7 +551,7 @@ class TestRefs(TestBase):
rw_repo.head.reference = Head.create(rw_repo, "master")
# At least the head should still exist
- assert osp.isfile(osp.join(rw_repo.git_dir, 'HEAD'))
+ assert osp.isfile(osp.join(rw_repo.git_dir, "HEAD"))
refs = list(SymbolicReference.iter_items(rw_repo))
assert len(refs) == 1
@@ -545,7 +572,7 @@ class TestRefs(TestBase):
# if the assignment raises, the ref doesn't exist
Reference.delete(ref.repo, ref.path)
assert not ref.is_valid()
- self.assertRaises(ValueError, setattr, ref, 'commit', "nonsense")
+ self.assertRaises(ValueError, setattr, ref, "commit", "nonsense")
assert not ref.is_valid()
# I am sure I had my reason to make it a class method at first, but
@@ -559,14 +586,14 @@ class TestRefs(TestBase):
Reference.delete(ref.repo, ref.path)
assert not ref.is_valid()
- self.assertRaises(ValueError, setattr, ref, 'object', "nonsense")
+ self.assertRaises(ValueError, setattr, ref, "object", "nonsense")
assert not ref.is_valid()
# END for each path
def test_dereference_recursive(self):
# for now, just test the HEAD
- assert SymbolicReference.dereference_recursive(self.rorepo, 'HEAD')
+ assert SymbolicReference.dereference_recursive(self.rorepo, "HEAD")
def test_reflog(self):
assert isinstance(self.rorepo.heads.master.log(), RefLog)
diff --git a/test/test_remote.py b/test/test_remote.py
index 761a7a3e..53f71e3d 100644
--- a/test/test_remote.py
+++ b/test/test_remote.py
@@ -20,7 +20,7 @@ from git import (
RemoteReference,
TagReference,
Remote,
- GitCommandError
+ GitCommandError,
)
from git.cmd import Git
from test.lib import (
@@ -28,7 +28,7 @@ from test.lib import (
with_rw_repo,
with_rw_and_rw_remote_repo,
fixture,
- GIT_DAEMON_PORT
+ GIT_DAEMON_PORT,
)
from git.util import rmtree, HIDE_WINDOWS_FREEZE_ERRORS, IterableList
import os.path as osp
@@ -39,7 +39,7 @@ random.seed(0)
class TestRemoteProgress(RemoteProgress):
- __slots__ = ("_seen_lines", "_stages_per_op", '_num_progress_messages')
+ __slots__ = ("_seen_lines", "_stages_per_op", "_num_progress_messages")
def __init__(self):
super(TestRemoteProgress, self).__init__()
@@ -60,21 +60,27 @@ class TestRemoteProgress(RemoteProgress):
except ValueError:
pass
- def update(self, op_code, cur_count, max_count=None, message=''):
+ def update(self, op_code, cur_count, max_count=None, message=""):
# check each stage only comes once
op_id = op_code & self.OP_MASK
assert op_id in (self.COUNTING, self.COMPRESSING, self.WRITING)
if op_code & self.WRITING > 0:
if op_code & self.BEGIN > 0:
- assert not message, 'should not have message when remote begins writing'
+ assert not message, "should not have message when remote begins writing"
elif op_code & self.END > 0:
assert message
- assert not message.startswith(', '), "Sanitize progress messages: '%s'" % message
- assert not message.endswith(', '), "Sanitize progress messages: '%s'" % message
+ assert not message.startswith(", "), (
+ "Sanitize progress messages: '%s'" % message
+ )
+ assert not message.endswith(", "), (
+ "Sanitize progress messages: '%s'" % message
+ )
self._stages_per_op.setdefault(op_id, 0)
- self._stages_per_op[op_id] = self._stages_per_op[op_id] | (op_code & self.STAGE_MASK)
+ self._stages_per_op[op_id] = self._stages_per_op[op_id] | (
+ op_code & self.STAGE_MASK
+ )
if op_code & (self.WRITING | self.END) == (self.WRITING | self.END):
assert message
@@ -101,9 +107,9 @@ class TestRemoteProgress(RemoteProgress):
class TestRemote(TestBase):
-
def tearDown(self):
import gc
+
gc.collect()
def _print_fetchhead(self, repo):
@@ -140,7 +146,11 @@ class TestRemote(TestBase):
self.assertIsInstance(info.old_commit, Commit)
if info.flags & info.ERROR:
has_one = False
- for bitflag in (info.REJECTED, info.REMOTE_REJECTED, info.REMOTE_FAILURE):
+ for bitflag in (
+ info.REJECTED,
+ info.REMOTE_REJECTED,
+ info.REMOTE_FAILURE,
+ ):
has_one |= bool(info.flags & bitflag)
# END for each bitflag
self.assertTrue(has_one)
@@ -161,15 +171,22 @@ class TestRemote(TestBase):
results.raise_if_error()
def _do_test_fetch_info(self, repo):
- self.assertRaises(ValueError, FetchInfo._from_line, repo, "nonsense", '')
+ self.assertRaises(ValueError, FetchInfo._from_line, repo, "nonsense", "")
self.assertRaises(
- ValueError, FetchInfo._from_line, repo, "? [up to date] 0.1.7RC -> origin/0.1.7RC", '')
+ ValueError,
+ FetchInfo._from_line,
+ repo,
+ "? [up to date] 0.1.7RC -> origin/0.1.7RC",
+ "",
+ )
def _commit_random_file(self, repo):
# Create a file with a random name and random data and commit it to repo.
# Return the committed absolute file path
index = repo.index
- new_file = self._make_file(osp.basename(tempfile.mktemp()), str(random.random()), repo)
+ new_file = self._make_file(
+ osp.basename(tempfile.mktemp()), str(random.random()), repo
+ )
index.add([new_file])
index.commit("Committing %s" % new_file)
return new_file
@@ -180,11 +197,12 @@ class TestRemote(TestBase):
def fetch_and_test(remote, **kwargs):
progress = TestRemoteProgress()
- kwargs['progress'] = progress
+ kwargs["progress"] = progress
res = remote.fetch(**kwargs)
progress.make_assertion()
self._do_test_fetch_result(res, remote)
return res
+
# END fetch and check
def get_info(res, remote, name):
@@ -204,7 +222,7 @@ class TestRemote(TestBase):
remote_commit = rhead.commit
rhead.reset("HEAD~2", index=False)
res = fetch_and_test(remote)
- mkey = "%s/%s" % (remote, 'master')
+ mkey = "%s/%s" % (remote, "master")
master_info = res[mkey]
self.assertTrue(master_info.flags & FetchInfo.FORCED_UPDATE)
self.assertIsNotNone(master_info.note)
@@ -241,10 +259,10 @@ class TestRemote(TestBase):
# test single branch fetch with refspec including target remote
res = fetch_and_test(remote, refspec="master:refs/remotes/%s/master" % remote)
self.assertEqual(len(res), 1)
- self.assertTrue(get_info(res, remote, 'master'))
+ self.assertTrue(get_info(res, remote, "master"))
# ... with respec and no target
- res = fetch_and_test(remote, refspec='master')
+ res = fetch_and_test(remote, refspec="master")
self.assertEqual(len(res), 1)
# ... multiple refspecs ... works, but git command returns with error if one ref is wrong without
@@ -286,8 +304,12 @@ class TestRemote(TestBase):
# must clone with a local path for the repo implementation not to freak out
# as it wants local paths only ( which I can understand )
other_repo = remote_repo.clone(other_repo_dir, shared=False)
- remote_repo_url = osp.basename(remote_repo.git_dir) # git-daemon runs with appropriate `--base-path`.
- remote_repo_url = Git.polish_url("git://localhost:%s/%s" % (GIT_DAEMON_PORT, remote_repo_url))
+ remote_repo_url = osp.basename(
+ remote_repo.git_dir
+ ) # git-daemon runs with appropriate `--base-path`.
+ remote_repo_url = Git.polish_url(
+ "git://localhost:%s/%s" % (GIT_DAEMON_PORT, remote_repo_url)
+ )
# put origin to git-url
other_origin = other_repo.remotes.origin
@@ -321,7 +343,7 @@ class TestRemote(TestBase):
except AttributeError:
# if the author is on a non-master branch, the clones might not have
# a local master yet. We simply create it
- lhead.reference = rw_repo.create_head('master')
+ lhead.reference = rw_repo.create_head("master")
# END master handling
lhead.reset(remote.refs.master, working_tree=True)
@@ -345,7 +367,7 @@ class TestRemote(TestBase):
self._do_test_push_result(res, remote)
# force rejected pull
- res = remote.push('+%s' % lhead.reference)
+ res = remote.push("+%s" % lhead.reference)
self.assertEqual(res[0].flags & PushInfo.ERROR, 0)
self.assertTrue(res[0].flags & PushInfo.FORCED_UPDATE)
self._do_test_push_result(res, remote)
@@ -357,7 +379,9 @@ class TestRemote(TestBase):
progress = TestRemoteProgress()
to_be_updated = "my_tag.1.0RV"
new_tag = TagReference.create(rw_repo, to_be_updated) # @UnusedVariable
- other_tag = TagReference.create(rw_repo, "my_obj_tag.2.1aRV", logmsg="my message")
+ other_tag = TagReference.create(
+ rw_repo, "my_obj_tag.2.1aRV", logmsg="my message"
+ )
res = remote.push(progress=progress, tags=True)
self.assertTrue(res[-1].flags & PushInfo.NEW_TAG)
progress.make_assertion()
@@ -365,7 +389,9 @@ class TestRemote(TestBase):
# update push new tags
# Rejection is default
- new_tag = TagReference.create(rw_repo, to_be_updated, reference='HEAD~1', force=True)
+ new_tag = TagReference.create(
+ rw_repo, to_be_updated, reference="HEAD~1", force=True
+ )
res = remote.push(tags=True)
self._do_test_push_result(res, remote)
self.assertTrue(res[-1].flags & PushInfo.REJECTED)
@@ -411,7 +437,7 @@ class TestRemote(TestBase):
res = remote.push(all=True)
self._do_test_push_result(res, remote)
- remote.pull('master', kill_after_timeout=10.0)
+ remote.pull("master", kill_after_timeout=10.0)
# cleanup - delete created tags and branches as we are in an innerloop on
# the same repository
@@ -419,7 +445,7 @@ class TestRemote(TestBase):
remote.push(":%s" % other_tag.path, kill_after_timeout=10.0)
@skipIf(HIDE_WINDOWS_FREEZE_ERRORS, "FIXME: Freezes!")
- @with_rw_and_rw_remote_repo('0.1.6')
+ @with_rw_and_rw_remote_repo("0.1.6")
def test_base(self, rw_repo, remote_repo):
num_remotes = 0
remote_set = set()
@@ -477,8 +503,9 @@ class TestRemote(TestBase):
# Only for remotes - local cases are the same or less complicated
# as additional progress information will never be emitted
if remote.name == "daemon_origin":
- self._do_test_fetch(remote, rw_repo, remote_repo,
- kill_after_timeout=10.0)
+ self._do_test_fetch(
+ remote, rw_repo, remote_repo, kill_after_timeout=10.0
+ )
ran_fetch_test = True
# END fetch test
@@ -489,7 +516,7 @@ class TestRemote(TestBase):
self.assertTrue(num_remotes)
self.assertEqual(num_remotes, len(remote_set))
- origin = rw_repo.remote('origin')
+ origin = rw_repo.remote("origin")
assert origin == rw_repo.remotes.origin
# Verify we can handle prunes when fetching
@@ -502,15 +529,19 @@ class TestRemote(TestBase):
num_deleted = False
for branch in remote_repo.heads:
- if branch.name != 'master':
+ if branch.name != "master":
branch.delete(remote_repo, branch, force=True)
num_deleted += 1
# end
# end for each branch
self.assertGreater(num_deleted, 0)
- self.assertEqual(len(rw_repo.remotes.origin.fetch(prune=True)), 1, "deleted everything but master")
+ self.assertEqual(
+ len(rw_repo.remotes.origin.fetch(prune=True)),
+ 1,
+ "deleted everything but master",
+ )
- @with_rw_repo('HEAD', bare=True)
+ @with_rw_repo("HEAD", bare=True)
def test_creation_and_removal(self, bare_rw_repo):
new_name = "test_new_one"
arg_list = (new_name, "git@server:hello.git")
@@ -523,7 +554,9 @@ class TestRemote(TestBase):
self.assertRaises(GitCommandError, Remote.create, bare_rw_repo, *arg_list)
Remote.remove(bare_rw_repo, new_name)
- self.assertTrue(remote.exists()) # We still have a cache that doesn't know we were deleted by name
+ self.assertTrue(
+ remote.exists()
+ ) # We still have a cache that doesn't know we were deleted by name
remote._clear_cache()
assert not remote.exists() # Cache should be renewed now. This is an issue ...
@@ -534,86 +567,108 @@ class TestRemote(TestBase):
# END for each remote
# Issue #262 - the next call would fail if bug wasn't fixed
- bare_rw_repo.create_remote('bogus', '/bogus/path', mirror='push')
+ bare_rw_repo.create_remote("bogus", "/bogus/path", mirror="push")
def test_fetch_info(self):
# assure we can handle remote-tracking branches
- fetch_info_line_fmt = "c437ee5deb8d00cf02f03720693e4c802e99f390 not-for-merge %s '0.3' of "
+ fetch_info_line_fmt = (
+ "c437ee5deb8d00cf02f03720693e4c802e99f390 not-for-merge %s '0.3' of "
+ )
fetch_info_line_fmt += "git://github.com/gitpython-developers/GitPython"
remote_info_line_fmt = "* [new branch] nomatter -> %s"
- self.assertRaises(ValueError, FetchInfo._from_line, self.rorepo,
- remote_info_line_fmt % "refs/something/branch",
- "269c498e56feb93e408ed4558c8138d750de8893\t\t/Users/ben/test/foo\n")
-
- fi = FetchInfo._from_line(self.rorepo,
- remote_info_line_fmt % "local/master",
- fetch_info_line_fmt % 'remote-tracking branch')
+ self.assertRaises(
+ ValueError,
+ FetchInfo._from_line,
+ self.rorepo,
+ remote_info_line_fmt % "refs/something/branch",
+ "269c498e56feb93e408ed4558c8138d750de8893\t\t/Users/ben/test/foo\n",
+ )
+
+ fi = FetchInfo._from_line(
+ self.rorepo,
+ remote_info_line_fmt % "local/master",
+ fetch_info_line_fmt % "remote-tracking branch",
+ )
assert not fi.ref.is_valid()
self.assertEqual(fi.ref.name, "local/master")
# handles non-default refspecs: One can specify a different path in refs/remotes
# or a special path just in refs/something for instance
- fi = FetchInfo._from_line(self.rorepo,
- remote_info_line_fmt % "subdir/tagname",
- fetch_info_line_fmt % 'tag')
+ fi = FetchInfo._from_line(
+ self.rorepo,
+ remote_info_line_fmt % "subdir/tagname",
+ fetch_info_line_fmt % "tag",
+ )
self.assertIsInstance(fi.ref, TagReference)
- assert fi.ref.path.startswith('refs/tags'), fi.ref.path
+ assert fi.ref.path.startswith("refs/tags"), fi.ref.path
# it could be in a remote direcftory though
- fi = FetchInfo._from_line(self.rorepo,
- remote_info_line_fmt % "remotename/tags/tagname",
- fetch_info_line_fmt % 'tag')
+ fi = FetchInfo._from_line(
+ self.rorepo,
+ remote_info_line_fmt % "remotename/tags/tagname",
+ fetch_info_line_fmt % "tag",
+ )
self.assertIsInstance(fi.ref, TagReference)
- assert fi.ref.path.startswith('refs/remotes/'), fi.ref.path
+ assert fi.ref.path.startswith("refs/remotes/"), fi.ref.path
# it can also be anywhere !
tag_path = "refs/something/remotename/tags/tagname"
- fi = FetchInfo._from_line(self.rorepo,
- remote_info_line_fmt % tag_path,
- fetch_info_line_fmt % 'tag')
+ fi = FetchInfo._from_line(
+ self.rorepo, remote_info_line_fmt % tag_path, fetch_info_line_fmt % "tag"
+ )
self.assertIsInstance(fi.ref, TagReference)
self.assertEqual(fi.ref.path, tag_path)
# branches default to refs/remotes
- fi = FetchInfo._from_line(self.rorepo,
- remote_info_line_fmt % "remotename/branch",
- fetch_info_line_fmt % 'branch')
+ fi = FetchInfo._from_line(
+ self.rorepo,
+ remote_info_line_fmt % "remotename/branch",
+ fetch_info_line_fmt % "branch",
+ )
self.assertIsInstance(fi.ref, RemoteReference)
- self.assertEqual(fi.ref.remote_name, 'remotename')
+ self.assertEqual(fi.ref.remote_name, "remotename")
# but you can force it anywhere, in which case we only have a references
- fi = FetchInfo._from_line(self.rorepo,
- remote_info_line_fmt % "refs/something/branch",
- fetch_info_line_fmt % 'branch')
+ fi = FetchInfo._from_line(
+ self.rorepo,
+ remote_info_line_fmt % "refs/something/branch",
+ fetch_info_line_fmt % "branch",
+ )
assert type(fi.ref) is Reference, type(fi.ref)
self.assertEqual(fi.ref.path, "refs/something/branch")
def test_uncommon_branch_names(self):
- stderr_lines = fixture('uncommon_branch_prefix_stderr').decode('ascii').splitlines()
- fetch_lines = fixture('uncommon_branch_prefix_FETCH_HEAD').decode('ascii').splitlines()
+ stderr_lines = (
+ fixture("uncommon_branch_prefix_stderr").decode("ascii").splitlines()
+ )
+ fetch_lines = (
+ fixture("uncommon_branch_prefix_FETCH_HEAD").decode("ascii").splitlines()
+ )
# The contents of the files above must be fetched with a custom refspec:
# +refs/pull/*:refs/heads/pull/*
- res = [FetchInfo._from_line('ShouldntMatterRepo', stderr, fetch_line)
- for stderr, fetch_line in zip(stderr_lines, fetch_lines)]
+ res = [
+ FetchInfo._from_line("ShouldntMatterRepo", stderr, fetch_line)
+ for stderr, fetch_line in zip(stderr_lines, fetch_lines)
+ ]
self.assertGreater(len(res), 0)
- self.assertEqual(res[0].remote_ref_path, 'refs/pull/1/head')
- self.assertEqual(res[0].ref.path, 'refs/heads/pull/1/head')
+ self.assertEqual(res[0].remote_ref_path, "refs/pull/1/head")
+ self.assertEqual(res[0].ref.path, "refs/heads/pull/1/head")
self.assertIsInstance(res[0].ref, Head)
- @with_rw_repo('HEAD', bare=False)
+ @with_rw_repo("HEAD", bare=False)
def test_multiple_urls(self, rw_repo):
# test addresses
- test1 = 'https://github.com/gitpython-developers/GitPython'
- test2 = 'https://github.com/gitpython-developers/gitdb'
- test3 = 'https://github.com/gitpython-developers/smmap'
+ test1 = "https://github.com/gitpython-developers/GitPython"
+ test2 = "https://github.com/gitpython-developers/gitdb"
+ test3 = "https://github.com/gitpython-developers/smmap"
remote = rw_repo.remotes[0]
# Testing setting a single URL
@@ -639,7 +694,7 @@ class TestRemote(TestBase):
self.assertRaises(GitCommandError, remote.set_url, test2, add=True, delete=True)
# Testing on another remote, with the add/delete URL
- remote = rw_repo.create_remote('another', url=test1)
+ remote = rw_repo.create_remote("another", url=test1)
remote.add_url(test2)
self.assertEqual(list(remote.urls), [test1, test2])
remote.add_url(test3)
@@ -653,19 +708,23 @@ class TestRemote(TestBase):
self.assertRaises(GitCommandError, remote.delete_url, test3)
def test_fetch_error(self):
- rem = self.rorepo.remote('origin')
- with self.assertRaisesRegex(GitCommandError, "[Cc]ouldn't find remote ref __BAD_REF__"):
- rem.fetch('__BAD_REF__')
+ rem = self.rorepo.remote("origin")
+ with self.assertRaisesRegex(
+ GitCommandError, "[Cc]ouldn't find remote ref __BAD_REF__"
+ ):
+ rem.fetch("__BAD_REF__")
- @with_rw_repo('0.1.6', bare=False)
+ @with_rw_repo("0.1.6", bare=False)
def test_push_error(self, repo):
- rem = repo.remote('origin')
- with self.assertRaisesRegex(GitCommandError, "src refspec __BAD_REF__ does not match any"):
- rem.push('__BAD_REF__')
+ rem = repo.remote("origin")
+ with self.assertRaisesRegex(
+ GitCommandError, "src refspec __BAD_REF__ does not match any"
+ ):
+ rem.push("__BAD_REF__")
class TestTimeouts(TestBase):
- @with_rw_repo('HEAD', bare=False)
+ @with_rw_repo("HEAD", bare=False)
def test_timeout_funcs(self, repo):
# Force error code to prevent a race condition if the python thread is
# slow
@@ -675,8 +734,7 @@ class TestTimeouts(TestBase):
f = getattr(repo.remotes.origin, function)
assert f is not None # Make sure these functions exist
_ = f() # Make sure the function runs
- with pytest.raises(GitCommandError,
- match="kill_after_timeout=0 s"):
+ with pytest.raises(GitCommandError, match="kill_after_timeout=0 s"):
f(kill_after_timeout=0)
Git.AutoInterrupt._status_code_if_terminate = default
diff --git a/test/test_repo.py b/test/test_repo.py
index c5b2680d..7cffbbd8 100644
--- a/test/test_repo.py
+++ b/test/test_repo.py
@@ -30,17 +30,13 @@ from git import (
GitCmdObjectDB,
Remote,
BadName,
- GitCommandError
+ GitCommandError,
)
from git.exc import (
BadObject,
)
from git.repo.fun import touch
-from test.lib import (
- TestBase,
- with_rw_repo,
- fixture
-)
+from test.lib import TestBase, with_rw_repo, fixture
from git.util import HIDE_WINDOWS_KNOWN_ERRORS, cygpath
from test.lib import with_rw_directory
from git.util import join_path_native, rmtree, rmfile, bin_to_hex
@@ -58,7 +54,7 @@ def flatten(lol):
return list(iter_flatten(lol))
-_tc_lock_fpaths = osp.join(osp.dirname(__file__), '../../.git/*.lock')
+_tc_lock_fpaths = osp.join(osp.dirname(__file__), "../../.git/*.lock")
def _rm_lock_files():
@@ -67,15 +63,17 @@ def _rm_lock_files():
class TestRepo(TestBase):
-
def setUp(self):
_rm_lock_files()
def tearDown(self):
for lfp in glob.glob(_tc_lock_fpaths):
if osp.isfile(lfp):
- raise AssertionError('Previous TC left hanging git-lock file: {}'.format(lfp))
+ raise AssertionError(
+ "Previous TC left hanging git-lock file: {}".format(lfp)
+ )
import gc
+
gc.collect()
def test_new_should_raise_on_invalid_repo_location(self):
@@ -84,15 +82,15 @@ class TestRepo(TestBase):
def test_new_should_raise_on_non_existent_path(self):
self.assertRaises(NoSuchPathError, Repo, "repos/foobar")
- @with_rw_repo('0.3.2.1')
+ @with_rw_repo("0.3.2.1")
def test_repo_creation_from_different_paths(self, rw_repo):
r_from_gitdir = Repo(rw_repo.git_dir)
self.assertEqual(r_from_gitdir.git_dir, rw_repo.git_dir)
- assert r_from_gitdir.git_dir.endswith('.git')
- assert not rw_repo.git.working_dir.endswith('.git')
+ assert r_from_gitdir.git_dir.endswith(".git")
+ assert not rw_repo.git.working_dir.endswith(".git")
self.assertEqual(r_from_gitdir.git.working_dir, rw_repo.git.working_dir)
- @with_rw_repo('0.3.2.1')
+ @with_rw_repo("0.3.2.1")
def test_repo_creation_pathlib(self, rw_repo):
r_from_gitdir = Repo(pathlib.Path(rw_repo.git_dir))
self.assertEqual(r_from_gitdir.git_dir, rw_repo.git_dir)
@@ -113,33 +111,35 @@ class TestRepo(TestBase):
# END for each head
self.assertIsInstance(self.rorepo.heads.master, Head)
- self.assertIsInstance(self.rorepo.heads['master'], Head)
+ self.assertIsInstance(self.rorepo.heads["master"], Head)
def test_tree_from_revision(self):
- tree = self.rorepo.tree('0.1.6')
+ tree = self.rorepo.tree("0.1.6")
self.assertEqual(len(tree.hexsha), 40)
self.assertEqual(tree.type, "tree")
self.assertEqual(self.rorepo.tree(tree), tree)
# try from invalid revision that does not exist
- self.assertRaises(BadName, self.rorepo.tree, 'hello world')
+ self.assertRaises(BadName, self.rorepo.tree, "hello world")
def test_pickleable(self):
pickle.loads(pickle.dumps(self.rorepo))
def test_commit_from_revision(self):
- commit = self.rorepo.commit('0.1.4')
- self.assertEqual(commit.type, 'commit')
+ commit = self.rorepo.commit("0.1.4")
+ self.assertEqual(commit.type, "commit")
self.assertEqual(self.rorepo.commit(commit), commit)
def test_commits(self):
mc = 10
- commits = list(self.rorepo.iter_commits('0.1.6', max_count=mc))
+ commits = list(self.rorepo.iter_commits("0.1.6", max_count=mc))
self.assertEqual(len(commits), mc)
c = commits[0]
- self.assertEqual('9a4b1d4d11eee3c5362a4152216376e634bd14cf', c.hexsha)
- self.assertEqual(["c76852d0bff115720af3f27acdb084c59361e5f6"], [p.hexsha for p in c.parents])
+ self.assertEqual("9a4b1d4d11eee3c5362a4152216376e634bd14cf", c.hexsha)
+ self.assertEqual(
+ ["c76852d0bff115720af3f27acdb084c59361e5f6"], [p.hexsha for p in c.parents]
+ )
self.assertEqual("ce41fc29549042f1aa09cc03174896cf23f112e3", c.tree.hexsha)
self.assertEqual("Michael Trier", c.author.name)
self.assertEqual("mtrier@gmail.com", c.author.email)
@@ -157,7 +157,7 @@ class TestRepo(TestBase):
def test_trees(self):
mc = 30
num_trees = 0
- for tree in self.rorepo.iter_trees('0.1.5', max_count=mc):
+ for tree in self.rorepo.iter_trees("0.1.5", max_count=mc):
num_trees += 1
self.assertIsInstance(tree, Tree)
# END for each tree
@@ -176,7 +176,7 @@ class TestRepo(TestBase):
assert not repo.head.is_valid()
# we can change the head to some other ref
- head_ref = Head.from_path(repo, Head.to_full_path('some_head'))
+ head_ref = Head.from_path(repo, Head.to_full_path("some_head"))
assert not head_ref.is_valid()
repo.head.ref = head_ref
@@ -195,7 +195,9 @@ class TestRepo(TestBase):
original_repo = Repo.init(osp.join(rw_dir, "repo"))
environment = {"entry1": "value", "another_entry": "10"}
- cloned = Repo.clone_from(original_repo.git_dir, osp.join(rw_dir, "clone"), env=environment)
+ cloned = Repo.clone_from(
+ original_repo.git_dir, osp.join(rw_dir, "clone"), env=environment
+ )
self.assertEqual(environment, cloned.git.environment())
@@ -215,20 +217,32 @@ class TestRepo(TestBase):
def test_clone_from_pathlib_withConfig(self, rw_dir):
original_repo = Repo.init(osp.join(rw_dir, "repo"))
- cloned = Repo.clone_from(original_repo.git_dir, pathlib.Path(rw_dir) / "clone_pathlib_withConfig",
- multi_options=["--recurse-submodules=repo",
- "--config core.filemode=false",
- "--config submodule.repo.update=checkout",
- "--config filter.lfs.clean='git-lfs clean -- %f'"])
-
- self.assertEqual(cloned.config_reader().get_value('submodule', 'active'), 'repo')
- self.assertEqual(cloned.config_reader().get_value('core', 'filemode'), False)
- self.assertEqual(cloned.config_reader().get_value('submodule "repo"', 'update'), 'checkout')
- self.assertEqual(cloned.config_reader().get_value('filter "lfs"', 'clean'), 'git-lfs clean -- %f')
+ cloned = Repo.clone_from(
+ original_repo.git_dir,
+ pathlib.Path(rw_dir) / "clone_pathlib_withConfig",
+ multi_options=[
+ "--recurse-submodules=repo",
+ "--config core.filemode=false",
+ "--config submodule.repo.update=checkout",
+ "--config filter.lfs.clean='git-lfs clean -- %f'",
+ ],
+ )
+
+ self.assertEqual(
+ cloned.config_reader().get_value("submodule", "active"), "repo"
+ )
+ self.assertEqual(cloned.config_reader().get_value("core", "filemode"), False)
+ self.assertEqual(
+ cloned.config_reader().get_value('submodule "repo"', "update"), "checkout"
+ )
+ self.assertEqual(
+ cloned.config_reader().get_value('filter "lfs"', "clean"),
+ "git-lfs clean -- %f",
+ )
def test_clone_from_with_path_contains_unicode(self):
with tempfile.TemporaryDirectory() as tmpdir:
- unicode_dir_name = '\u0394'
+ unicode_dir_name = "\u0394"
path_with_unicode = os.path.join(tmpdir, unicode_dir_name)
os.makedirs(path_with_unicode)
@@ -238,7 +252,7 @@ class TestRepo(TestBase):
to_path=path_with_unicode,
)
except UnicodeEncodeError:
- self.fail('Raised UnicodeEncodeError')
+ self.fail("Raised UnicodeEncodeError")
@with_rw_directory
def test_leaking_password_in_clone_logs(self, rw_dir):
@@ -246,16 +260,21 @@ class TestRepo(TestBase):
try:
Repo.clone_from(
url="https://fakeuser:{}@fakerepo.example.com/testrepo".format(
- password),
- to_path=rw_dir)
+ password
+ ),
+ to_path=rw_dir,
+ )
except GitCommandError as err:
- assert password not in str(err), "The error message '%s' should not contain the password" % err
+ assert password not in str(err), (
+ "The error message '%s' should not contain the password" % err
+ )
# Working example from a blank private project
Repo.clone_from(
url="https://gitlab+deploy-token-392045:mLWhVus7bjLsy8xj8q2V@gitlab.com/mercierm/test_git_python",
- to_path=rw_dir)
+ to_path=rw_dir,
+ )
- @with_rw_repo('HEAD')
+ @with_rw_repo("HEAD")
def test_max_chunk_size(self, repo):
class TestOutputStream(TestBase):
def __init__(self, max_chunk_size):
@@ -265,10 +284,20 @@ class TestRepo(TestBase):
self.assertTrue(len(b) <= self.max_chunk_size)
for chunk_size in [16, 128, 1024]:
- repo.git.status(output_stream=TestOutputStream(chunk_size), max_chunk_size=chunk_size)
-
- repo.git.log(n=100, output_stream=TestOutputStream(io.DEFAULT_BUFFER_SIZE), max_chunk_size=None)
- repo.git.log(n=100, output_stream=TestOutputStream(io.DEFAULT_BUFFER_SIZE), max_chunk_size=-10)
+ repo.git.status(
+ output_stream=TestOutputStream(chunk_size), max_chunk_size=chunk_size
+ )
+
+ repo.git.log(
+ n=100,
+ output_stream=TestOutputStream(io.DEFAULT_BUFFER_SIZE),
+ max_chunk_size=None,
+ )
+ repo.git.log(
+ n=100,
+ output_stream=TestOutputStream(io.DEFAULT_BUFFER_SIZE),
+ max_chunk_size=-10,
+ )
repo.git.log(n=100, output_stream=TestOutputStream(io.DEFAULT_BUFFER_SIZE))
def test_init(self):
@@ -352,7 +381,7 @@ class TestRepo(TestBase):
self.rorepo.alternates = cur_alternates
def test_repr(self):
- assert repr(self.rorepo).startswith('<git.repo.base.Repo ')
+ assert repr(self.rorepo).startswith("<git.repo.base.Repo ")
def test_is_dirty_with_bare_repository(self):
orig_value = self.rorepo._bare
@@ -365,7 +394,9 @@ class TestRepo(TestBase):
for index in (0, 1):
for working_tree in (0, 1):
for untracked_files in (0, 1):
- assert self.rorepo.is_dirty(index, working_tree, untracked_files) in (True, False)
+ assert self.rorepo.is_dirty(
+ index, working_tree, untracked_files
+ ) in (True, False)
# END untracked files
# END working tree
# END index
@@ -379,7 +410,9 @@ class TestRepo(TestBase):
for index in (0, 1):
for working_tree in (0, 1):
for untracked_files in (0, 1):
- assert self.rorepo.is_dirty(index, working_tree, untracked_files, path=':!foo') in (True, False)
+ assert self.rorepo.is_dirty(
+ index, working_tree, untracked_files, path=":!foo"
+ ) in (True, False)
# END untracked files
# END working tree
# END index
@@ -388,7 +421,7 @@ class TestRepo(TestBase):
assert self.rorepo.is_dirty() is False
self.rorepo._bare = orig_val
- @with_rw_repo('HEAD')
+ @with_rw_repo("HEAD")
def test_is_dirty_with_path(self, rwrepo):
assert rwrepo.is_dirty(path="git") is False
@@ -407,17 +440,19 @@ class TestRepo(TestBase):
assert rwrepo.is_dirty(untracked_files=True, path="doc") is True
def test_head(self):
- self.assertEqual(self.rorepo.head.reference.object, self.rorepo.active_branch.object)
+ self.assertEqual(
+ self.rorepo.head.reference.object, self.rorepo.active_branch.object
+ )
def test_index(self):
index = self.rorepo.index
self.assertIsInstance(index, IndexFile)
def test_tag(self):
- assert self.rorepo.tag('refs/tags/0.1.5').commit
+ assert self.rorepo.tag("refs/tags/0.1.5").commit
def test_tag_to_full_tag_path(self):
- tags = ['0.1.5', 'tags/0.1.5', 'refs/tags/0.1.5']
+ tags = ["0.1.5", "tags/0.1.5", "refs/tags/0.1.5"]
value_errors = []
for tag in tags:
try:
@@ -427,16 +462,16 @@ class TestRepo(TestBase):
self.assertEqual(value_errors, [])
def test_archive(self):
- tmpfile = tempfile.mktemp(suffix='archive-test')
- with open(tmpfile, 'wb') as stream:
- self.rorepo.archive(stream, '0.1.6', path='doc')
+ tmpfile = tempfile.mktemp(suffix="archive-test")
+ with open(tmpfile, "wb") as stream:
+ self.rorepo.archive(stream, "0.1.6", path="doc")
assert stream.tell()
os.remove(tmpfile)
- @mock.patch.object(Git, '_call_process')
+ @mock.patch.object(Git, "_call_process")
def test_should_display_blame_information(self, git):
- git.return_value = fixture('blame')
- b = self.rorepo.blame('master', 'lib/git.py')
+ git.return_value = fixture("blame")
+ b = self.rorepo.blame("master", "lib/git.py")
self.assertEqual(13, len(b))
self.assertEqual(2, len(b[0]))
# self.assertEqual(25, reduce(lambda acc, x: acc + len(x[-1]), b))
@@ -444,85 +479,127 @@ class TestRepo(TestBase):
c = b[0][0]
self.assertTrue(git.called)
- self.assertEqual('634396b2f541a9f2d58b00be1a07f0c358b999b3', c.hexsha)
- self.assertEqual('Tom Preston-Werner', c.author.name)
- self.assertEqual('tom@mojombo.com', c.author.email)
+ self.assertEqual("634396b2f541a9f2d58b00be1a07f0c358b999b3", c.hexsha)
+ self.assertEqual("Tom Preston-Werner", c.author.name)
+ self.assertEqual("tom@mojombo.com", c.author.email)
self.assertEqual(1191997100, c.authored_date)
- self.assertEqual('Tom Preston-Werner', c.committer.name)
- self.assertEqual('tom@mojombo.com', c.committer.email)
+ self.assertEqual("Tom Preston-Werner", c.committer.name)
+ self.assertEqual("tom@mojombo.com", c.committer.email)
self.assertEqual(1191997100, c.committed_date)
- self.assertRaisesRegex(ValueError, "634396b2f541a9f2d58b00be1a07f0c358b999b3 missing", lambda: c.message)
+ self.assertRaisesRegex(
+ ValueError,
+ "634396b2f541a9f2d58b00be1a07f0c358b999b3 missing",
+ lambda: c.message,
+ )
# test the 'lines per commit' entries
tlist = b[0][1]
self.assertTrue(tlist)
self.assertTrue(isinstance(tlist[0], str))
- self.assertTrue(len(tlist) < sum(len(t) for t in tlist)) # test for single-char bug
+ self.assertTrue(
+ len(tlist) < sum(len(t) for t in tlist)
+ ) # test for single-char bug
# BINARY BLAME
- git.return_value = fixture('blame_binary')
- blames = self.rorepo.blame('master', 'rps')
+ git.return_value = fixture("blame_binary")
+ blames = self.rorepo.blame("master", "rps")
self.assertEqual(len(blames), 2)
def test_blame_real(self):
c = 0
- nml = 0 # amount of multi-lines per blame
+ nml = 0 # amount of multi-lines per blame
for item in self.rorepo.head.commit.tree.traverse(
- predicate=lambda i, d: i.type == 'blob' and i.path.endswith('.py')):
+ predicate=lambda i, d: i.type == "blob" and i.path.endswith(".py")
+ ):
c += 1
for b in self.rorepo.blame(self.rorepo.head, item.path):
nml += int(len(b[1]) > 1)
# END for each item to traverse
assert c, "Should have executed at least one blame command"
- assert nml, "There should at least be one blame commit that contains multiple lines"
+ assert (
+ nml
+ ), "There should at least be one blame commit that contains multiple lines"
- @mock.patch.object(Git, '_call_process')
+ @mock.patch.object(Git, "_call_process")
def test_blame_incremental(self, git):
# loop over two fixtures, create a test fixture for 2.11.1+ syntax
- for git_fixture in ('blame_incremental', 'blame_incremental_2.11.1_plus'):
+ for git_fixture in ("blame_incremental", "blame_incremental_2.11.1_plus"):
git.return_value = fixture(git_fixture)
- blame_output = self.rorepo.blame_incremental('9debf6b0aafb6f7781ea9d1383c86939a1aacde3', 'AUTHORS')
+ blame_output = self.rorepo.blame_incremental(
+ "9debf6b0aafb6f7781ea9d1383c86939a1aacde3", "AUTHORS"
+ )
blame_output = list(blame_output)
self.assertEqual(len(blame_output), 5)
# Check all outputted line numbers
ranges = flatten([entry.linenos for entry in blame_output])
- self.assertEqual(ranges, flatten([range(2, 3), range(14, 15), range(1, 2), range(3, 14), range(15, 17)]))
+ self.assertEqual(
+ ranges,
+ flatten(
+ [
+ range(2, 3),
+ range(14, 15),
+ range(1, 2),
+ range(3, 14),
+ range(15, 17),
+ ]
+ ),
+ )
commits = [entry.commit.hexsha[:7] for entry in blame_output]
- self.assertEqual(commits, ['82b8902', '82b8902', 'c76852d', 'c76852d', 'c76852d'])
+ self.assertEqual(
+ commits, ["82b8902", "82b8902", "c76852d", "c76852d", "c76852d"]
+ )
# Original filenames
- self.assertSequenceEqual([entry.orig_path for entry in blame_output], ['AUTHORS'] * len(blame_output))
+ self.assertSequenceEqual(
+ [entry.orig_path for entry in blame_output],
+ ["AUTHORS"] * len(blame_output),
+ )
# Original line numbers
orig_ranges = flatten([entry.orig_linenos for entry in blame_output])
- self.assertEqual(orig_ranges, flatten([range(2, 3), range(14, 15), range(1, 2), range(2, 13), range(13, 15)])) # noqa E501
-
- @mock.patch.object(Git, '_call_process')
+ self.assertEqual(
+ orig_ranges,
+ flatten(
+ [
+ range(2, 3),
+ range(14, 15),
+ range(1, 2),
+ range(2, 13),
+ range(13, 15),
+ ]
+ ),
+ ) # noqa E501
+
+ @mock.patch.object(Git, "_call_process")
def test_blame_complex_revision(self, git):
- git.return_value = fixture('blame_complex_revision')
+ git.return_value = fixture("blame_complex_revision")
res = self.rorepo.blame("HEAD~10..HEAD", "README.md")
self.assertEqual(len(res), 1)
self.assertEqual(len(res[0][1]), 83, "Unexpected amount of parsed blame lines")
- @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and Git.is_cygwin(),
- """FIXME: File "C:\\projects\\gitpython\\git\\cmd.py", line 671, in execute
+ @skipIf(
+ HIDE_WINDOWS_KNOWN_ERRORS and Git.is_cygwin(),
+ """FIXME: File "C:\\projects\\gitpython\\git\\cmd.py", line 671, in execute
raise GitCommandError(command, status, stderr_value, stdout_value)
GitCommandError: Cmd('git') failed due to: exit code(128)
cmdline: git add 1__��ava verb��ten 1_test _myfile 1_test_other_file
1_��ava-----verb��ten
stderr: 'fatal: pathspec '"1__çava verböten"' did not match any files'
- """)
- @with_rw_repo('HEAD', bare=False)
+ """,
+ )
+ @with_rw_repo("HEAD", bare=False)
def test_untracked_files(self, rwrepo):
for run, repo_add in enumerate((rwrepo.index.add, rwrepo.git.add)):
base = rwrepo.working_tree_dir
- files = (join_path_native(base, "%i_test _myfile" % run),
- join_path_native(base, "%i_test_other_file" % run),
- join_path_native(base, "%i__çava verböten" % run),
- join_path_native(base, "%i_çava-----verböten" % run))
+ files = (
+ join_path_native(base, "%i_test _myfile" % run),
+ join_path_native(base, "%i_test_other_file" % run),
+ join_path_native(base, "%i__çava verböten" % run),
+ join_path_native(base, "%i_çava-----verböten" % run),
+ )
num_recently_untracked = 0
for fpath in files:
@@ -538,13 +615,15 @@ class TestRepo(TestBase):
self.assertEqual(len(files), num_test_untracked)
repo_add(untracked_files)
- self.assertEqual(len(rwrepo.untracked_files), (num_recently_untracked - len(files)))
+ self.assertEqual(
+ len(rwrepo.untracked_files), (num_recently_untracked - len(files))
+ )
# end for each run
def test_config_reader(self):
- reader = self.rorepo.config_reader() # all config files
+ reader = self.rorepo.config_reader() # all config files
assert reader.read_only
- reader = self.rorepo.config_reader("repository") # single config file
+ reader = self.rorepo.config_reader("repository") # single config file
assert reader.read_only
def test_config_writer(self):
@@ -586,17 +665,17 @@ class TestRepo(TestBase):
@with_rw_directory
def test_tilde_and_env_vars_in_repo_path(self, rw_dir):
- ph = os.environ.get('HOME')
+ ph = os.environ.get("HOME")
try:
- os.environ['HOME'] = rw_dir
- Repo.init(osp.join('~', 'test.git'), bare=True)
+ os.environ["HOME"] = rw_dir
+ Repo.init(osp.join("~", "test.git"), bare=True)
- os.environ['FOO'] = rw_dir
- Repo.init(osp.join('$FOO', 'test.git'), bare=True)
+ os.environ["FOO"] = rw_dir
+ Repo.init(osp.join("$FOO", "test.git"), bare=True)
finally:
if ph:
- os.environ['HOME'] = ph
- del os.environ['FOO']
+ os.environ["HOME"] = ph
+ del os.environ["FOO"]
# end assure HOME gets reset to what it was
def test_git_cmd(self):
@@ -623,7 +702,7 @@ class TestRepo(TestBase):
s = mkfull()
lines = s.readlines()
self.assertEqual(len(lines), 3)
- self.assertTrue(lines[-1].endswith(b'\n'), lines[-1])
+ self.assertTrue(lines[-1].endswith(b"\n"), lines[-1])
self.assertEqual(s._stream.tell(), len(d)) # must have scrubbed to the end
# realines line limit
@@ -643,7 +722,7 @@ class TestRepo(TestBase):
self.assertEqual(s.readline(), l1)
self.assertEqual(s.readline(), l2)
self.assertEqual(s.readline(), l3)
- self.assertEqual(s.readline(), b'')
+ self.assertEqual(s.readline(), b"")
self.assertEqual(s._stream.tell(), len(d))
# readline limit
@@ -654,13 +733,13 @@ class TestRepo(TestBase):
# readline on tiny section
s = mktiny()
self.assertEqual(s.readline(), l1p)
- self.assertEqual(s.readline(), b'')
+ self.assertEqual(s.readline(), b"")
self.assertEqual(s._stream.tell(), ts + 1)
# read no limit
s = mkfull()
self.assertEqual(s.read(), d[:-1])
- self.assertEqual(s.read(), b'')
+ self.assertEqual(s.read(), b"")
self.assertEqual(s._stream.tell(), len(d))
# read limit
@@ -679,24 +758,24 @@ class TestRepo(TestBase):
def _assert_rev_parse_types(self, name, rev_obj):
rev_parse = self.rorepo.rev_parse
- if rev_obj.type == 'tag':
+ if rev_obj.type == "tag":
rev_obj = rev_obj.object
# tree and blob type
- obj = rev_parse(name + '^{tree}')
+ obj = rev_parse(name + "^{tree}")
self.assertEqual(obj, rev_obj.tree)
- obj = rev_parse(name + ':CHANGES')
- self.assertEqual(obj.type, 'blob')
- self.assertEqual(obj.path, 'CHANGES')
- self.assertEqual(rev_obj.tree['CHANGES'], obj)
+ obj = rev_parse(name + ":CHANGES")
+ self.assertEqual(obj.type, "blob")
+ self.assertEqual(obj.path, "CHANGES")
+ self.assertEqual(rev_obj.tree["CHANGES"], obj)
def _assert_rev_parse(self, name):
"""tries multiple different rev-parse syntaxes with the given name
:return: parsed object"""
rev_parse = self.rorepo.rev_parse
orig_obj = rev_parse(name)
- if orig_obj.type == 'tag':
+ if orig_obj.type == "tag":
obj = orig_obj.object
else:
obj = orig_obj
@@ -737,17 +816,19 @@ class TestRepo(TestBase):
return orig_obj
- @with_rw_repo('HEAD', bare=False)
+ @with_rw_repo("HEAD", bare=False)
def test_rw_rev_parse(self, rwrepo):
# verify it does not confuse branches with hexsha ids
- ahead = rwrepo.create_head('aaaaaaaa')
- assert(rwrepo.rev_parse(str(ahead)) == ahead.commit)
+ ahead = rwrepo.create_head("aaaaaaaa")
+ assert rwrepo.rev_parse(str(ahead)) == ahead.commit
def test_rev_parse(self):
rev_parse = self.rorepo.rev_parse
# try special case: This one failed at some point, make sure its fixed
- self.assertEqual(rev_parse("33ebe").hexsha, "33ebe7acec14b25c5f84f35a664803fcab2f7781")
+ self.assertEqual(
+ rev_parse("33ebe").hexsha, "33ebe7acec14b25c5f84f35a664803fcab2f7781"
+ )
# start from reference
num_resolved = 0
@@ -755,7 +836,7 @@ class TestRepo(TestBase):
for ref_no, ref in enumerate(Reference.iter_items(self.rorepo)):
path_tokens = ref.path.split("/")
for pt in range(len(path_tokens)):
- path_section = '/'.join(path_tokens[-(pt + 1):])
+ path_section = "/".join(path_tokens[-(pt + 1) :])
try:
obj = self._assert_rev_parse(path_section)
self.assertEqual(obj.type, ref.object.type)
@@ -771,17 +852,17 @@ class TestRepo(TestBase):
assert num_resolved
# it works with tags !
- tag = self._assert_rev_parse('0.1.4')
- self.assertEqual(tag.type, 'tag')
+ tag = self._assert_rev_parse("0.1.4")
+ self.assertEqual(tag.type, "tag")
# try full sha directly ( including type conversion )
self.assertEqual(tag.object, rev_parse(tag.object.hexsha))
self._assert_rev_parse_types(tag.object.hexsha, tag.object)
# multiple tree types result in the same tree: HEAD^{tree}^{tree}:CHANGES
- rev = '0.1.4^{tree}^{tree}'
+ rev = "0.1.4^{tree}^{tree}"
self.assertEqual(rev_parse(rev), tag.object.tree)
- self.assertEqual(rev_parse(rev + ':CHANGES'), tag.object.tree['CHANGES'])
+ self.assertEqual(rev_parse(rev + ":CHANGES"), tag.object.tree["CHANGES"])
# try to get parents from first revision - it should fail as no such revision
# exists
@@ -802,15 +883,18 @@ class TestRepo(TestBase):
# needs a tag which points to a blob
# ref^0 returns commit being pointed to, same with ref~0, and ^{}
- tag = rev_parse('0.1.4')
- for token in (('~0', '^0', '^{}')):
- self.assertEqual(tag.object, rev_parse('0.1.4%s' % token))
+ tag = rev_parse("0.1.4")
+ for token in ("~0", "^0", "^{}"):
+ self.assertEqual(tag.object, rev_parse("0.1.4%s" % token))
# END handle multiple tokens
# try partial parsing
max_items = 40
for i, binsha in enumerate(self.rorepo.odb.sha_iter()):
- self.assertEqual(rev_parse(bin_to_hex(binsha)[:8 - (i % 2)].decode('ascii')).binsha, binsha)
+ self.assertEqual(
+ rev_parse(bin_to_hex(binsha)[: 8 - (i % 2)].decode("ascii")).binsha,
+ binsha,
+ )
if i > max_items:
# this is rather slow currently, as rev_parse returns an object
# which requires accessing packs, it has some additional overhead
@@ -818,10 +902,10 @@ class TestRepo(TestBase):
# END for each binsha in repo
# missing closing brace commit^{tree
- self.assertRaises(ValueError, rev_parse, '0.1.4^{tree')
+ self.assertRaises(ValueError, rev_parse, "0.1.4^{tree")
# missing starting brace
- self.assertRaises(ValueError, rev_parse, '0.1.4^tree}')
+ self.assertRaises(ValueError, rev_parse, "0.1.4^tree}")
# REVLOG
#######
@@ -831,23 +915,23 @@ class TestRepo(TestBase):
self.assertRaises(BadObject, rev_parse, "%s@{0}" % head.commit.hexsha)
# uses HEAD.ref by default
- self.assertEqual(rev_parse('@{0}'), head.commit)
+ self.assertEqual(rev_parse("@{0}"), head.commit)
if not head.is_detached:
- refspec = '%s@{0}' % head.ref.name
+ refspec = "%s@{0}" % head.ref.name
self.assertEqual(rev_parse(refspec), head.ref.commit)
# all additional specs work as well
self.assertEqual(rev_parse(refspec + "^{tree}"), head.commit.tree)
- self.assertEqual(rev_parse(refspec + ":CHANGES").type, 'blob')
+ self.assertEqual(rev_parse(refspec + ":CHANGES").type, "blob")
# END operate on non-detached head
# position doesn't exist
- self.assertRaises(IndexError, rev_parse, '@{10000}')
+ self.assertRaises(IndexError, rev_parse, "@{10000}")
# currently, nothing more is supported
self.assertRaises(NotImplementedError, rev_parse, "@{1 week ago}")
# the last position
- assert rev_parse('@{1}') != head.commit
+ assert rev_parse("@{1}") != head.commit
def test_repo_odbtype(self):
target_type = GitCmdObjectDB
@@ -860,7 +944,7 @@ class TestRepo(TestBase):
self.assertIsInstance(self.rorepo.submodule("gitdb"), Submodule)
self.assertRaises(ValueError, self.rorepo.submodule, "doesn't exist")
- @with_rw_repo('HEAD', bare=False)
+ @with_rw_repo("HEAD", bare=False)
def test_submodule_update(self, rwrepo):
# fails in bare mode
rwrepo._bare = True
@@ -869,27 +953,31 @@ class TestRepo(TestBase):
# test create submodule
sm = rwrepo.submodules[0]
- sm = rwrepo.create_submodule("my_new_sub", "some_path", join_path_native(self.rorepo.working_tree_dir, sm.path))
+ sm = rwrepo.create_submodule(
+ "my_new_sub",
+ "some_path",
+ join_path_native(self.rorepo.working_tree_dir, sm.path),
+ )
self.assertIsInstance(sm, Submodule)
# note: the rest of this functionality is tested in test_submodule
- @with_rw_repo('HEAD')
+ @with_rw_repo("HEAD")
def test_git_file(self, rwrepo):
# Move the .git directory to another location and create the .git file.
- real_path_abs = osp.abspath(join_path_native(rwrepo.working_tree_dir, '.real'))
+ real_path_abs = osp.abspath(join_path_native(rwrepo.working_tree_dir, ".real"))
os.rename(rwrepo.git_dir, real_path_abs)
- git_file_path = join_path_native(rwrepo.working_tree_dir, '.git')
- with open(git_file_path, 'wb') as fp:
- fp.write(fixture('git_file'))
+ git_file_path = join_path_native(rwrepo.working_tree_dir, ".git")
+ with open(git_file_path, "wb") as fp:
+ fp.write(fixture("git_file"))
# Create a repo and make sure it's pointing to the relocated .git directory.
git_file_repo = Repo(rwrepo.working_tree_dir)
self.assertEqual(osp.abspath(git_file_repo.git_dir), real_path_abs)
# Test using an absolute gitdir path in the .git file.
- with open(git_file_path, 'wb') as fp:
- fp.write(('gitdir: %s\n' % real_path_abs).encode('ascii'))
+ with open(git_file_path, "wb") as fp:
+ fp.write(("gitdir: %s\n" % real_path_abs).encode("ascii"))
git_file_repo = Repo(rwrepo.working_tree_dir)
self.assertEqual(osp.abspath(git_file_repo.git_dir), real_path_abs)
@@ -906,13 +994,13 @@ class TestRepo(TestBase):
for _ in range(64):
for repo_type in (GitCmdObjectDB, GitDB):
repo = Repo(self.rorepo.working_tree_dir, odbt=repo_type)
- last_commit(repo, 'master', 'test/test_base.py')
+ last_commit(repo, "master", "test/test_base.py")
# end for each repository type
# end for each iteration
def test_remote_method(self):
- self.assertRaises(ValueError, self.rorepo.remote, 'foo-blue')
- self.assertIsInstance(self.rorepo.remote(name='origin'), Remote)
+ self.assertRaises(ValueError, self.rorepo.remote, "foo-blue")
+ self.assertIsInstance(self.rorepo.remote(name="origin"), Remote)
@with_rw_directory
def test_empty_repo(self, rw_dir):
@@ -920,13 +1008,13 @@ class TestRepo(TestBase):
r = Repo.init(rw_dir, mkdir=False)
# It's ok not to be able to iterate a commit, as there is none
self.assertRaises(ValueError, r.iter_commits)
- self.assertEqual(r.active_branch.name, 'master')
+ self.assertEqual(r.active_branch.name, "master")
assert not r.active_branch.is_valid(), "Branch is yet to be born"
# actually, when trying to create a new branch without a commit, git itself fails
# We should, however, not fail ungracefully
- self.assertRaises(BadName, r.create_head, 'foo')
- self.assertRaises(BadName, r.create_head, 'master')
+ self.assertRaises(BadName, r.create_head, "foo")
+ self.assertRaises(BadName, r.create_head, "master")
# It's expected to not be able to access a tree
self.assertRaises(ValueError, r.tree)
@@ -936,43 +1024,43 @@ class TestRepo(TestBase):
r.index.commit("initial commit\nBAD MESSAGE 1\n")
# Now a branch should be creatable
- nb = r.create_head('foo')
+ nb = r.create_head("foo")
assert nb.is_valid()
- with open(new_file_path, 'w') as f:
- f.write('Line 1\n')
+ with open(new_file_path, "w") as f:
+ f.write("Line 1\n")
r.index.add([new_file_path])
r.index.commit("add line 1\nBAD MESSAGE 2\n")
- with open('%s/.git/logs/refs/heads/master' % (rw_dir,), 'r') as f:
+ with open("%s/.git/logs/refs/heads/master" % (rw_dir,), "r") as f:
contents = f.read()
- assert 'BAD MESSAGE' not in contents, 'log is corrupt'
+ assert "BAD MESSAGE" not in contents, "log is corrupt"
def test_merge_base(self):
repo = self.rorepo
- c1 = 'f6aa8d1'
- c2 = repo.commit('d46e3fe')
- c3 = '763ef75'
+ c1 = "f6aa8d1"
+ c2 = repo.commit("d46e3fe")
+ c3 = "763ef75"
self.assertRaises(ValueError, repo.merge_base)
- self.assertRaises(ValueError, repo.merge_base, 'foo')
+ self.assertRaises(ValueError, repo.merge_base, "foo")
# two commit merge-base
res = repo.merge_base(c1, c2)
self.assertIsInstance(res, list)
self.assertEqual(len(res), 1)
self.assertIsInstance(res[0], Commit)
- self.assertTrue(res[0].hexsha.startswith('3936084'))
+ self.assertTrue(res[0].hexsha.startswith("3936084"))
- for kw in ('a', 'all'):
+ for kw in ("a", "all"):
res = repo.merge_base(c1, c2, c3, **{kw: True})
self.assertIsInstance(res, list)
self.assertEqual(len(res), 1)
# end for each keyword signalling all merge-bases to be returned
# Test for no merge base - can't do as we have
- self.assertRaises(GitCommandError, repo.merge_base, c1, 'ffffff')
+ self.assertRaises(GitCommandError, repo.merge_base, c1, "ffffff")
def test_is_ancestor(self):
git = self.rorepo.git
@@ -980,23 +1068,23 @@ class TestRepo(TestBase):
raise SkipTest("git merge-base --is-ancestor feature unsupported")
repo = self.rorepo
- c1 = 'f6aa8d1'
- c2 = '763ef75'
+ c1 = "f6aa8d1"
+ c2 = "763ef75"
self.assertTrue(repo.is_ancestor(c1, c1))
self.assertTrue(repo.is_ancestor("master", "master"))
self.assertTrue(repo.is_ancestor(c1, c2))
self.assertTrue(repo.is_ancestor(c1, "master"))
self.assertFalse(repo.is_ancestor(c2, c1))
self.assertFalse(repo.is_ancestor("master", c1))
- for i, j in itertools.permutations([c1, 'ffffff', ''], r=2):
+ for i, j in itertools.permutations([c1, "ffffff", ""], r=2):
self.assertRaises(GitCommandError, repo.is_ancestor, i, j)
def test_is_valid_object(self):
repo = self.rorepo
- commit_sha = 'f6aa8d1'
- blob_sha = '1fbe3e4375'
- tree_sha = '960b40fe36'
- tag_sha = '42c2f60c43'
+ commit_sha = "f6aa8d1"
+ blob_sha = "1fbe3e4375"
+ tree_sha = "960b40fe36"
+ tag_sha = "42c2f60c43"
# Check for valid objects
self.assertTrue(repo.is_valid_object(commit_sha))
@@ -1005,19 +1093,21 @@ class TestRepo(TestBase):
self.assertTrue(repo.is_valid_object(tag_sha))
# Check for valid objects of specific type
- self.assertTrue(repo.is_valid_object(commit_sha, 'commit'))
- self.assertTrue(repo.is_valid_object(blob_sha, 'blob'))
- self.assertTrue(repo.is_valid_object(tree_sha, 'tree'))
- self.assertTrue(repo.is_valid_object(tag_sha, 'tag'))
+ self.assertTrue(repo.is_valid_object(commit_sha, "commit"))
+ self.assertTrue(repo.is_valid_object(blob_sha, "blob"))
+ self.assertTrue(repo.is_valid_object(tree_sha, "tree"))
+ self.assertTrue(repo.is_valid_object(tag_sha, "tag"))
# Check for invalid objects
- self.assertFalse(repo.is_valid_object(b'1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a', 'blob'))
+ self.assertFalse(
+ repo.is_valid_object(b"1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a", "blob")
+ )
# Check for invalid objects of specific type
- self.assertFalse(repo.is_valid_object(commit_sha, 'blob'))
- self.assertFalse(repo.is_valid_object(blob_sha, 'commit'))
- self.assertFalse(repo.is_valid_object(tree_sha, 'commit'))
- self.assertFalse(repo.is_valid_object(tag_sha, 'commit'))
+ self.assertFalse(repo.is_valid_object(commit_sha, "blob"))
+ self.assertFalse(repo.is_valid_object(blob_sha, "commit"))
+ self.assertFalse(repo.is_valid_object(tree_sha, "commit"))
+ self.assertFalse(repo.is_valid_object(tag_sha, "commit"))
@with_rw_directory
def test_git_work_tree_dotgit(self, rw_dir):
@@ -1027,12 +1117,12 @@ class TestRepo(TestBase):
if git.version_info[:3] < (2, 5, 1):
raise SkipTest("worktree feature unsupported")
- rw_master = self.rorepo.clone(join_path_native(rw_dir, 'master_repo'))
- branch = rw_master.create_head('aaaaaaaa')
- worktree_path = join_path_native(rw_dir, 'worktree_repo')
+ rw_master = self.rorepo.clone(join_path_native(rw_dir, "master_repo"))
+ branch = rw_master.create_head("aaaaaaaa")
+ worktree_path = join_path_native(rw_dir, "worktree_repo")
if Git.is_cygwin():
worktree_path = cygpath(worktree_path)
- rw_master.git.worktree('add', worktree_path, branch.name)
+ rw_master.git.worktree("add", worktree_path, branch.name)
# this ensures that we can read the repo's gitdir correctly
repo = Repo(worktree_path)
@@ -1048,7 +1138,7 @@ class TestRepo(TestBase):
origin = repo.remotes.origin
self.assertIsInstance(origin, Remote)
- self.assertIsInstance(repo.heads['aaaaaaaa'], Head)
+ self.assertIsInstance(repo.heads["aaaaaaaa"], Head)
@with_rw_directory
def test_git_work_tree_env(self, rw_dir):
@@ -1057,18 +1147,18 @@ class TestRepo(TestBase):
# move .git directory to a subdirectory
# set GIT_DIR and GIT_WORK_TREE appropriately
# check that repo.working_tree_dir == rw_dir
- self.rorepo.clone(join_path_native(rw_dir, 'master_repo'))
+ self.rorepo.clone(join_path_native(rw_dir, "master_repo"))
- repo_dir = join_path_native(rw_dir, 'master_repo')
- old_git_dir = join_path_native(repo_dir, '.git')
- new_subdir = join_path_native(repo_dir, 'gitdir')
- new_git_dir = join_path_native(new_subdir, 'git')
+ repo_dir = join_path_native(rw_dir, "master_repo")
+ old_git_dir = join_path_native(repo_dir, ".git")
+ new_subdir = join_path_native(repo_dir, "gitdir")
+ new_git_dir = join_path_native(new_subdir, "git")
os.mkdir(new_subdir)
os.rename(old_git_dir, new_git_dir)
oldenv = os.environ.copy()
- os.environ['GIT_DIR'] = new_git_dir
- os.environ['GIT_WORK_TREE'] = repo_dir
+ os.environ["GIT_DIR"] = new_git_dir
+ os.environ["GIT_WORK_TREE"] = repo_dir
try:
r = Repo()
@@ -1080,15 +1170,18 @@ class TestRepo(TestBase):
@with_rw_directory
def test_rebasing(self, rw_dir):
r = Repo.init(rw_dir)
- fp = osp.join(rw_dir, 'hello.txt')
- r.git.commit("--allow-empty", message="init",)
- with open(fp, 'w') as fs:
+ fp = osp.join(rw_dir, "hello.txt")
+ r.git.commit(
+ "--allow-empty",
+ message="init",
+ )
+ with open(fp, "w") as fs:
fs.write("hello world")
r.git.add(Git.polish_url(fp))
r.git.commit(message="English")
self.assertEqual(r.currently_rebasing_on(), None)
r.git.checkout("HEAD^1")
- with open(fp, 'w') as fs:
+ with open(fp, "w") as fs:
fs.write("Hola Mundo")
r.git.add(Git.polish_url(fp))
r.git.commit(message="Spanish")
@@ -1102,9 +1195,11 @@ class TestRepo(TestBase):
@with_rw_directory
def test_do_not_strip_newline_in_stdout(self, rw_dir):
r = Repo.init(rw_dir)
- fp = osp.join(rw_dir, 'hello.txt')
- with open(fp, 'w') as fs:
+ fp = osp.join(rw_dir, "hello.txt")
+ with open(fp, "w") as fs:
fs.write("hello\n")
r.git.add(Git.polish_url(fp))
r.git.commit(message="init")
- self.assertEqual(r.git.show("HEAD:hello.txt", strip_newline_in_stdout=False), 'hello\n')
+ self.assertEqual(
+ r.git.show("HEAD:hello.txt", strip_newline_in_stdout=False), "hello\n"
+ )
diff --git a/test/test_stats.py b/test/test_stats.py
index 2759698a..1f689655 100644
--- a/test/test_stats.py
+++ b/test/test_stats.py
@@ -4,27 +4,23 @@
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
-from test.lib import (
- TestBase,
- fixture
-)
+from test.lib import TestBase, fixture
from git import Stats
from git.compat import defenc
class TestStats(TestBase):
-
def test_list_from_string(self):
- output = fixture('diff_numstat').decode(defenc)
+ output = fixture("diff_numstat").decode(defenc)
stats = Stats._list_from_string(self.rorepo, output)
- self.assertEqual(2, stats.total['files'])
- self.assertEqual(52, stats.total['lines'])
- self.assertEqual(29, stats.total['insertions'])
- self.assertEqual(23, stats.total['deletions'])
+ self.assertEqual(2, stats.total["files"])
+ self.assertEqual(52, stats.total["lines"])
+ self.assertEqual(29, stats.total["insertions"])
+ self.assertEqual(23, stats.total["deletions"])
- self.assertEqual(29, stats.files["a.txt"]['insertions'])
- self.assertEqual(18, stats.files["a.txt"]['deletions'])
+ self.assertEqual(29, stats.files["a.txt"]["insertions"])
+ self.assertEqual(18, stats.files["a.txt"]["deletions"])
- self.assertEqual(0, stats.files["b.txt"]['insertions'])
- self.assertEqual(5, stats.files["b.txt"]['deletions'])
+ self.assertEqual(0, stats.files["b.txt"]["insertions"])
+ self.assertEqual(5, stats.files["b.txt"]["deletions"])
diff --git a/test/test_submodule.py b/test/test_submodule.py
index a79123dc..fc96391d 100644
--- a/test/test_submodule.py
+++ b/test/test_submodule.py
@@ -9,20 +9,11 @@ import git
from git.cmd import Git
from git.compat import is_win
from git.config import GitConfigParser, cp
-from git.exc import (
- InvalidGitRepositoryError,
- RepositoryDirtyError
-)
+from git.exc import InvalidGitRepositoryError, RepositoryDirtyError
from git.objects.submodule.base import Submodule
from git.objects.submodule.root import RootModule, RootUpdateProgress
-from git.repo.fun import (
- find_submodule_git_dir,
- touch
-)
-from test.lib import (
- TestBase,
- with_rw_repo
-)
+from git.repo.fun import find_submodule_git_dir, touch
+from test.lib import TestBase, with_rw_repo
from test.lib import with_rw_directory
from git.util import HIDE_WINDOWS_KNOWN_ERRORS
from git.util import to_native_path_linux, join_path_native
@@ -32,7 +23,7 @@ import os.path as osp
class TestRootProgress(RootUpdateProgress):
"""Just prints messages, for now without checking the correctness of the states"""
- def update(self, op, cur_count, max_count, message=''):
+ def update(self, op, cur_count, max_count, message=""):
print(op, cur_count, max_count, message)
@@ -40,9 +31,9 @@ prog = TestRootProgress()
class TestSubmodule(TestBase):
-
def tearDown(self):
import gc
+
gc.collect()
k_subm_current = "c15a6e1923a14bc760851913858a3942a4193cdb"
@@ -54,7 +45,7 @@ class TestSubmodule(TestBase):
# manual instantiation
smm = Submodule(rwrepo, "\0" * 20)
# name needs to be set in advance
- self.assertRaises(AttributeError, getattr, smm, 'name')
+ self.assertRaises(AttributeError, getattr, smm, "name")
# iterate - 1 submodule
sms = Submodule.list_items(rwrepo, self.k_subm_current)
@@ -64,11 +55,13 @@ class TestSubmodule(TestBase):
# at a different time, there is None
assert len(Submodule.list_items(rwrepo, self.k_no_subm_tag)) == 0
- assert sm.path == 'git/ext/gitdb'
- assert sm.path != sm.name # in our case, we have ids there, which don't equal the path
- assert sm.url.endswith('github.com/gitpython-developers/gitdb.git')
- assert sm.branch_path == 'refs/heads/master' # the default ...
- assert sm.branch_name == 'master'
+ assert sm.path == "git/ext/gitdb"
+ assert (
+ sm.path != sm.name
+ ) # in our case, we have ids there, which don't equal the path
+ assert sm.url.endswith("github.com/gitpython-developers/gitdb.git")
+ assert sm.branch_path == "refs/heads/master" # the default ...
+ assert sm.branch_name == "master"
assert sm.parent_commit == rwrepo.head.commit
# size is always 0
assert sm.size == 0
@@ -76,7 +69,7 @@ class TestSubmodule(TestBase):
self.assertRaises(InvalidGitRepositoryError, sm.module)
# which is why we can't get the branch either - it points into the module() repository
- self.assertRaises(InvalidGitRepositoryError, getattr, sm, 'branch')
+ self.assertRaises(InvalidGitRepositoryError, getattr, sm, "branch")
# branch_path works, as its just a string
assert isinstance(sm.branch_path, str)
@@ -84,16 +77,16 @@ class TestSubmodule(TestBase):
# some commits earlier we still have a submodule, but its at a different commit
smold = next(Submodule.iter_items(rwrepo, self.k_subm_changed))
assert smold.binsha != sm.binsha
- assert smold != sm # the name changed
+ assert smold != sm # the name changed
# force it to reread its information
- del(smold._url)
+ del smold._url
smold.url == sm.url # @NoEffect
# test config_reader/writer methods
sm.config_reader()
- new_smclone_path = None # keep custom paths for later
- new_csmclone_path = None #
+ new_smclone_path = None # keep custom paths for later
+ new_csmclone_path = None #
if rwrepo.bare:
with self.assertRaises(InvalidGitRepositoryError):
with sm.config_writer() as cw:
@@ -101,10 +94,12 @@ class TestSubmodule(TestBase):
else:
with sm.config_writer() as writer:
# for faster checkout, set the url to the local path
- new_smclone_path = Git.polish_url(osp.join(self.rorepo.working_tree_dir, sm.path))
- writer.set_value('url', new_smclone_path)
+ new_smclone_path = Git.polish_url(
+ osp.join(self.rorepo.working_tree_dir, sm.path)
+ )
+ writer.set_value("url", new_smclone_path)
writer.release()
- assert sm.config_reader().get_value('url') == new_smclone_path
+ assert sm.config_reader().get_value("url") == new_smclone_path
assert sm.url == new_smclone_path
# END handle bare repo
smold.config_reader()
@@ -134,7 +129,9 @@ class TestSubmodule(TestBase):
if rwrepo.bare:
self.assertRaises(InvalidGitRepositoryError, sm.module)
self.assertRaises(InvalidGitRepositoryError, sm.remove)
- self.assertRaises(InvalidGitRepositoryError, sm.add, rwrepo, 'here', 'there')
+ self.assertRaises(
+ InvalidGitRepositoryError, sm.add, rwrepo, "here", "there"
+ )
else:
# its not checked out in our case
self.assertRaises(InvalidGitRepositoryError, sm.module)
@@ -152,13 +149,15 @@ class TestSubmodule(TestBase):
assert sma.path == sm.path
# no url and no module at path fails
- self.assertRaises(ValueError, Submodule.add, rwrepo, "newsubm", "pathtorepo", url=None)
+ self.assertRaises(
+ ValueError, Submodule.add, rwrepo, "newsubm", "pathtorepo", url=None
+ )
# CONTINUE UPDATE
#################
# lets update it - its a recursive one too
- newdir = osp.join(sm.abspath, 'dir')
+ newdir = osp.join(sm.abspath, "dir")
os.makedirs(newdir)
# update fails if the path already exists non-empty
@@ -170,7 +169,7 @@ class TestSubmodule(TestBase):
assert not sm.module_exists()
assert sm.update() is sm
- sm_repopath = sm.path # cache for later
+ sm_repopath = sm.path # cache for later
assert sm.module_exists()
assert isinstance(sm.module(), git.Repo)
assert sm.module().working_tree_dir == sm.abspath
@@ -179,7 +178,14 @@ class TestSubmodule(TestBase):
#####################
# url must match the one in the existing repository ( if submodule name suggests a new one )
# or we raise
- self.assertRaises(ValueError, Submodule.add, rwrepo, "newsubm", sm.path, "git://someurl/repo.git")
+ self.assertRaises(
+ ValueError,
+ Submodule.add,
+ rwrepo,
+ "newsubm",
+ sm.path,
+ "git://someurl/repo.git",
+ )
# CONTINUE UPDATE
#################
@@ -197,15 +203,17 @@ class TestSubmodule(TestBase):
sm.update(recursive=False)
assert len(list(rwrepo.iter_submodules())) == 2
- assert len(sm.children()) == 1 # its not checked out yet
+ assert len(sm.children()) == 1 # its not checked out yet
csm = sm.children()[0]
assert not csm.module_exists()
csm_repopath = csm.path
# adjust the path of the submodules module to point to the local destination
- new_csmclone_path = Git.polish_url(osp.join(self.rorepo.working_tree_dir, sm.path, csm.path))
+ new_csmclone_path = Git.polish_url(
+ osp.join(self.rorepo.working_tree_dir, sm.path, csm.path)
+ )
with csm.config_writer() as writer:
- writer.set_value('url', new_csmclone_path)
+ writer.set_value("url", new_csmclone_path)
assert csm.url == new_csmclone_path
# dry-run does nothing
@@ -226,26 +234,34 @@ class TestSubmodule(TestBase):
# reset both heads to the previous version, verify that to_latest_revision works
smods = (sm.module(), csm.module())
for repo in smods:
- repo.head.reset('HEAD~2', working_tree=1)
+ repo.head.reset("HEAD~2", working_tree=1)
# END for each repo to reset
# dry run does nothing
- self.assertRaises(RepositoryDirtyError, sm.update, recursive=True, dry_run=True, progress=prog)
+ self.assertRaises(
+ RepositoryDirtyError,
+ sm.update,
+ recursive=True,
+ dry_run=True,
+ progress=prog,
+ )
sm.update(recursive=True, dry_run=True, progress=prog, force=True)
for repo in smods:
assert repo.head.commit != repo.head.ref.tracking_branch().commit
# END for each repo to check
- self.assertRaises(RepositoryDirtyError, sm.update, recursive=True, to_latest_revision=True)
+ self.assertRaises(
+ RepositoryDirtyError, sm.update, recursive=True, to_latest_revision=True
+ )
sm.update(recursive=True, to_latest_revision=True, force=True)
for repo in smods:
assert repo.head.commit == repo.head.ref.tracking_branch().commit
# END for each repo to check
- del(smods)
+ del smods
# if the head is detached, it still works ( but warns )
smref = sm.module().head.ref
- sm.module().head.ref = 'HEAD~1'
+ sm.module().head.ref = "HEAD~1"
# if there is no tracking branch, we get a warning as well
csm_tracking_branch = csm.module().head.ref.tracking_branch()
csm.module().head.ref.set_tracking_branch(None)
@@ -268,8 +284,10 @@ class TestSubmodule(TestBase):
# to GitHub. To save time, we will change it to
csm.set_parent_commit(csm.repo.head.commit)
with csm.config_writer() as cw:
- cw.set_value('url', self._small_repo_url())
- csm.repo.index.commit("adjusted URL to point to local source, instead of the internet")
+ cw.set_value("url", self._small_repo_url())
+ csm.repo.index.commit(
+ "adjusted URL to point to local source, instead of the internet"
+ )
# We have modified the configuration, hence the index is dirty, and the
# deletion will fail
@@ -301,7 +319,7 @@ class TestSubmodule(TestBase):
# but ... we have untracked files in the child submodule
fn = join_path_native(csm.module().working_tree_dir, "newfile")
- with open(fn, 'w') as fd:
+ with open(fn, "w") as fd:
fd.write("hi")
self.assertRaises(InvalidGitRepositoryError, sm.remove)
@@ -323,14 +341,14 @@ class TestSubmodule(TestBase):
sm.remove(configuration=False, force=True)
assert sm.exists()
assert not sm.module_exists()
- assert sm.config_reader().get_value('url')
+ assert sm.config_reader().get_value("url")
# delete the rest
sm_path = sm.path
sm.remove()
assert not sm.exists()
assert not sm.module_exists()
- self.assertRaises(ValueError, getattr, sm, 'path')
+ self.assertRaises(ValueError, getattr, sm, "path")
assert len(rwrepo.submodules) == 0
@@ -339,20 +357,35 @@ class TestSubmodule(TestBase):
# add a simple remote repo - trailing slashes are no problem
smid = "newsub"
osmid = "othersub"
- nsm = Submodule.add(rwrepo, smid, sm_repopath, new_smclone_path + "/", None, no_checkout=True)
+ nsm = Submodule.add(
+ rwrepo,
+ smid,
+ sm_repopath,
+ new_smclone_path + "/",
+ None,
+ no_checkout=True,
+ )
assert nsm.name == smid
assert nsm.module_exists()
assert nsm.exists()
# its not checked out
- assert not osp.isfile(join_path_native(nsm.module().working_tree_dir, Submodule.k_modules_file))
+ assert not osp.isfile(
+ join_path_native(
+ nsm.module().working_tree_dir, Submodule.k_modules_file
+ )
+ )
assert len(rwrepo.submodules) == 1
# add another submodule, but into the root, not as submodule
- osm = Submodule.add(rwrepo, osmid, csm_repopath, new_csmclone_path, Submodule.k_head_default)
+ osm = Submodule.add(
+ rwrepo, osmid, csm_repopath, new_csmclone_path, Submodule.k_head_default
+ )
assert osm != nsm
assert osm.module_exists()
assert osm.exists()
- assert osp.isfile(join_path_native(osm.module().working_tree_dir, 'setup.py'))
+ assert osp.isfile(
+ join_path_native(osm.module().working_tree_dir, "setup.py")
+ )
assert len(rwrepo.submodules) == 2
@@ -368,7 +401,9 @@ class TestSubmodule(TestBase):
# MOVE MODULE
#############
# invalid input
- self.assertRaises(ValueError, nsm.move, 'doesntmatter', module=False, configuration=False)
+ self.assertRaises(
+ ValueError, nsm.move, "doesntmatter", module=False, configuration=False
+ )
# renaming to the same path does nothing
assert nsm.move(sm_path) is nsm
@@ -377,14 +412,14 @@ class TestSubmodule(TestBase):
nmp = join_path_native("new", "module", "dir") + "/" # new module path
pmp = nsm.path
assert nsm.move(nmp) is nsm
- nmp = nmp[:-1] # cut last /
+ nmp = nmp[:-1] # cut last /
nmpl = to_native_path_linux(nmp)
assert nsm.path == nmpl
assert rwrepo.submodules[0].path == nmpl
- mpath = 'newsubmodule'
+ mpath = "newsubmodule"
absmpath = join_path_native(rwrepo.working_tree_dir, mpath)
- open(absmpath, 'w').write('')
+ open(absmpath, "w").write("")
self.assertRaises(ValueError, nsm.move, mpath)
os.remove(absmpath)
@@ -402,11 +437,19 @@ class TestSubmodule(TestBase):
for remote in osmod.remotes:
remote.remove(osmod, remote.name)
assert not osm.exists()
- self.assertRaises(ValueError, Submodule.add, rwrepo, osmid, csm_repopath, url=None)
+ self.assertRaises(
+ ValueError, Submodule.add, rwrepo, osmid, csm_repopath, url=None
+ )
# END handle bare mode
# Error if there is no submodule file here
- self.assertRaises(IOError, Submodule._config_parser, rwrepo, rwrepo.commit(self.k_no_subm_tag), True)
+ self.assertRaises(
+ IOError,
+ Submodule._config_parser,
+ rwrepo,
+ rwrepo.commit(self.k_no_subm_tag),
+ True,
+ )
# @skipIf(HIDE_WINDOWS_KNOWN_ERRORS, ## ACTUALLY skipped by `git.submodule.base#L869`.
# "FIXME: fails with: PermissionError: [WinError 32] The process cannot access the file because"
@@ -420,11 +463,14 @@ class TestSubmodule(TestBase):
def test_base_bare(self, rwrepo):
self._do_base_tests(rwrepo)
- @skipIf(HIDE_WINDOWS_KNOWN_ERRORS, """
+ @skipIf(
+ HIDE_WINDOWS_KNOWN_ERRORS,
+ """
File "C:\\projects\\gitpython\\git\\cmd.py", line 559, in execute
raise GitCommandNotFound(command, err)
git.exc.GitCommandNotFound: Cmd('git') not found due to: OSError('[WinError 6] The handle is invalid')
- cmdline: git clone -n --shared -v C:\\projects\\gitpython\\.git Users\\appveyor\\AppData\\Local\\Temp\\1\\tmplyp6kr_rnon_bare_test_root_module""") # noqa E501
+ cmdline: git clone -n --shared -v C:\\projects\\gitpython\\.git Users\\appveyor\\AppData\\Local\\Temp\\1\\tmplyp6kr_rnon_bare_test_root_module""",
+ ) # noqa E501
@with_rw_repo(k_subm_current, bare=False)
def test_root_module(self, rwrepo):
# Can query everything without problems
@@ -447,10 +493,12 @@ class TestSubmodule(TestBase):
# deep traversal gitdb / async
rsmsp = [sm.path for sm in rm.traverse()]
- assert len(rsmsp) >= 2 # gitdb and async [and smmap], async being a child of gitdb
+ assert (
+ len(rsmsp) >= 2
+ ) # gitdb and async [and smmap], async being a child of gitdb
# cannot set the parent commit as root module's path didn't exist
- self.assertRaises(ValueError, rm.set_parent_commit, 'HEAD')
+ self.assertRaises(ValueError, rm.set_parent_commit, "HEAD")
# TEST UPDATE
#############
@@ -460,16 +508,18 @@ class TestSubmodule(TestBase):
# modify path without modifying the index entry
# ( which is what the move method would do properly )
- #==================================================
+ # ==================================================
sm = rm.children()[0]
pp = "path/prefix"
fp = join_path_native(pp, sm.path)
prep = sm.path
- assert not sm.module_exists() # was never updated after rwrepo's clone
+ assert not sm.module_exists() # was never updated after rwrepo's clone
# assure we clone from a local source
with sm.config_writer() as writer:
- writer.set_value('url', Git.polish_url(osp.join(self.rorepo.working_tree_dir, sm.path)))
+ writer.set_value(
+ "url", Git.polish_url(osp.join(self.rorepo.working_tree_dir, sm.path))
+ )
# dry-run does nothing
sm.update(recursive=False, dry_run=True, progress=prog)
@@ -478,7 +528,9 @@ class TestSubmodule(TestBase):
sm.update(recursive=False)
assert sm.module_exists()
with sm.config_writer() as writer:
- writer.set_value('path', fp) # change path to something with prefix AFTER url change
+ writer.set_value(
+ "path", fp
+ ) # change path to something with prefix AFTER url change
# update doesn't fail, because list_items ignores the wrong path in such situations.
rm.update(recursive=False)
@@ -488,7 +540,7 @@ class TestSubmodule(TestBase):
self.assertRaises(InvalidGitRepositoryError, sm.move, pp)
# reset the path(cache) to where it was, now it works
sm.path = prep
- sm.move(fp, module=False) # leave it at the old location
+ sm.move(fp, module=False) # leave it at the old location
assert not sm.module_exists()
cpathchange = rwrepo.index.commit("changed sm path") # finally we can commit
@@ -499,12 +551,16 @@ class TestSubmodule(TestBase):
assert sm.module_exists()
# add submodule
- #================
+ # ================
nsmn = "newsubmodule"
nsmp = "submrepo"
- subrepo_url = Git.polish_url(osp.join(self.rorepo.working_tree_dir, rsmsp[0], rsmsp[1]))
+ subrepo_url = Git.polish_url(
+ osp.join(self.rorepo.working_tree_dir, rsmsp[0], rsmsp[1])
+ )
nsm = Submodule.add(rwrepo, nsmn, nsmp, url=subrepo_url)
- csmadded = rwrepo.index.commit("Added submodule").hexsha # make sure we don't keep the repo reference
+ csmadded = rwrepo.index.commit(
+ "Added submodule"
+ ).hexsha # make sure we don't keep the repo reference
nsm.set_parent_commit(csmadded)
assert nsm.module_exists()
# in our case, the module should not exist, which happens if we update a parent
@@ -520,11 +576,11 @@ class TestSubmodule(TestBase):
assert nsm.module_exists()
# remove submodule - the previous one
- #====================================
+ # ====================================
sm.set_parent_commit(csmadded)
smp = sm.abspath
assert not sm.remove(module=False).exists()
- assert osp.isdir(smp) # module still exists
+ assert osp.isdir(smp) # module still exists
csmremoved = rwrepo.index.commit("Removed submodule")
# an update will remove the module
@@ -535,37 +591,45 @@ class TestSubmodule(TestBase):
# when removing submodules, we may get new commits as nested submodules are auto-committing changes
# to allow deletions without force, as the index would be dirty otherwise.
# QUESTION: Why does this seem to work in test_git_submodule_compatibility() ?
- self.assertRaises(InvalidGitRepositoryError, rm.update, recursive=False, force_remove=False)
+ self.assertRaises(
+ InvalidGitRepositoryError, rm.update, recursive=False, force_remove=False
+ )
rm.update(recursive=False, force_remove=True)
assert not osp.isdir(smp)
# 'apply work' to the nested submodule and assure this is not removed/altered during updates
# Need to commit first, otherwise submodule.update wouldn't have a reason to change the head
- touch(osp.join(nsm.module().working_tree_dir, 'new-file'))
+ touch(osp.join(nsm.module().working_tree_dir, "new-file"))
# We cannot expect is_dirty to even run as we wouldn't reset a head to the same location
assert nsm.module().head.commit.hexsha == nsm.hexsha
nsm.module().index.add([nsm])
nsm.module().index.commit("added new file")
- rm.update(recursive=False, dry_run=True, progress=prog) # would not change head, and thus doesn't fail
+ rm.update(
+ recursive=False, dry_run=True, progress=prog
+ ) # would not change head, and thus doesn't fail
# Everything we can do from now on will trigger the 'future' check, so no is_dirty() check will even run
# This would only run if our local branch is in the past and we have uncommitted changes
prev_commit = nsm.module().head.commit
rm.update(recursive=False, dry_run=False, progress=prog)
- assert prev_commit == nsm.module().head.commit, "head shouldn't change, as it is in future of remote branch"
+ assert (
+ prev_commit == nsm.module().head.commit
+ ), "head shouldn't change, as it is in future of remote branch"
# this kills the new file
rm.update(recursive=True, progress=prog, force_reset=True)
- assert prev_commit != nsm.module().head.commit, "head changed, as the remote url and its commit changed"
+ assert (
+ prev_commit != nsm.module().head.commit
+ ), "head changed, as the remote url and its commit changed"
# change url ...
- #===============
+ # ===============
# ... to the first repository, this way we have a fast checkout, and a completely different
# repository at the different url
nsm.set_parent_commit(csmremoved)
nsmurl = Git.polish_url(osp.join(self.rorepo.working_tree_dir, rsmsp[0]))
with nsm.config_writer() as writer:
- writer.set_value('url', nsmurl)
+ writer.set_value("url", nsmurl)
csmpathchange = rwrepo.index.commit("changed url")
nsm.set_parent_commit(csmpathchange)
@@ -579,7 +643,9 @@ class TestSubmodule(TestBase):
assert nsm.module().remotes.origin.url == nsmurl
assert prev_commit != nsm.module().head.commit, "Should now point to gitdb"
assert len(rwrepo.submodules) == 1
- assert not rwrepo.submodules[0].children()[0].module_exists(), "nested submodule should not be checked out"
+ assert (
+ not rwrepo.submodules[0].children()[0].module_exists()
+ ), "nested submodule should not be checked out"
# add the submodule's changed commit to the index, which is what the
# user would do
@@ -588,7 +654,7 @@ class TestSubmodule(TestBase):
rwrepo.index.add([nsm])
# change branch
- #=================
+ # =================
# we only have one branch, so we switch to a virtual one, and back
# to the current one to trigger the difference
cur_branch = nsm.branch
@@ -603,7 +669,7 @@ class TestSubmodule(TestBase):
# Lets remove our tracking branch to simulate some changes
nsmmh = nsmm.head
- assert nsmmh.ref.tracking_branch() is None # never set it up until now
+ assert nsmmh.ref.tracking_branch() is None # never set it up until now
assert not nsmmh.is_detached
# dry run does nothing
@@ -625,8 +691,8 @@ class TestSubmodule(TestBase):
# assure we pull locally only
nsmc = nsm.children()[0]
with nsmc.config_writer() as writer:
- writer.set_value('url', subrepo_url)
- rm.update(recursive=True, progress=prog, dry_run=True) # just to run the code
+ writer.set_value("url", subrepo_url)
+ rm.update(recursive=True, progress=prog, dry_run=True) # just to run the code
rm.update(recursive=True, progress=prog)
# gitdb: has either 1 or 2 submodules depending on the version
@@ -636,41 +702,57 @@ class TestSubmodule(TestBase):
def test_first_submodule(self, rwrepo):
assert len(list(rwrepo.iter_submodules())) == 0
- for sm_name, sm_path in (('first', 'submodules/first'),
- ('second', osp.join(rwrepo.working_tree_dir, 'submodules/second'))):
- sm = rwrepo.create_submodule(sm_name, sm_path, rwrepo.git_dir, no_checkout=True)
+ for sm_name, sm_path in (
+ ("first", "submodules/first"),
+ ("second", osp.join(rwrepo.working_tree_dir, "submodules/second")),
+ ):
+ sm = rwrepo.create_submodule(
+ sm_name, sm_path, rwrepo.git_dir, no_checkout=True
+ )
assert sm.exists() and sm.module_exists()
rwrepo.index.commit("Added submodule " + sm_name)
# end for each submodule path to add
- self.assertRaises(ValueError, rwrepo.create_submodule, 'fail', osp.expanduser('~'))
- self.assertRaises(ValueError, rwrepo.create_submodule, 'fail-too',
- rwrepo.working_tree_dir + osp.sep)
+ self.assertRaises(
+ ValueError, rwrepo.create_submodule, "fail", osp.expanduser("~")
+ )
+ self.assertRaises(
+ ValueError,
+ rwrepo.create_submodule,
+ "fail-too",
+ rwrepo.working_tree_dir + osp.sep,
+ )
@with_rw_directory
def test_add_empty_repo(self, rwdir):
- empty_repo_dir = osp.join(rwdir, 'empty-repo')
+ empty_repo_dir = osp.join(rwdir, "empty-repo")
- parent = git.Repo.init(osp.join(rwdir, 'parent'))
+ parent = git.Repo.init(osp.join(rwdir, "parent"))
git.Repo.init(empty_repo_dir)
for checkout_mode in range(2):
- name = 'empty' + str(checkout_mode)
- self.assertRaises(ValueError, parent.create_submodule, name, name,
- url=empty_repo_dir, no_checkout=checkout_mode and True or False)
+ name = "empty" + str(checkout_mode)
+ self.assertRaises(
+ ValueError,
+ parent.create_submodule,
+ name,
+ name,
+ url=empty_repo_dir,
+ no_checkout=checkout_mode and True or False,
+ )
# end for each checkout mode
@with_rw_directory
def test_list_only_valid_submodules(self, rwdir):
- repo_path = osp.join(rwdir, 'parent')
+ repo_path = osp.join(rwdir, "parent")
repo = git.Repo.init(repo_path)
- repo.git.submodule('add', self._small_repo_url(), 'module')
+ repo.git.submodule("add", self._small_repo_url(), "module")
repo.index.commit("add submodule")
assert len(repo.submodules) == 1
# Delete the directory from submodule
- submodule_path = osp.join(repo_path, 'module')
+ submodule_path = osp.join(repo_path, "module")
shutil.rmtree(submodule_path)
repo.git.add([submodule_path])
repo.index.commit("remove submodule")
@@ -678,18 +760,20 @@ class TestSubmodule(TestBase):
repo = git.Repo(repo_path)
assert len(repo.submodules) == 0
- @skipIf(HIDE_WINDOWS_KNOWN_ERRORS,
- """FIXME on cygwin: File "C:\\projects\\gitpython\\git\\cmd.py", line 671, in execute
+ @skipIf(
+ HIDE_WINDOWS_KNOWN_ERRORS,
+ """FIXME on cygwin: File "C:\\projects\\gitpython\\git\\cmd.py", line 671, in execute
raise GitCommandError(command, status, stderr_value, stdout_value)
GitCommandError: Cmd('git') failed due to: exit code(128)
cmdline: git add 1__Xava verbXXten 1_test _myfile 1_test_other_file 1_XXava-----verbXXten
stderr: 'fatal: pathspec '"1__çava verböten"' did not match any files'
FIXME on appveyor: see https://ci.appveyor.com/project/Byron/gitpython/build/1.0.185
- """)
+ """,
+ )
@with_rw_directory
def test_git_submodules_and_add_sm_with_new_commit(self, rwdir):
- parent = git.Repo.init(osp.join(rwdir, 'parent'))
- parent.git.submodule('add', self._small_repo_url(), 'module')
+ parent = git.Repo.init(osp.join(rwdir, "parent"))
+ parent.git.submodule("add", self._small_repo_url(), "module")
parent.index.commit("added submodule")
assert len(parent.submodules) == 1
@@ -697,9 +781,11 @@ class TestSubmodule(TestBase):
assert sm.exists() and sm.module_exists()
- clone = git.Repo.clone_from(self._small_repo_url(),
- osp.join(parent.working_tree_dir, 'existing-subrepository'))
- sm2 = parent.create_submodule('nongit-file-submodule', clone.working_tree_dir)
+ clone = git.Repo.clone_from(
+ self._small_repo_url(),
+ osp.join(parent.working_tree_dir, "existing-subrepository"),
+ )
+ sm2 = parent.create_submodule("nongit-file-submodule", clone.working_tree_dir)
assert len(parent.submodules) == 2
for _ in range(2):
@@ -709,26 +795,28 @@ class TestSubmodule(TestBase):
# end for each init state
# end for each iteration
- sm.move(sm.path + '_moved')
- sm2.move(sm2.path + '_moved')
+ sm.move(sm.path + "_moved")
+ sm2.move(sm2.path + "_moved")
parent.index.commit("moved submodules")
with sm.config_writer() as writer:
- writer.set_value('user.email', 'example@example.com')
- writer.set_value('user.name', 'me')
+ writer.set_value("user.email", "example@example.com")
+ writer.set_value("user.name", "me")
smm = sm.module()
- fp = osp.join(smm.working_tree_dir, 'empty-file')
- with open(fp, 'w'):
+ fp = osp.join(smm.working_tree_dir, "empty-file")
+ with open(fp, "w"):
pass
smm.git.add(Git.polish_url(fp))
smm.git.commit(m="new file added")
# submodules are retrieved from the current commit's tree, therefore we can't really get a new submodule
# object pointing to the new submodule commit
- sm_too = parent.submodules['module_moved']
+ sm_too = parent.submodules["module_moved"]
assert parent.head.commit.tree[sm.path].binsha == sm.binsha
- assert sm_too.binsha == sm.binsha, "cached submodule should point to the same commit as updated one"
+ assert (
+ sm_too.binsha == sm.binsha
+ ), "cached submodule should point to the same commit as updated one"
added_bies = parent.index.add([sm]) # added base-index-entries
assert len(added_bies) == 1
@@ -751,21 +839,24 @@ class TestSubmodule(TestBase):
# "'C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\test_work_tree_unsupportedryfa60di\\master_repo\\.git\\objects\\pack\\pack-bc9e0787aef9f69e1591ef38ea0a6f566ec66fe3.idx") # noqa E501
@with_rw_directory
def test_git_submodule_compatibility(self, rwdir):
- parent = git.Repo.init(osp.join(rwdir, 'parent'))
- sm_path = join_path_native('submodules', 'intermediate', 'one')
- sm = parent.create_submodule('mymodules/myname', sm_path, url=self._small_repo_url())
+ parent = git.Repo.init(osp.join(rwdir, "parent"))
+ sm_path = join_path_native("submodules", "intermediate", "one")
+ sm = parent.create_submodule(
+ "mymodules/myname", sm_path, url=self._small_repo_url()
+ )
parent.index.commit("added submodule")
def assert_exists(sm, value=True):
assert sm.exists() == value
assert sm.module_exists() == value
+
# end
# As git is backwards compatible itself, it would still recognize what we do here ... unless we really
# muss it up. That's the only reason why the test is still here ... .
assert len(parent.git.submodule().splitlines()) == 1
- module_repo_path = osp.join(sm.module().working_tree_dir, '.git')
+ module_repo_path = osp.join(sm.module().working_tree_dir, ".git")
assert module_repo_path.startswith(osp.join(parent.working_tree_dir, sm_path))
if not sm._need_gitfile_submodules(parent.git):
assert osp.isdir(module_repo_path)
@@ -773,17 +864,22 @@ class TestSubmodule(TestBase):
else:
assert osp.isfile(module_repo_path)
assert sm.module().has_separate_working_tree()
- assert find_submodule_git_dir(module_repo_path) is not None, "module pointed to by .git file must be valid"
+ assert (
+ find_submodule_git_dir(module_repo_path) is not None
+ ), "module pointed to by .git file must be valid"
# end verify submodule 'style'
# test move
- new_sm_path = join_path_native('submodules', 'one')
+ new_sm_path = join_path_native("submodules", "one")
sm.move(new_sm_path)
assert_exists(sm)
# Add additional submodule level
- csm = sm.module().create_submodule('nested-submodule', join_path_native('nested-submodule', 'working-tree'),
- url=self._small_repo_url())
+ csm = sm.module().create_submodule(
+ "nested-submodule",
+ join_path_native("nested-submodule", "working-tree"),
+ url=self._small_repo_url(),
+ )
sm.module().index.commit("added nested submodule")
sm_head_commit = sm.module().commit()
assert_exists(csm)
@@ -796,24 +892,36 @@ class TestSubmodule(TestBase):
# rename nested submodule
# This name would move itself one level deeper - needs special handling internally
- new_name = csm.name + '/mine'
+ new_name = csm.name + "/mine"
assert csm.rename(new_name).name == new_name
assert_exists(csm)
- assert csm.repo.is_dirty(index=True, working_tree=False), "index must contain changed .gitmodules file"
+ assert csm.repo.is_dirty(
+ index=True, working_tree=False
+ ), "index must contain changed .gitmodules file"
csm.repo.index.commit("renamed module")
# keep_going evaluation
rsm = parent.submodule_update()
assert_exists(sm)
assert_exists(csm)
- with csm.config_writer().set_value('url', 'bar'):
+ with csm.config_writer().set_value("url", "bar"):
pass
- csm.repo.index.commit("Have to commit submodule change for algorithm to pick it up")
- assert csm.url == 'bar'
-
- self.assertRaises(Exception, rsm.update, recursive=True, to_latest_revision=True, progress=prog)
+ csm.repo.index.commit(
+ "Have to commit submodule change for algorithm to pick it up"
+ )
+ assert csm.url == "bar"
+
+ self.assertRaises(
+ Exception,
+ rsm.update,
+ recursive=True,
+ to_latest_revision=True,
+ progress=prog,
+ )
assert_exists(csm)
- rsm.update(recursive=True, to_latest_revision=True, progress=prog, keep_going=True)
+ rsm.update(
+ recursive=True, to_latest_revision=True, progress=prog, keep_going=True
+ )
# remove
sm_module_path = sm.module().git_dir
@@ -826,8 +934,8 @@ class TestSubmodule(TestBase):
@with_rw_directory
def test_remove_norefs(self, rwdir):
- parent = git.Repo.init(osp.join(rwdir, 'parent'))
- sm_name = 'mymodules/myname'
+ parent = git.Repo.init(osp.join(rwdir, "parent"))
+ sm_name = "mymodules/myname"
sm = parent.create_submodule(sm_name, sm_name, url=self._small_repo_url())
assert sm.exists()
@@ -835,24 +943,26 @@ class TestSubmodule(TestBase):
assert sm.repo is parent # yoh was surprised since expected sm repo!!
# so created a new instance for submodule
- smrepo = git.Repo(osp.join(rwdir, 'parent', sm.path))
+ smrepo = git.Repo(osp.join(rwdir, "parent", sm.path))
# Adding a remote without fetching so would have no references
- smrepo.create_remote('special', 'git@server-shouldnotmatter:repo.git')
+ smrepo.create_remote("special", "git@server-shouldnotmatter:repo.git")
# And we should be able to remove it just fine
sm.remove()
assert not sm.exists()
@with_rw_directory
def test_rename(self, rwdir):
- parent = git.Repo.init(osp.join(rwdir, 'parent'))
- sm_name = 'mymodules/myname'
+ parent = git.Repo.init(osp.join(rwdir, "parent"))
+ sm_name = "mymodules/myname"
sm = parent.create_submodule(sm_name, sm_name, url=self._small_repo_url())
parent.index.commit("Added submodule")
assert sm.rename(sm_name) is sm and sm.name == sm_name
- assert not sm.repo.is_dirty(index=True, working_tree=False, untracked_files=False)
+ assert not sm.repo.is_dirty(
+ index=True, working_tree=False, untracked_files=False
+ )
- new_path = 'renamed/myname'
+ new_path = "renamed/myname"
assert sm.move(new_path).name == new_path
new_sm_name = "shortname"
@@ -861,8 +971,12 @@ class TestSubmodule(TestBase):
assert sm.exists()
sm_mod = sm.module()
- if osp.isfile(osp.join(sm_mod.working_tree_dir, '.git')) == sm._need_gitfile_submodules(parent.git):
- assert sm_mod.git_dir.endswith(join_path_native('.git', 'modules', new_sm_name))
+ if osp.isfile(
+ osp.join(sm_mod.working_tree_dir, ".git")
+ ) == sm._need_gitfile_submodules(parent.git):
+ assert sm_mod.git_dir.endswith(
+ join_path_native(".git", "modules", new_sm_name)
+ )
# end
@with_rw_directory
@@ -870,33 +984,41 @@ class TestSubmodule(TestBase):
# Setup initial sandbox:
# parent repo has one submodule, which has all the latest changes
source_url = self._small_repo_url()
- sm_source_repo = git.Repo.clone_from(source_url, osp.join(rw_dir, 'sm-source'), b='master')
- parent_repo = git.Repo.init(osp.join(rw_dir, 'parent'))
- sm = parent_repo.create_submodule('mysubmodule', 'subdir/submodule',
- sm_source_repo.working_tree_dir, branch='master')
- parent_repo.index.commit('added submodule')
+ sm_source_repo = git.Repo.clone_from(
+ source_url, osp.join(rw_dir, "sm-source"), b="master"
+ )
+ parent_repo = git.Repo.init(osp.join(rw_dir, "parent"))
+ sm = parent_repo.create_submodule(
+ "mysubmodule",
+ "subdir/submodule",
+ sm_source_repo.working_tree_dir,
+ branch="master",
+ )
+ parent_repo.index.commit("added submodule")
assert sm.exists()
# Create feature branch with one new commit in submodule source
- sm_fb = sm_source_repo.create_head('feature')
+ sm_fb = sm_source_repo.create_head("feature")
sm_fb.checkout()
- new_file = touch(osp.join(sm_source_repo.working_tree_dir, 'new-file'))
+ new_file = touch(osp.join(sm_source_repo.working_tree_dir, "new-file"))
sm_source_repo.index.add([new_file])
sm.repo.index.commit("added new file")
# change designated submodule checkout branch to the new upstream feature branch
with sm.config_writer() as smcw:
- smcw.set_value('branch', sm_fb.name)
+ smcw.set_value("branch", sm_fb.name)
assert sm.repo.is_dirty(index=True, working_tree=False)
sm.repo.index.commit("changed submodule branch to '%s'" % sm_fb)
# verify submodule update with feature branch that leaves currently checked out branch in it's past
sm_mod = sm.module()
prev_commit = sm_mod.commit()
- assert sm_mod.head.ref.name == 'master'
+ assert sm_mod.head.ref.name == "master"
assert parent_repo.submodule_update()
assert sm_mod.head.ref.name == sm_fb.name
- assert sm_mod.commit() == prev_commit, "Without to_latest_revision, we don't change the commit"
+ assert (
+ sm_mod.commit() == prev_commit
+ ), "Without to_latest_revision, we don't change the commit"
assert parent_repo.submodule_update(to_latest_revision=True)
assert sm_mod.head.ref.name == sm_fb.name
@@ -904,25 +1026,29 @@ class TestSubmodule(TestBase):
# Create new branch which is in our past, and thus seemingly unrelated to the currently checked out one
# To make it even 'harder', we shall fork and create a new commit
- sm_pfb = sm_source_repo.create_head('past-feature', commit='HEAD~20')
+ sm_pfb = sm_source_repo.create_head("past-feature", commit="HEAD~20")
sm_pfb.checkout()
- sm_source_repo.index.add([touch(osp.join(sm_source_repo.working_tree_dir, 'new-file'))])
+ sm_source_repo.index.add(
+ [touch(osp.join(sm_source_repo.working_tree_dir, "new-file"))]
+ )
sm_source_repo.index.commit("new file added, to past of '%r'" % sm_fb)
# Change designated submodule checkout branch to a new commit in its own past
with sm.config_writer() as smcw:
- smcw.set_value('branch', sm_pfb.path)
+ smcw.set_value("branch", sm_pfb.path)
sm.repo.index.commit("changed submodule branch to '%s'" % sm_pfb)
# Test submodule updates - must fail if submodule is dirty
- touch(osp.join(sm_mod.working_tree_dir, 'unstaged file'))
+ touch(osp.join(sm_mod.working_tree_dir, "unstaged file"))
# This doesn't fail as our own submodule binsha didn't change, and the reset is only triggered if
# to latest revision is True.
parent_repo.submodule_update(to_latest_revision=False)
sm_mod.head.ref.name == sm_pfb.name, "should have been switched to past head"
sm_mod.commit() == sm_fb.commit, "Head wasn't reset"
- self.assertRaises(RepositoryDirtyError, parent_repo.submodule_update, to_latest_revision=True)
+ self.assertRaises(
+ RepositoryDirtyError, parent_repo.submodule_update, to_latest_revision=True
+ )
parent_repo.submodule_update(to_latest_revision=True, force_reset=True)
assert sm_mod.commit() == sm_pfb.commit, "Now head should have been reset"
assert sm_mod.head.ref.name == sm_pfb.name
@@ -930,83 +1056,116 @@ class TestSubmodule(TestBase):
@skipIf(not is_win, "Specifically for Windows.")
def test_to_relative_path_with_super_at_root_drive(self):
class Repo(object):
- working_tree_dir = 'D:\\'
+ working_tree_dir = "D:\\"
+
super_repo = Repo()
- submodule_path = 'D:\\submodule_path'
+ submodule_path = "D:\\submodule_path"
relative_path = Submodule._to_relative_path(super_repo, submodule_path)
- msg = '_to_relative_path should be "submodule_path" but was "%s"' % relative_path
- assert relative_path == 'submodule_path', msg
-
- @skipIf(True, 'for some unknown reason the assertion fails, even though it in fact is working in more common setup')
+ msg = (
+ '_to_relative_path should be "submodule_path" but was "%s"' % relative_path
+ )
+ assert relative_path == "submodule_path", msg
+
+ @skipIf(
+ True,
+ "for some unknown reason the assertion fails, even though it in fact is working in more common setup",
+ )
@with_rw_directory
def test_depth(self, rwdir):
- parent = git.Repo.init(osp.join(rwdir, 'test_depth'))
- sm_name = 'mymodules/myname'
+ parent = git.Repo.init(osp.join(rwdir, "test_depth"))
+ sm_name = "mymodules/myname"
sm_depth = 1
- sm = parent.create_submodule(sm_name, sm_name, url=self._small_repo_url(), depth=sm_depth)
+ sm = parent.create_submodule(
+ sm_name, sm_name, url=self._small_repo_url(), depth=sm_depth
+ )
self.assertEqual(len(list(sm.module().iter_commits())), sm_depth)
@with_rw_directory
def test_update_clone_multi_options_argument(self, rwdir):
- #Arrange
- parent = git.Repo.init(osp.join(rwdir, 'parent'))
- sm_name = 'foo'
+ # Arrange
+ parent = git.Repo.init(osp.join(rwdir, "parent"))
+ sm_name = "foo"
sm_url = self._small_repo_url()
- sm_branch = 'refs/heads/master'
+ sm_branch = "refs/heads/master"
sm_hexsha = git.Repo(self._small_repo_url()).head.commit.hexsha
- sm = Submodule(parent, bytes.fromhex(sm_hexsha), name=sm_name, path=sm_name, url=sm_url,
- branch_path=sm_branch)
-
- #Act
- sm.update(init=True, clone_multi_options=['--config core.eol=true'])
-
- #Assert
- sm_config = GitConfigParser(file_or_files=osp.join(parent.git_dir, 'modules', sm_name, 'config'))
- self.assertTrue(sm_config.get_value('core', 'eol'))
+ sm = Submodule(
+ parent,
+ bytes.fromhex(sm_hexsha),
+ name=sm_name,
+ path=sm_name,
+ url=sm_url,
+ branch_path=sm_branch,
+ )
+
+ # Act
+ sm.update(init=True, clone_multi_options=["--config core.eol=true"])
+
+ # Assert
+ sm_config = GitConfigParser(
+ file_or_files=osp.join(parent.git_dir, "modules", sm_name, "config")
+ )
+ self.assertTrue(sm_config.get_value("core", "eol"))
@with_rw_directory
def test_update_no_clone_multi_options_argument(self, rwdir):
- #Arrange
- parent = git.Repo.init(osp.join(rwdir, 'parent'))
- sm_name = 'foo'
+ # Arrange
+ parent = git.Repo.init(osp.join(rwdir, "parent"))
+ sm_name = "foo"
sm_url = self._small_repo_url()
- sm_branch = 'refs/heads/master'
+ sm_branch = "refs/heads/master"
sm_hexsha = git.Repo(self._small_repo_url()).head.commit.hexsha
- sm = Submodule(parent, bytes.fromhex(sm_hexsha), name=sm_name, path=sm_name, url=sm_url,
- branch_path=sm_branch)
-
- #Act
+ sm = Submodule(
+ parent,
+ bytes.fromhex(sm_hexsha),
+ name=sm_name,
+ path=sm_name,
+ url=sm_url,
+ branch_path=sm_branch,
+ )
+
+ # Act
sm.update(init=True)
- #Assert
- sm_config = GitConfigParser(file_or_files=osp.join(parent.git_dir, 'modules', sm_name, 'config'))
+ # Assert
+ sm_config = GitConfigParser(
+ file_or_files=osp.join(parent.git_dir, "modules", sm_name, "config")
+ )
with self.assertRaises(cp.NoOptionError):
- sm_config.get_value('core', 'eol')
+ sm_config.get_value("core", "eol")
@with_rw_directory
def test_add_clone_multi_options_argument(self, rwdir):
- #Arrange
- parent = git.Repo.init(osp.join(rwdir, 'parent'))
- sm_name = 'foo'
-
- #Act
- Submodule.add(parent, sm_name, sm_name, url=self._small_repo_url(),
- clone_multi_options=['--config core.eol=true'])
-
- #Assert
- sm_config = GitConfigParser(file_or_files=osp.join(parent.git_dir, 'modules', sm_name, 'config'))
- self.assertTrue(sm_config.get_value('core', 'eol'))
+ # Arrange
+ parent = git.Repo.init(osp.join(rwdir, "parent"))
+ sm_name = "foo"
+
+ # Act
+ Submodule.add(
+ parent,
+ sm_name,
+ sm_name,
+ url=self._small_repo_url(),
+ clone_multi_options=["--config core.eol=true"],
+ )
+
+ # Assert
+ sm_config = GitConfigParser(
+ file_or_files=osp.join(parent.git_dir, "modules", sm_name, "config")
+ )
+ self.assertTrue(sm_config.get_value("core", "eol"))
@with_rw_directory
def test_add_no_clone_multi_options_argument(self, rwdir):
- #Arrange
- parent = git.Repo.init(osp.join(rwdir, 'parent'))
- sm_name = 'foo'
+ # Arrange
+ parent = git.Repo.init(osp.join(rwdir, "parent"))
+ sm_name = "foo"
- #Act
+ # Act
Submodule.add(parent, sm_name, sm_name, url=self._small_repo_url())
- #Assert
- sm_config = GitConfigParser(file_or_files=osp.join(parent.git_dir, 'modules', sm_name, 'config'))
+ # Assert
+ sm_config = GitConfigParser(
+ file_or_files=osp.join(parent.git_dir, "modules", sm_name, "config")
+ )
with self.assertRaises(cp.NoOptionError):
- sm_config.get_value('core', 'eol')
+ sm_config.get_value("core", "eol")
diff --git a/test/test_tree.py b/test/test_tree.py
index 24c401cb..97067fb2 100644
--- a/test/test_tree.py
+++ b/test/test_tree.py
@@ -7,10 +7,7 @@
from io import BytesIO
from unittest import skipIf
-from git.objects import (
- Tree,
- Blob
-)
+from git.objects import Tree, Blob
from test.lib import TestBase
from git.util import HIDE_WINDOWS_KNOWN_ERRORS
@@ -18,22 +15,24 @@ import os.path as osp
class TestTree(TestBase):
-
- @skipIf(HIDE_WINDOWS_KNOWN_ERRORS, """
+ @skipIf(
+ HIDE_WINDOWS_KNOWN_ERRORS,
+ """
File "C:\\projects\\gitpython\\git\\cmd.py", line 559, in execute
raise GitCommandNotFound(command, err)
git.exc.GitCommandNotFound: Cmd('git') not found due to: OSError('[WinError 6] The handle is invalid')
- cmdline: git cat-file --batch-check""")
+ cmdline: git cat-file --batch-check""",
+ )
def test_serializable(self):
# tree at the given commit contains a submodule as well
- roottree = self.rorepo.tree('6c1faef799095f3990e9970bc2cb10aa0221cf9c')
+ roottree = self.rorepo.tree("6c1faef799095f3990e9970bc2cb10aa0221cf9c")
for item in roottree.traverse(ignore_self=False):
if item.type != Tree.type:
continue
# END skip non-trees
tree = item
# trees have no dict
- self.assertRaises(AttributeError, setattr, tree, 'someattr', 1)
+ self.assertRaises(AttributeError, setattr, tree, "someattr", 1)
orig_data = tree.data_stream.read()
orig_cache = tree._cache
@@ -43,22 +42,25 @@ class TestTree(TestBase):
assert stream.getvalue() == orig_data
stream.seek(0)
- testtree = Tree(self.rorepo, Tree.NULL_BIN_SHA, 0, '')
+ testtree = Tree(self.rorepo, Tree.NULL_BIN_SHA, 0, "")
testtree._deserialize(stream)
assert testtree._cache == orig_cache
# replaces cache, but we make sure of it
- del(testtree._cache)
+ del testtree._cache
testtree._deserialize(stream)
# END for each item in tree
- @skipIf(HIDE_WINDOWS_KNOWN_ERRORS, """
+ @skipIf(
+ HIDE_WINDOWS_KNOWN_ERRORS,
+ """
File "C:\\projects\\gitpython\\git\\cmd.py", line 559, in execute
raise GitCommandNotFound(command, err)
git.exc.GitCommandNotFound: Cmd('git') not found due to: OSError('[WinError 6] The handle is invalid')
- cmdline: git cat-file --batch-check""")
+ cmdline: git cat-file --batch-check""",
+ )
def test_traverse(self):
- root = self.rorepo.tree('0.1.6')
+ root = self.rorepo.tree("0.1.6")
num_recursive = 0
all_items = []
for obj in root.traverse():
@@ -72,7 +74,7 @@ class TestTree(TestBase):
# limit recursion level to 0 - should be same as default iteration
assert all_items
- assert 'CHANGES' in root
+ assert "CHANGES" in root
assert len(list(root)) == len(list(root.traverse(depth=1)))
# only choose trees
@@ -87,7 +89,9 @@ class TestTree(TestBase):
# trees and blobs
assert len(set(trees) | set(root.trees)) == len(trees)
- assert len({b for b in root if isinstance(b, Blob)} | set(root.blobs)) == len(root.blobs)
+ assert len({b for b in root if isinstance(b, Blob)} | set(root.blobs)) == len(
+ root.blobs
+ )
subitem = trees[0][0]
assert "/" in subitem.path
assert subitem.name == osp.basename(subitem.path)
@@ -96,7 +100,7 @@ class TestTree(TestBase):
found_slash = False
for item in root.traverse():
assert osp.isabs(item.abspath)
- if '/' in item.path:
+ if "/" in item.path:
found_slash = True
# END check for slash
diff --git a/test/test_util.py b/test/test_util.py
index a213b46c..b2903620 100644
--- a/test/test_util.py
+++ b/test/test_util.py
@@ -21,7 +21,8 @@ from git.objects.util import (
verify_utctz,
parse_date,
tzoffset,
- from_timestamp)
+ from_timestamp,
+)
from test.lib import (
TestBase,
with_rw_repo,
@@ -39,35 +40,31 @@ from git.util import (
_norm_cygpath_pairs = (
- (r'foo\bar', 'foo/bar'),
- (r'foo/bar', 'foo/bar'),
-
- (r'C:\Users', '/cygdrive/c/Users'),
- (r'C:\d/e', '/cygdrive/c/d/e'),
-
- ('C:\\', '/cygdrive/c/'),
-
- (r'\\server\C$\Users', '//server/C$/Users'),
- (r'\\server\C$', '//server/C$'),
- ('\\\\server\\c$\\', '//server/c$/'),
- (r'\\server\BAR/', '//server/BAR/'),
-
- (r'D:/Apps', '/cygdrive/d/Apps'),
- (r'D:/Apps\fOO', '/cygdrive/d/Apps/fOO'),
- (r'D:\Apps/123', '/cygdrive/d/Apps/123'),
+ (r"foo\bar", "foo/bar"),
+ (r"foo/bar", "foo/bar"),
+ (r"C:\Users", "/cygdrive/c/Users"),
+ (r"C:\d/e", "/cygdrive/c/d/e"),
+ ("C:\\", "/cygdrive/c/"),
+ (r"\\server\C$\Users", "//server/C$/Users"),
+ (r"\\server\C$", "//server/C$"),
+ ("\\\\server\\c$\\", "//server/c$/"),
+ (r"\\server\BAR/", "//server/BAR/"),
+ (r"D:/Apps", "/cygdrive/d/Apps"),
+ (r"D:/Apps\fOO", "/cygdrive/d/Apps/fOO"),
+ (r"D:\Apps/123", "/cygdrive/d/Apps/123"),
)
_unc_cygpath_pairs = (
- (r'\\?\a:\com', '/cygdrive/a/com'),
- (r'\\?\a:/com', '/cygdrive/a/com'),
-
- (r'\\?\UNC\server\D$\Apps', '//server/D$/Apps'),
+ (r"\\?\a:\com", "/cygdrive/a/com"),
+ (r"\\?\a:/com", "/cygdrive/a/com"),
+ (r"\\?\UNC\server\D$\Apps", "//server/D$/Apps"),
)
class TestIterableMember(object):
"""A member of an iterable list"""
+
__slots__ = "name"
def __init__(self, name):
@@ -79,7 +76,6 @@ class TestIterableMember(object):
@ddt.ddt
class TestUtils(TestBase):
-
def setup(self):
self.testdict = {
"string": "42",
@@ -96,11 +92,11 @@ class TestUtils(TestBase):
@skipIf(not is_win, "Paths specifically for Windows.")
@ddt.data(
- (r'./bar', 'bar'),
- (r'.\bar', 'bar'),
- (r'../bar', '../bar'),
- (r'..\bar', '../bar'),
- (r'../bar/.\foo/../chu', '../bar/chu'),
+ (r"./bar", "bar"),
+ (r".\bar", "bar"),
+ (r"../bar", "../bar"),
+ (r"..\bar", "../bar"),
+ (r"../bar/.\foo/../chu", "../bar/chu"),
)
def test_cygpath_norm_ok(self, case):
wpath, cpath = case
@@ -109,27 +105,27 @@ class TestUtils(TestBase):
@skipIf(not is_win, "Paths specifically for Windows.")
@ddt.data(
- r'C:',
- r'C:Relative',
- r'D:Apps\123',
- r'D:Apps/123',
- r'\\?\a:rel',
- r'\\share\a:rel',
+ r"C:",
+ r"C:Relative",
+ r"D:Apps\123",
+ r"D:Apps/123",
+ r"\\?\a:rel",
+ r"\\share\a:rel",
)
def test_cygpath_invalids(self, wpath):
cwpath = cygpath(wpath)
- self.assertEqual(cwpath, wpath.replace('\\', '/'), wpath)
+ self.assertEqual(cwpath, wpath.replace("\\", "/"), wpath)
@skipIf(not is_win, "Paths specifically for Windows.")
@ddt.idata(_norm_cygpath_pairs)
def test_decygpath(self, case):
wpath, cpath = case
wcpath = decygpath(cpath)
- self.assertEqual(wcpath, wpath.replace('/', '\\'), cpath)
+ self.assertEqual(wcpath, wpath.replace("/", "\\"), cpath)
def test_it_should_dashify(self):
- self.assertEqual('this-is-my-argument', dashify('this_is_my_argument'))
- self.assertEqual('foo', dashify('foo'))
+ self.assertEqual("this-is-my-argument", dashify("this_is_my_argument"))
+ self.assertEqual("foo", dashify("foo"))
def test_lock_file(self):
my_file = tempfile.mktemp()
@@ -154,7 +150,7 @@ class TestUtils(TestBase):
self.assertRaises(IOError, lock_file._obtain_lock_or_raise)
# auto-release on destruction
- del(other_lock_file)
+ del other_lock_file
lock_file._obtain_lock_or_raise()
lock_file._release_lock()
@@ -176,12 +172,18 @@ class TestUtils(TestBase):
self.assertLess(elapsed, wait_time + extra_time)
def test_user_id(self):
- self.assertIn('@', get_user_id())
+ self.assertIn("@", get_user_id())
def test_parse_date(self):
# parse_date(from_timestamp()) must return the tuple unchanged
- for timestamp, offset in (1522827734, -7200), (1522827734, 0), (1522827734, +3600):
- self.assertEqual(parse_date(from_timestamp(timestamp, offset)), (timestamp, offset))
+ for timestamp, offset in (
+ (1522827734, -7200),
+ (1522827734, 0),
+ (1522827734, +3600),
+ ):
+ self.assertEqual(
+ parse_date(from_timestamp(timestamp, offset)), (timestamp, offset)
+ )
# test all supported formats
def assert_rval(rval, veri_time, offset=0):
@@ -195,6 +197,7 @@ class TestUtils(TestBase):
utctz = altz_to_utctz_str(offset)
self.assertIsInstance(utctz, str)
self.assertEqual(utctz_to_altz(verify_utctz(utctz)), offset)
+
# END assert rval utility
rfc = ("Thu, 07 Apr 2005 22:13:11 +0000", 0)
@@ -203,16 +206,16 @@ class TestUtils(TestBase):
iso3 = ("2005.04.07 22:13:11 -0000", 0)
alt = ("04/07/2005 22:13:11", 0)
alt2 = ("07.04.2005 22:13:11", 0)
- veri_time_utc = 1112911991 # the time this represents, in time since epoch, UTC
+ veri_time_utc = 1112911991 # the time this represents, in time since epoch, UTC
for date, offset in (rfc, iso, iso2, iso3, alt, alt2):
assert_rval(parse_date(date), veri_time_utc, offset)
# END for each date type
# and failure
self.assertRaises(ValueError, parse_date, datetime.now()) # non-aware datetime
- self.assertRaises(ValueError, parse_date, 'invalid format')
- self.assertRaises(ValueError, parse_date, '123456789 -02000')
- self.assertRaises(ValueError, parse_date, ' 123456789 -0200')
+ self.assertRaises(ValueError, parse_date, "invalid format")
+ self.assertRaises(ValueError, parse_date, "123456789 -02000")
+ self.assertRaises(ValueError, parse_date, " 123456789 -0200")
def test_actor(self):
for cr in (None, self.rorepo.config_reader()):
@@ -220,23 +223,23 @@ class TestUtils(TestBase):
self.assertIsInstance(Actor.author(cr), Actor)
# END assure config reader is handled
- @with_rw_repo('HEAD')
+ @with_rw_repo("HEAD")
@mock.patch("getpass.getuser")
def test_actor_get_uid_laziness_not_called(self, rwrepo, mock_get_uid):
with rwrepo.config_writer() as cw:
cw.set_value("user", "name", "John Config Doe")
cw.set_value("user", "email", "jcdoe@example.com")
-
+
cr = rwrepo.config_reader()
committer = Actor.committer(cr)
author = Actor.author(cr)
-
- self.assertEqual(committer.name, 'John Config Doe')
- self.assertEqual(committer.email, 'jcdoe@example.com')
- self.assertEqual(author.name, 'John Config Doe')
- self.assertEqual(author.email, 'jcdoe@example.com')
+
+ self.assertEqual(committer.name, "John Config Doe")
+ self.assertEqual(committer.email, "jcdoe@example.com")
+ self.assertEqual(author.name, "John Config Doe")
+ self.assertEqual(author.email, "jcdoe@example.com")
self.assertFalse(mock_get_uid.called)
-
+
env = {
"GIT_AUTHOR_NAME": "John Doe",
"GIT_AUTHOR_EMAIL": "jdoe@example.com",
@@ -247,10 +250,10 @@ class TestUtils(TestBase):
for cr in (None, rwrepo.config_reader()):
committer = Actor.committer(cr)
author = Actor.author(cr)
- self.assertEqual(committer.name, 'Jane Doe')
- self.assertEqual(committer.email, 'jane@example.com')
- self.assertEqual(author.name, 'John Doe')
- self.assertEqual(author.email, 'jdoe@example.com')
+ self.assertEqual(committer.name, "Jane Doe")
+ self.assertEqual(committer.email, "jane@example.com")
+ self.assertEqual(author.name, "John Doe")
+ self.assertEqual(author.email, "jdoe@example.com")
self.assertFalse(mock_get_uid.called)
@mock.patch("getpass.getuser")
@@ -260,20 +263,22 @@ class TestUtils(TestBase):
author = Actor.author(None)
# We can't test with `self.rorepo.config_reader()` here, as the uuid laziness
# depends on whether the user running the test has their global user.name config set.
- self.assertEqual(committer.name, 'user')
- self.assertTrue(committer.email.startswith('user@'))
- self.assertEqual(author.name, 'user')
- self.assertTrue(committer.email.startswith('user@'))
+ self.assertEqual(committer.name, "user")
+ self.assertTrue(committer.email.startswith("user@"))
+ self.assertEqual(author.name, "user")
+ self.assertTrue(committer.email.startswith("user@"))
self.assertTrue(mock_get_uid.called)
self.assertEqual(mock_get_uid.call_count, 2)
def test_actor_from_string(self):
self.assertEqual(Actor._from_string("name"), Actor("name", None))
self.assertEqual(Actor._from_string("name <>"), Actor("name", ""))
- self.assertEqual(Actor._from_string("name last another <some-very-long-email@example.com>"),
- Actor("name last another", "some-very-long-email@example.com"))
+ self.assertEqual(
+ Actor._from_string("name last another <some-very-long-email@example.com>"),
+ Actor("name last another", "some-very-long-email@example.com"),
+ )
- @ddt.data(('name', ''), ('name', 'prefix_'))
+ @ddt.data(("name", ""), ("name", "prefix_"))
def test_iterable_list(self, case):
name, prefix = case
ilist = IterableList(name, prefix)
@@ -292,7 +297,7 @@ class TestUtils(TestBase):
self.assertIn(name2, ilist)
self.assertIn(m2, ilist)
self.assertIn(m2, ilist)
- self.assertNotIn('invalid', ilist)
+ self.assertNotIn("invalid", ilist)
# with string index
self.assertIs(ilist[name1], m1)
@@ -307,34 +312,43 @@ class TestUtils(TestBase):
self.assertIs(ilist.two, m2)
# test exceptions
- self.assertRaises(AttributeError, getattr, ilist, 'something')
- self.assertRaises(IndexError, ilist.__getitem__, 'something')
+ self.assertRaises(AttributeError, getattr, ilist, "something")
+ self.assertRaises(IndexError, ilist.__getitem__, "something")
# delete by name and index
- self.assertRaises(IndexError, ilist.__delitem__, 'something')
- del(ilist[name2])
+ self.assertRaises(IndexError, ilist.__delitem__, "something")
+ del ilist[name2]
self.assertEqual(len(ilist), 1)
self.assertNotIn(name2, ilist)
self.assertIn(name1, ilist)
- del(ilist[0])
+ del ilist[0]
self.assertNotIn(name1, ilist)
self.assertEqual(len(ilist), 0)
self.assertRaises(IndexError, ilist.__delitem__, 0)
- self.assertRaises(IndexError, ilist.__delitem__, 'something')
+ self.assertRaises(IndexError, ilist.__delitem__, "something")
def test_from_timestamp(self):
# Correct offset: UTC+2, should return datetime + tzoffset(+2)
- altz = utctz_to_altz('+0200')
- self.assertEqual(datetime.fromtimestamp(1522827734, tzoffset(altz)), from_timestamp(1522827734, altz))
+ altz = utctz_to_altz("+0200")
+ self.assertEqual(
+ datetime.fromtimestamp(1522827734, tzoffset(altz)),
+ from_timestamp(1522827734, altz),
+ )
# Wrong offset: UTC+58, should return datetime + tzoffset(UTC)
- altz = utctz_to_altz('+5800')
- self.assertEqual(datetime.fromtimestamp(1522827734, tzoffset(0)), from_timestamp(1522827734, altz))
+ altz = utctz_to_altz("+5800")
+ self.assertEqual(
+ datetime.fromtimestamp(1522827734, tzoffset(0)),
+ from_timestamp(1522827734, altz),
+ )
# Wrong offset: UTC-9000, should return datetime + tzoffset(UTC)
- altz = utctz_to_altz('-9000')
- self.assertEqual(datetime.fromtimestamp(1522827734, tzoffset(0)), from_timestamp(1522827734, altz))
+ altz = utctz_to_altz("-9000")
+ self.assertEqual(
+ datetime.fromtimestamp(1522827734, tzoffset(0)),
+ from_timestamp(1522827734, altz),
+ )
def test_pickle_tzoffset(self):
t1 = tzoffset(555)
@@ -345,7 +359,9 @@ class TestUtils(TestBase):
def test_remove_password_from_command_line(self):
username = "fakeuser"
password = "fakepassword1234"
- url_with_user_and_pass = "https://{}:{}@fakerepo.example.com/testrepo".format(username, password)
+ url_with_user_and_pass = "https://{}:{}@fakerepo.example.com/testrepo".format(
+ username, password
+ )
url_with_user = "https://{}@fakerepo.example.com/testrepo".format(username)
url_with_pass = "https://:{}@fakerepo.example.com/testrepo".format(password)
url_without_user_or_pass = "https://fakerepo.example.com/testrepo"
diff --git a/test/tstrunner.py b/test/tstrunner.py
index a3bcfa3c..441050c6 100644
--- a/test/tstrunner.py
+++ b/test/tstrunner.py
@@ -1,6 +1,7 @@
import unittest
+
loader = unittest.TestLoader()
-start_dir = '.'
+start_dir = "."
suite = loader.discover(start_dir)
runner = unittest.TextTestRunner()