summaryrefslogtreecommitdiffhomepage
path: root/tests/doctests
diff options
context:
space:
mode:
authorGuido Günther <agx@sigxcpu.org>2016-11-04 15:37:07 +0100
committerGuido Günther <agx@sigxcpu.org>2016-11-04 15:47:54 +0100
commitced46db062f8e38c0eed7d1feb6e6e8b0d6435f9 (patch)
tree6fda6af97a5ebe6dbfd79c8d04964611b49b0104 /tests/doctests
parent42657fcf8adb17d63ae904b5cd8abd44388b881e (diff)
tests: Move doctests to subdir
Diffstat (limited to 'tests/doctests')
-rw-r--r--tests/doctests/__init__.py0
-rw-r--r--tests/doctests/test_Changelog.py320
-rw-r--r--tests/doctests/test_Config.py103
-rw-r--r--tests/doctests/test_Control.py93
-rw-r--r--tests/doctests/test_GitModifier.py84
-rw-r--r--tests/doctests/test_GitRepository.py999
-rw-r--r--tests/doctests/test_GitVfs.py56
-rw-r--r--tests/doctests/test_PristineTar.py158
-rw-r--r--tests/doctests/test_create_remote_repo.py122
9 files changed, 1935 insertions, 0 deletions
diff --git a/tests/doctests/__init__.py b/tests/doctests/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tests/doctests/__init__.py
diff --git a/tests/doctests/test_Changelog.py b/tests/doctests/test_Changelog.py
new file mode 100644
index 00000000..9525e76d
--- /dev/null
+++ b/tests/doctests/test_Changelog.py
@@ -0,0 +1,320 @@
+# vim: set fileencoding=utf-8 :
+
+"""
+Test L{gbp.deb.changelog.ChangeLog}
+"""
+from .. import context # noqa: 401
+import os
+import nose
+
+cl_debian = """git-buildpackage (0.5.32) unstable; urgency=low
+
+ * [efe9220] Use known_compressions in guess_upstream_version too
+ (Closes: #645477)
+ * [e984baf] git-import-orig: fix --filter
+
+ -- Guido Günther <agx@sigxcpu.org> Mon, 17 Oct 2011 10:15:22 +0200
+
+git-buildpackage (0.5.31) unstable; urgency=low
+
+ [ Guido Günther ]
+ * [3588d88] Fix pristine-tar error message
+ * [8da98da] gbp-pq: don't fail on missing series file but create an empty
+ branch instead
+
+ [ Salvatore Bonaccorso ]
+ * [b33cf74] Fix URL to cl2vcs service.
+ Refer to https://honk.sigxcpu.org/cl2vcs instead of
+ https://honk.sigxcpu.org/cl2vcs for the cl2vcs service. (Closes: #640141)
+
+ -- Guido Günther <agx@sigxcpu.org> Wed, 28 Sep 2011 20:21:34 +0200
+"""
+
+cl_upstream = """python-dateutil (1.0-1) unstable; urgency=low
+
+ * Initial release (Closes: #386256)
+
+ -- Guido Günther <agx@sigxcpu.org> Wed, 6 Sep 2006 10:33:06 +0200
+"""
+
+cl_epoch = """xserver-xorg-video-nv (1:1.2.0-3) unstable; urgency=low
+
+ [ Steve Langasek ]
+ * Upload to unstable
+
+ -- David Nusinow <dnusinow@debian.org> Mon, 18 Sep 2006 19:57:45 -0400
+"""
+
+
+def setup():
+ """Setup test module"""
+ if not os.path.exists('/usr/bin/debchange'):
+ raise nose.SkipTest('debchange tool not present')
+
+
+def test_parse_debian_only():
+ """
+ Parse a the changelog of debian only package
+
+ Methods tested:
+ - L{gbp.deb.changelog.ChangeLog.__init__}
+
+ Properties tested:
+ - L{gbp.deb.changelog.ChangeLog.version}
+ - L{gbp.deb.changelog.ChangeLog.debian_version}
+ - L{gbp.deb.changelog.ChangeLog.upstream_version}
+ - L{gbp.deb.changelog.ChangeLog.epoch}
+ - L{gbp.deb.changelog.ChangeLog.noepoch}
+
+ >>> import gbp.deb.changelog
+ >>> cl = gbp.deb.changelog.ChangeLog(cl_debian)
+ >>> cl.version
+ '0.5.32'
+ >>> cl.version == cl['Version']
+ True
+ >>> cl.debian_version
+ '0.5.32'
+ >>> cl.debian_version == cl['Debian-Version']
+ True
+ >>> cl.noepoch
+ '0.5.32'
+ >>> cl.noepoch == cl['NoEpoch-Version']
+ True
+ >>> cl.epoch
+ >>> cl.upstream_version
+ """
+
+
+def test_parse_no_eopch():
+ """
+ Parse a the changelog of a package without eopch
+
+ Methods tested:
+ - L{gbp.deb.changelog.ChangeLog.__init__}
+ - L{gbp.deb.changelog.ChangeLog.has_epoch}
+
+ Properties tested:
+ - L{gbp.deb.changelog.ChangeLog.version}
+ - L{gbp.deb.changelog.ChangeLog.debian_version}
+ - L{gbp.deb.changelog.ChangeLog.upstream_version}
+ - L{gbp.deb.changelog.ChangeLog.epoch}
+ - L{gbp.deb.changelog.ChangeLog.noepoch}
+
+ >>> import gbp.deb.changelog
+ >>> cl = gbp.deb.changelog.ChangeLog(cl_upstream)
+ >>> cl.version
+ '1.0-1'
+ >>> cl.version == cl['Version']
+ True
+ >>> cl.debian_version
+ '1'
+ >>> cl.debian_version == cl['Debian-Version']
+ True
+ >>> cl.noepoch
+ '1.0-1'
+ >>> cl.noepoch == cl['NoEpoch-Version']
+ True
+ >>> cl.epoch
+ >>> cl.upstream_version
+ '1.0'
+ >>> cl.has_epoch()
+ False
+ """
+
+
+def test_parse_eopch():
+ """
+ Parse a the changelog of a package without epoch
+
+ Methods tested:
+ - L{gbp.deb.changelog.ChangeLog.__init__}
+ - L{gbp.deb.changelog.ChangeLog.has_epoch}
+
+ Properties tested:
+ - L{gbp.deb.changelog.ChangeLog.version}
+ - L{gbp.deb.changelog.ChangeLog.debian_version}
+ - L{gbp.deb.changelog.ChangeLog.upstream_version}
+ - L{gbp.deb.changelog.ChangeLog.epoch}
+ - L{gbp.deb.changelog.ChangeLog.noepoch}
+
+ >>> import gbp.deb.changelog
+ >>> cl = gbp.deb.changelog.ChangeLog(cl_epoch)
+ >>> cl.version
+ '1:1.2.0-3'
+ >>> cl.version == cl['Version']
+ True
+ >>> cl.debian_version
+ '3'
+ >>> cl.debian_version == cl['Debian-Version']
+ True
+ >>> cl.noepoch
+ '1.2.0-3'
+ >>> cl.noepoch == cl['NoEpoch-Version']
+ True
+ >>> cl.epoch
+ '1'
+ >>> cl.upstream_version
+ '1.2.0'
+ >>> cl.has_epoch()
+ True
+ """
+
+
+def test_parse_name():
+ """
+ Methods tested:
+ - L{gbp.deb.changelog.ChangeLog.__init__}
+
+ Properties tested:
+ - L{gbp.deb.changelog.ChangeLog.name}
+
+ >>> import gbp.deb.changelog
+ >>> cl = gbp.deb.changelog.ChangeLog(cl_debian)
+ >>> cl.name
+ 'git-buildpackage'
+ """
+
+
+def test_parse_last_mod():
+ """
+ Test author, email and date of last modification
+
+ Methods tested:
+ - L{gbp.deb.changelog.ChangeLog.__init__}
+
+ Properties tested:
+ - L{gbp.deb.changelog.ChangeLog.name}
+ - L{gbp.deb.changelog.ChangeLog.email}
+ - L{gbp.deb.changelog.ChangeLog.date}
+
+ >>> import gbp.deb.changelog
+ >>> cl = gbp.deb.changelog.ChangeLog(cl_debian)
+ >>> cl.author.startswith('Guido')
+ True
+ >>> cl.email
+ 'agx@sigxcpu.org'
+ >>> cl.date
+ 'Mon, 17 Oct 2011 10:15:22 +0200'
+ """
+
+
+def test_parse_sections():
+ """
+ Test if we can parse sections out of the changelog
+
+ Methods tested:
+ - L{gbp.deb.changelog.ChangeLog.__init__}
+ - L{gbp.deb.changelog.ChangeLogSection.__init__}
+ - L{gbp.deb.changelog.ChangeLogSection.parse}
+
+ Properties tested:
+ - L{gbp.deb.changelog.ChangeLog.sections}
+
+ >>> import gbp.deb.changelog
+ >>> cl = gbp.deb.changelog.ChangeLog(cl_debian)
+ >>> cl.sections[0].package
+ 'git-buildpackage'
+ >>> cl.sections[0].version
+ '0.5.32'
+ >>> cl.sections[1].package
+ 'git-buildpackage'
+ >>> cl.sections[1].version
+ '0.5.31'
+ """
+
+
+def test_add_section():
+ """
+ Test if we can add a section to an existing changelog
+
+ Methods tested:
+ - L{gbp.deb.changelog.ChangeLog.__init__}
+ - L{gbp.deb.changelog.ChangeLog._parse}
+ - L{gbp.deb.changelog.ChangeLog.add_section}
+ - L{gbp.deb.changelog.ChangeLog.spawn_dch}
+
+ >>> import os
+ >>> import tempfile
+ >>> import shutil
+ >>> import gbp.deb.changelog
+ >>> from ..testutils import OsReleaseFile
+ >>> os_release = OsReleaseFile('/etc/lsb-release')
+ >>> olddir = os.path.abspath(os.path.curdir)
+ >>> testdir = tempfile.mkdtemp(prefix='gbp-test-changelog-')
+ >>> testdebdir = os.path.join(testdir, 'debian')
+ >>> testclname = os.path.join(testdebdir, "changelog")
+ >>> os.mkdir(testdebdir)
+ >>> clh = open(os.path.join(testdebdir, "changelog"), "w")
+ >>> ret = clh.write(cl_debian)
+ >>> clh.close()
+ >>> os.chdir(testdir)
+ >>> os.path.abspath(os.path.curdir) == testdir
+ True
+ >>> cl = gbp.deb.changelog.ChangeLog(filename=testclname)
+ >>> cl.add_section(msg=["Test add section"], distribution=None, author="Debian Maintainer", email="maint@debian.org")
+ >>> cl = gbp.deb.changelog.ChangeLog(filename=testclname)
+ >>> version = '0.5.32ubuntu1' if os_release['DISTRIB_ID'] == 'Ubuntu' else '0.5.33'
+ >>> cl.version == version
+ True
+ >>> cl.debian_version == version
+ True
+ >>> distributions = ['UNRELEASED', os_release['DISTRIB_CODENAME'] or 'unstable']
+ >>> cl['Distribution'] in distributions
+ True
+ >>> 'Test add section' in cl['Changes']
+ True
+ >>> os.chdir(olddir)
+ >>> os.path.abspath(os.path.curdir) == olddir
+ True
+ >>> shutil.rmtree(testdir, ignore_errors=True)
+ """
+
+
+def test_add_entry():
+ """
+ Test if we can add an entry to an existing changelog
+
+ Methods tested:
+ - L{gbp.deb.changelog.ChangeLog.__init__}
+ - L{gbp.deb.changelog.ChangeLog._parse}
+ - L{gbp.deb.changelog.ChangeLog.add_entry}
+ - L{gbp.deb.changelog.ChangeLog.spawn_dch}
+
+ >>> import os
+ >>> import tempfile
+ >>> import shutil
+ >>> import gbp.deb.changelog
+ >>> from ..testutils import OsReleaseFile
+ >>> os_release = OsReleaseFile('/etc/lsb-release')
+ >>> olddir = os.path.abspath(os.path.curdir)
+ >>> testdir = tempfile.mkdtemp(prefix='gbp-test-changelog-')
+ >>> testdebdir = os.path.join(testdir, 'debian')
+ >>> testclname = os.path.join(testdebdir, "changelog")
+ >>> os.mkdir(testdebdir)
+ >>> clh = open(os.path.join(testdebdir, "changelog"), "w")
+ >>> ret = clh.write(cl_debian)
+ >>> clh.close()
+ >>> os.chdir(testdir)
+ >>> os.path.abspath(os.path.curdir) == testdir
+ True
+ >>> cl = gbp.deb.changelog.ChangeLog(filename=testclname)
+ >>> cl.add_section(msg=["Test add section"], distribution=None, author="Debian Maintainer", email="maint@debian.org")
+ >>> cl.add_entry(msg=["Test add entry"], author="Debian Maintainer", email="maint@debian.org")
+ >>> cl = gbp.deb.changelog.ChangeLog(filename=testclname)
+ >>> version = '0.5.32ubuntu1' if os_release['DISTRIB_ID'] == 'Ubuntu' else '0.5.33'
+ >>> cl.version == version
+ True
+ >>> cl.debian_version == version
+ True
+ >>> distributions = ['UNRELEASED', os_release['DISTRIB_CODENAME'] or 'unstable']
+ >>> cl['Distribution'] in distributions
+ True
+ >>> 'Test add entry' in cl['Changes']
+ True
+ >>> cl['Changes'].split('*',1)[1]
+ ' Test add section\\n * Test add entry'
+ >>> os.chdir(olddir)
+ >>> os.path.abspath(os.path.curdir) == olddir
+ True
+ >>> shutil.rmtree(testdir, ignore_errors=True)
+ """
diff --git a/tests/doctests/test_Config.py b/tests/doctests/test_Config.py
new file mode 100644
index 00000000..d985d830
--- /dev/null
+++ b/tests/doctests/test_Config.py
@@ -0,0 +1,103 @@
+# vim: set fileencoding=utf-8 :
+
+"""
+Test L{gbp.config.GbpOptionParser}
+Test L{gbp.config.GbpOptionParserDebian}
+"""
+
+from .. import context # noqa: F401
+
+
+def test_option_parser():
+ """
+ Methods tested:
+ - L{gbp.config.GbpOptionParser.add_config_file_option}
+ - L{gbp.config.GbpOptionParser.add_boolean_config_file_option}
+
+ >>> import gbp.config
+ >>> c = gbp.config.GbpOptionParser('common', prefix='test')
+ >>> c.add_config_file_option(option_name='upstream-branch', dest='upstream')
+ >>> c.add_boolean_config_file_option(option_name='overlay', dest='overlay')
+ >>> c.add_boolean_config_file_option(option_name='track', dest='track')
+ """
+
+
+def test_option_parser_debian():
+ """
+ Methods tested:
+ - L{gbp.config.GbpOptionParserDebian.add_config_file_option}
+
+ >>> import gbp.config
+ >>> c = gbp.config.GbpOptionParserDebian('debian')
+ >>> c.add_config_file_option(option_name='builder', dest='builder')
+ Traceback (most recent call last):
+ ...
+ KeyError: 'builder'
+ >>> c.add_config_file_option(option_name='builder', dest='builder', help='foo')
+ """
+
+
+def test_option_group():
+ """
+ Methods tested:
+ - L{gbp.config.GbpOptionGroup.add_config_file_option}
+ - L{gbp.config.GbpOptionGroup.add_boolean_config_file_option}
+
+ >>> import gbp.config
+ >>> c = gbp.config.GbpOptionParser('debian')
+ >>> g = gbp.config.GbpOptionGroup(c, 'wheezy')
+ >>> g.add_config_file_option(option_name='debian-branch', dest='branch')
+ >>> g.add_boolean_config_file_option(option_name='track', dest='track')
+ """
+
+
+def test_tristate():
+ """
+ Methods tested:
+ - L{gbp.config.GbpOptionParser.add_config_file_option}
+
+ >>> import gbp.config
+ >>> c = gbp.config.GbpOptionParser('tristate')
+ >>> c.add_config_file_option(option_name="color", dest="color", type='tristate')
+ >>> options, args= c.parse_args(['--color=auto'])
+ >>> options.color
+ auto
+ """
+
+
+def test_filter():
+ """
+ The filter option should always parse as a list
+ >>> import os
+ >>> from gbp.config import GbpOptionParser
+ >>> tmpdir = str(context.new_tmpdir('bar'))
+ >>> confname = os.path.join(tmpdir, 'gbp.conf')
+ >>> GbpOptionParser._set_config_file_value('bar', 'filter', 'asdf', filename=confname)
+ >>> os.environ['GBP_CONF_FILES'] = confname
+ >>> parser = GbpOptionParser('bar')
+ >>> parser.config['filter']
+ ['asdf']
+ >>> f = open(confname, 'w')
+ >>> ret = f.write("[bar]\\nfilter = ['this', 'is', 'a', 'list']\\n")
+ >>> f.close()
+ >>> parser = GbpOptionParser('bar')
+ >>> parser.config['filter']
+ ['this', 'is', 'a', 'list']
+ >>> del os.environ['GBP_CONF_FILES']
+ """
+
+
+def test_filters():
+ """
+ The filter can be given in plural form
+ >>> import os
+ >>> from gbp.config import GbpOptionParser
+ >>> tmpdir = str(context.new_tmpdir('bar'))
+ >>> confname = os.path.join(tmpdir, 'gbp.conf')
+ >>> GbpOptionParser._set_config_file_value('bar', 'filters', '["abc", "def"]\\n', filename=confname)
+ >>> os.environ['GBP_CONF_FILES'] = confname
+ >>> parser = GbpOptionParser('bar')
+ >>> parser.config['filter']
+ ['abc', 'def']
+ >>> del os.environ['GBP_CONF_FILES']
+ """
diff --git a/tests/doctests/test_Control.py b/tests/doctests/test_Control.py
new file mode 100644
index 00000000..3e1b0829
--- /dev/null
+++ b/tests/doctests/test_Control.py
@@ -0,0 +1,93 @@
+# vim: set fileencoding=utf-8 :
+
+"""
+Test L{gbp.deb.control.Control}
+"""
+
+from .. import context # noqa: 401
+
+cl_debian = """Source: git-buildpackage
+Section: vcs
+Priority: optional
+Maintainer: Guido Günther <agx@sigxcpu.org>
+Build-Depends: debhelper (>= 7.0.50~), python (>> 2.6.6-3~),
+ pychecker, gtk-doc-tools, sgml2x, docbook-utils, jade, python-dateutil, python-nose,
+ bash-completion, perl, python-epydoc, python-coverage, python-setuptools,
+ # For the testsuite
+ git (>= 1:1.7.9.1-1~), bzip2, unzip, pristine-tar
+Standards-Version: 3.9.3
+Vcs-Git: git://honk.sigxcpu.org/git/git-buildpackage.git
+Vcs-Browser: http://git.debian.org/?p=users/agx/git-buildpackage.git
+Homepage: https://honk.sigxcpu.org/piki/projects/git-buildpackage/
+X-Python-Version: >= 2.6
+
+Package: git-buildpackage
+Architecture: all
+Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends}, devscripts (>= 2.10.66~),
+ git (>= 1:1.7.9.1-1~), python-dateutil
+Recommends: pristine-tar (>= 0.5), cowbuilder
+Suggests: python-notify, unzip
+Description: Suite to help with Debian packages in Git repositories
+ This package contains the following tools:
+ * git-import-{dsc,dscs}: import existing Debian source packages into a git
+ repository
+ * git-import-orig: import a new upstream version into the git repository
+ * git-buildpackage: build a package out of a git repository, check for local
+ modifications and tag appropriately
+ * git-dch: generate Debian changelog entries from Git commit messages
+ * gbp-{pull,clone}: clone and pull from remote repos
+ * gbp-pq: manage debian/patches easily
+ * gbp-create-remote-repo: create remote repositories
+"""
+
+
+def test_parse_control():
+ """
+ Parse a the control of debian package
+
+ Methods tested:
+ - L{gbp.deb.control.Control.__init__}
+
+ Properties tested:
+ - L{gbp.deb.control.Control.name}
+ - L{gbp.deb.control.Control.section}
+ - L{gbp.deb.control.Control.priority}
+
+ >>> import gbp.deb.control
+ >>> cl = gbp.deb.control.Control(cl_debian)
+ >>> cl.name
+ 'git-buildpackage'
+ >>> cl.name == cl['Source']
+ True
+ >>> cl.section
+ 'vcs'
+ >>> cl.section == cl['Section']
+ True
+ >>> cl.priority
+ 'optional'
+ >>> cl.priority == cl['Priority']
+ True
+ >>> cl['Standards-Version']
+ '3.9.3'
+ >>> cl['Package']
+
+ """
+
+
+def test_no_control_error():
+ """
+ Raise an error if no control file exist or is empty
+
+ Methods tested:
+ - L{gbp.deb.control.Control.__init__}
+
+ >>> import gbp.deb.control
+ >>> cl = gbp.deb.control.Control(filename="doesnotexist")
+ Traceback (most recent call last):
+ ...
+ NoControlError: Control file doesnotexist does not exist
+ >>> cl = gbp.deb.control.Control("notparsable")
+ Traceback (most recent call last):
+ ...
+ ParseControlError: Empty or invalid control file or contents
+ """
diff --git a/tests/doctests/test_GitModifier.py b/tests/doctests/test_GitModifier.py
new file mode 100644
index 00000000..06a31c70
--- /dev/null
+++ b/tests/doctests/test_GitModifier.py
@@ -0,0 +1,84 @@
+# vim: set fileencoding=utf-8 :
+
+"""
+Test L{gbp.git.GitModifier}
+"""
+
+from .. import context # noqa: F401
+
+
+def test_author():
+ """
+ Methods tested:
+ - L{gbp.git.GitModifier.get_author_env}
+ - L{gbp.git.GitModifier.get_committer_env}
+ - L{gbp.git.GitModifier.keys}
+
+ >>> import gbp.git
+ >>> modifier = gbp.git.GitModifier('foo', 'bar')
+ >>> modifier.name
+ 'foo'
+ >>> modifier.email
+ 'bar'
+ >>> modifier.get_author_env()['GIT_AUTHOR_EMAIL']
+ 'bar'
+ >>> modifier.get_author_env()['GIT_AUTHOR_NAME']
+ 'foo'
+ >>> modifier.get_committer_env()['GIT_COMMITTER_NAME']
+ 'foo'
+ >>> modifier.get_committer_env()['GIT_COMMITTER_EMAIL']
+ 'bar'
+ >>> modifier._get_env('foo')
+ Traceback (most recent call last):
+ ...
+ GitModifierError: Neither committer nor author
+ >>> modifier['name']
+ 'foo'
+ >>> modifier['email']
+ 'bar'
+ >>> modifier['date']
+ """
+
+
+def test_date():
+ """
+ Methods tested:
+ - L{gbp.git.GitModifier.__init__}
+
+ Properties tested:
+ - L{gbp.git.GitModifier.date}
+ - L{gbp.git.GitModifier.datetime}
+ - L{gbp.git.GitModifier.tz_offset}
+
+ >>> import gbp.git
+ >>> import datetime
+ >>> modifier = gbp.git.GitModifier('foo', 'bar', 1)
+ >>> modifier.date
+ '1 +0000'
+ >>> modifier.date = '1 +0400'
+ >>> modifier.date
+ '1 +0400'
+ >>> modifier['date']
+ '1 +0400'
+ >>> modifier.datetime # doctest: +ELLIPSIS
+ datetime.datetime(1970, 1, 1, 4, 0, 1, tzinfo=<gbp.git.modifier.GitTz...>)
+ >>> modifier.date = datetime.datetime(1970, 1, 1, 0, 0, 1)
+ >>> modifier.date
+ '1 +0000'
+ >>> modifier.datetime # doctest: +ELLIPSIS
+ datetime.datetime(1970, 1, 1, 0, 0, 1, tzinfo=<gbp.git.modifier.GitTz...>)
+ >>> modifier.tz_offset
+ '+0000'
+ """
+
+
+def test_dict():
+ """
+ Test C{dict} interface
+ >>> import gbp.git
+ >>> modifier = gbp.git.GitModifier('foo', 'bar', 1)
+ >>> sorted(modifier.keys())
+ ['date', 'email', 'name']
+ >>> sorted(modifier.items())
+ [('date', '1 +0000'), ('email', 'bar'), ('name', 'foo')]
+ """
diff --git a/tests/doctests/test_GitRepository.py b/tests/doctests/test_GitRepository.py
new file mode 100644
index 00000000..bd7c005a
--- /dev/null
+++ b/tests/doctests/test_GitRepository.py
@@ -0,0 +1,999 @@
+# vim: set fileencoding=utf-8 :
+
+"""
+Test L{gbp.git.GitRepository}
+
+This testcase creates several repositores:
+
+ - A repository at I{dirs['repo']} called I{repo}
+ - A bare repository at I{dirs['bare']} called I{bare}
+ - A clone of I{repo} below I{dirs['clone']} called I{clone}
+ - A mirror of I{repo} below I{mirror_dirs['clone']} called I{mirror}
+"""
+
+from .. import context
+
+import gbp.log
+
+gbp.log.setup(color=False, verbose=True)
+
+dirs = {}
+subdirs = ['repo', 'bare', 'clone', 'mirror_clone']
+
+
+def setup_module():
+ tmpdir = context.new_tmpdir(__name__)
+ for s in subdirs:
+ dirs[s] = tmpdir.join(s)
+
+
+def teardown_module():
+ for s in subdirs:
+ del dirs[s]
+ context.teardown()
+
+
+def test_create():
+ """
+ Create a repository
+
+ Methods tested:
+ - L{gbp.git.GitRepository.create}
+
+ Properties tested:
+ - L{gbp.git.GitRepository.path}
+ - L{gbp.git.GitRepository.git_dir}
+
+ >>> import os, gbp.git
+ >>> repo = gbp.git.GitRepository.create(dirs['repo'])
+ >>> repo.path == dirs['repo']
+ True
+ >>> repo.git_dir == os.path.join(dirs['repo'], '.git')
+ True
+ >>> type(repo) == gbp.git.GitRepository
+ True
+ """
+
+
+def test_empty():
+ """
+ Empty repos have no branch
+
+ Methods tested:
+ - L{gbp.git.GitRepository.get_branch}
+ - L{gbp.git.GitRepository.is_empty}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.get_branch()
+ >>> repo.branch
+ >>> repo.is_empty()
+ True
+ """
+
+
+def test_add_files():
+ """
+ Add some dummy data
+
+ Methods tested:
+ - L{gbp.git.GitRepository.add_files}
+ - L{gbp.git.GitRepository.commit_all}
+ - L{gbp.git.GitRepository.is_clean}
+
+ Properties tested:
+ - L{gbp.git.GitRepository.head}
+
+ >>> import gbp.git, shutil, os
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> ret = shutil.copy(os.path.join(repo.path, ".git/HEAD"),
+ ... os.path.join(repo.path, "testfile"))
+ >>> repo.is_clean()[0]
+ False
+ >>> repo.is_clean(ignore_untracked=True)[0]
+ True
+ >>> repo.add_files(repo.path, force=True)
+ >>> repo.commit_all(msg="foo")
+ >>> repo.is_clean()[0]
+ True
+ >>> h = repo.head
+ >>> len(h)
+ 40
+ """
+
+
+def test_branch_master():
+ """
+ First branch is called I{master}
+
+ Methods tested:
+ - L{gbp.git.GitRepository.get_branch}
+ >>> import gbp.git, shutil
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.get_branch()
+ 'master'
+ >>> repo.branch
+ 'master'
+ """
+
+
+def test_clean():
+ """
+ Remove untracked files from the working tree
+
+ Methods tested:
+ - L{gbp.git.GitRepository.clean}
+
+ >>> import gbp.git, shutil, os
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> ret = shutil.copy(os.path.join(repo.path, ".git/HEAD"),
+ ... os.path.join(repo.path, "testclean"))
+ >>> repo.clean(dry_run=True)
+ >>> repo.is_clean()[0]
+ False
+ >>> repo.clean(directories=True, force=True)
+ >>> repo.is_clean()[0]
+ True
+ """
+
+
+def test_create_branch():
+ """
+ Create a branch name I{foo}
+
+ Methods tested:
+ - L{gbp.git.GitRepository.create_branch}
+ - L{gbp.git.GitRepository.branch_contains}
+
+ >>> import gbp.git, shutil
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.create_branch("foo")
+ >>> repo.branch_contains("foo", 'HEAD')
+ True
+ >>> repo.branch_contains("doesnotexist", 'HEAD', remote=True)
+ False
+ """
+
+
+def test_delete_branch():
+ """
+ Create a branch named I{foo2} and delete it
+
+ Methods tested:
+ - L{gbp.git.GitRepository.create_branch}
+ - L{gbp.git.GitRepository.delete_branch}
+
+ >>> import gbp.git, shutil
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.create_branch("bar")
+ >>> repo.delete_branch("bar")
+ >>> repo.delete_branch("master")
+ Traceback (most recent call last):
+ ...
+ GitRepositoryError: Can't delete the branch you're on
+ """
+
+
+def test_set_branch():
+ """
+ Switch to branch named I{foo}
+
+ Methods tested:
+ - L{gbp.git.GitRepository.set_branch}
+ - L{gbp.git.GitRepository.get_branch}
+ - L{gbp.git.GitRepository.branch}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.set_branch("foo")
+ >>> repo.get_branch() == "foo"
+ True
+ >>> repo.branch == "foo"
+ True
+ """
+
+
+def test_rename_branch():
+ """
+ Create branch named I{baz}, rename it to I{bax} and finally delete it
+
+ Methods tested:
+ - L{gbp.git.GitRepository.create_branch}
+ - L{gbp.git.GitRepository.rename_branch}
+ - L{gbp.git.GitRepository.delete_branch}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.create_branch("baz")
+ >>> repo.rename_branch("baz", "bax")
+ >>> repo.delete_branch("bax")
+ """
+
+
+def test_set_upstream_branch():
+ """
+ Set upstream branch master -> origin/master
+
+ >>> import os, shutil
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> os.makedirs(os.path.join(repo.git_dir, 'refs/remotes/origin'))
+ >>> ret = shutil.copy(os.path.join(repo.git_dir, 'refs/heads/master'), \
+ os.path.join(repo.git_dir, 'refs/remotes/origin/'))
+ >>> repo.add_remote_repo('origin', 'git://git.example.com/git/origin')
+ >>> repo.set_upstream_branch('master', 'origin/master')
+ >>> repo.get_upstream_branch('master')
+ 'origin/master'
+ >>> repo.set_upstream_branch('bla', 'origin/master')
+ Traceback (most recent call last):
+ GitRepositoryError: Branch bla doesn't exist!
+ >>> repo.set_upstream_branch('foo', 'origin/bla')
+ Traceback (most recent call last):
+ GitRepositoryError: Branch origin/bla doesn't exist!
+ """
+
+
+def test_get_upstream_branch():
+ """
+ Get info about upstream branches set in test_set_upstream_branch
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.get_upstream_branch('master')
+ 'origin/master'
+ >>> repo.get_upstream_branch('foo')
+ ''
+ >>> repo.get_upstream_branch('bla')
+ Traceback (most recent call last):
+ GitRepositoryError: Branch bla doesn't exist!
+ """
+
+
+def test_tag():
+ """
+ Create a tag named I{tag} and check its existance
+
+ Methods tested:
+ - L{gbp.git.GitRepository.create_tag}
+ - L{gbp.git.GitRepository.verify_tag}
+ - L{gbp.git.GitRepository.has_tag}
+ - L{gbp.git.GitRepository.get_tags}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.create_tag("tag")
+ >>> repo.has_tag("tag")
+ True
+ >>> repo.has_tag("unknown")
+ False
+ >>> repo.create_tag("tag2", msg="foo")
+ >>> repo.has_tag("tag2")
+ True
+ >>> repo.verify_tag("tag2")
+ False
+ >>> repo.get_tags()
+ ['tag', 'tag2']
+ >>> repo.tags
+ ['tag', 'tag2']
+ """
+
+
+def test_describe():
+ """
+ Describe commit-ish
+
+ Methods tested:
+ - L{gbp.git.GitRepository.describe}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> sha = repo.rev_parse('HEAD')
+ >>> repo.describe('HEAD')
+ 'tag2'
+ >>> repo.describe('HEAD', longfmt=True) == 'tag2-0-g%s' % sha[:7]
+ True
+ >>> repo.describe('HEAD', pattern='foo*')
+ Traceback (most recent call last):
+ ...
+ GitRepositoryError: Can't describe HEAD. Git error: fatal: No names found, cannot describe anything.
+ >>> repo.describe('HEAD', pattern='foo*', always=True) == sha[:7]
+ True
+ >>> repo.describe('HEAD', always=True, abbrev=16)
+ 'tag2'
+ >>> repo.describe('HEAD', pattern='foo*', always=True, abbrev=16) == sha[:16]
+ True
+ >>> tag = repo.describe('HEAD', longfmt=True, abbrev=16) == 'tag2-0-g%s' % sha[:16]
+ >>> repo.delete_tag('tag2')
+ >>> repo.describe('HEAD', tags=True)
+ 'tag'
+ >>> repo.describe('HEAD', tags=True, exact_match=True)
+ 'tag'
+ >>> repo.create_tag('tag2', msg='foo')
+ """
+
+
+def test_find_tag():
+ """
+ Find tags
+
+ Methods tested:
+ - L{gbp.git.GitRepository.find_tag}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.find_tag('HEAD')
+ 'tag2'
+ >>> repo.find_tag('HEAD', pattern='foo*')
+ Traceback (most recent call last):
+ ...
+ GitRepositoryError: Can't describe HEAD. Git error: fatal: No names found, cannot describe anything.
+ """
+
+
+def test_find_branch_tag():
+ """
+ Find the closest tags on a certain branch to a given commit
+
+ Methods tested:
+ - L{gbp.git.GitRepository.find_branch_tag}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.find_branch_tag('HEAD', 'master', 'tag*')
+ 'tag2'
+ >>> repo.find_branch_tag('HEAD', 'master', 'v*') # doctest:+ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ GitRepositoryError: Can't describe .... Git error: fatal: No names found, cannot describe anything.
+ """
+
+
+def test_move_tag():
+ """
+ Move a tag
+
+ Methods tested:
+ - L{gbp.git.GitRepository.move_tag}
+ - L{gbp.git.GitRepository.has_tag}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.move_tag("tag", "moved")
+ >>> repo.has_tag("tag")
+ False
+ >>> repo.has_tag("moved")
+ True
+ """
+
+
+def test_delete_tag():
+ """
+ Delete tags
+
+ Methods tested:
+ - L{gbp.git.GitRepository.delete_tag}
+ - L{gbp.git.GitRepository.has_tag}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.has_tag("moved")
+ True
+ >>> repo.delete_tag("moved")
+ >>> repo.has_tag("moved")
+ False
+ """
+
+
+def test_get_obj_type():
+ """
+ Find commit SHA1 related to tags
+
+ Methods tested:
+ - L{gbp.git.GitRepository.create_tag}
+ - L{gbp.git.GitRepository.get_obj_type}
+ - L{gbp.git.GitRepository.delete_tag}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.create_tag("tag3", "tag msg")
+ >>> repo.get_obj_type("tag3")
+ 'tag'
+ >>> repo.get_obj_type("HEAD")
+ 'commit'
+ >>> repo.get_obj_type("HEAD:testfile")
+ 'blob'
+ >>> repo.delete_tag("tag3")
+ """
+
+
+def test_list_files():
+ """
+ List files in the index
+
+ Methods tested:
+ - L{gbp.git.GitRepository.list_files}
+ - L{gbp.git.GitRepository.add_files}
+ - L{gbp.git.GitRepository.commit_staged}
+ - L{gbp.git.GitRepository.commit_files}
+ - L{gbp.git.GitRepository.force_head}
+
+ >>> import gbp.git, os, shutil
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> src = os.path.join(repo.path, ".git/HEAD")
+ >>> dst = os.path.join(repo.path, "testfile")
+ >>> repo.list_files()
+ ['testfile']
+ >>> repo.list_files(['modified'])
+ []
+ >>> repo.list_files(['modified', 'deleted'])
+ []
+ >>> repo.list_files(['modified', 'deleted', 'cached'])
+ ['testfile']
+ >>> ret = shutil.copy(src, dst)
+ >>> repo.list_files(['modified'])
+ ['testfile']
+ >>> repo.add_files(dst)
+ >>> repo.commit_staged(msg="foo")
+ >>> repo.list_files(['modified'])
+ []
+ >>> repo.list_files(['foo'])
+ Traceback (most recent call last):
+ ...
+ GitRepositoryError: Unknown type 'foo'
+ >>> repo.force_head('HEAD^', hard=True)
+ >>> repo.list_files(['modified'])
+ []
+ >>> ret = shutil.copy(src, dst)
+ >>> repo.list_files(['modified'])
+ ['testfile']
+ >>> repo.commit_files(dst, msg="foo")
+ >>> repo.list_files(['modified'])
+ []
+ """
+
+
+def test_get_commits():
+ """
+ Test listing commits
+
+ Methods tested:
+ - L{gbp.git.GitRepository.get_commits}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> commits = repo.get_commits()
+ >>> type(commits) == list and len(commits) == 2
+ True
+ >>> len(repo.get_commits(num=1)) == 1
+ True
+ >>> commits2 = repo.get_commits(since='HEAD~1')
+ >>> len(commits2) == 1
+ True
+ >>> commits2[0] == commits[0]
+ True
+ >>> commits2 = repo.get_commits(until='HEAD~1')
+ >>> len(commits2) == 1
+ True
+ >>> commits2[0] == commits[-1]
+ True
+ >>> repo.get_commits(paths=['foo', 'bar'])
+ []
+ >>> repo.get_commits(paths=['testfile']) == commits
+ True
+ """
+
+
+def test_get_commit_info():
+ """
+ Test inspecting commits
+
+ Methods tested:
+ - L{gbp.git.GitRepository.get_commit_info}
+
+ >>> import gbp.git
+ >>> from datetime import datetime
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> info = repo.get_commit_info('HEAD')
+ >>> info['id']
+ 'HEAD'
+ >>> info['body']
+ ''
+ >>> info['subject']
+ 'foo'
+ >>> '@' in info['author'].email
+ True
+ >>> '@' in info['committer'].email
+ True
+ >>> now = datetime.now()
+ >>> (now - datetime.fromtimestamp(int(info['author'].date.split()[0]))).seconds < 10
+ True
+ >>> (now - datetime.fromtimestamp(int(info['committer'].date.split()[0]))).seconds < 10
+ True
+ >>> info['patchname']
+ 'foo'
+ >>> info['files'] # doctest:+ELLIPSIS
+ defaultdict(<... 'list'>, {'M': ['testfile']})
+ >>> repo.get_subject('HEAD')
+ 'foo'
+ """
+
+
+def test_diff():
+ """
+ Test git-diff
+
+ Methods tested:
+ - L{gbp.git.GitRepository.diff}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> len(repo.diff('HEAD~1', 'HEAD')) > 3
+ True
+ >>> len(repo.diff('HEAD~1', 'HEAD', 'testfile')) > 3
+ True
+ >>> len(repo.diff('HEAD~1', 'HEAD', 'testfile', text=True)) > 3
+ True
+ >>> len(repo.diff('HEAD~1', 'HEAD', 'filenotexist')) == 0
+ True
+ >>> repo.diff('HEAD~1', 'HEAD') == repo.diff('HEAD~1')
+ True
+ """
+
+
+def test_diff_status():
+ """
+ Methods tested:
+ - L{gbp.git.GitRepository.diff_status}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.diff_status("HEAD", "HEAD") # doctest:+ELLIPSIS
+ defaultdict(<... 'list'>, {})
+ >>> repo.diff_status("HEAD~1", "HEAD") # doctest:+ELLIPSIS
+ defaultdict(<... 'list'>, {'M': ['testfile']})
+ """
+
+
+def test_mirror_clone():
+ """
+ Mirror a repository
+
+ Methods tested:
+ - L{gbp.git.GitRepository.clone}
+ - L{gbp.git.GitRepository.is_empty}
+ - L{gbp.git.GitRepository.set_branch}
+ - L{gbp.git.GitRepository.has_branch}
+ - L{gbp.git.GitRepository.branch}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.set_branch('master')
+ >>> mirror = gbp.git.GitRepository.clone(dirs['mirror_clone'], repo.path, mirror=True)
+ >>> mirror.is_empty()
+ False
+ >>> mirror.branch
+ 'master'
+ >>> mirror.has_branch('foo')
+ True
+ >>> mirror.has_branch('bar')
+ False
+ >>> mirror.set_branch('foo')
+ >>> mirror.branch
+ 'foo'
+ >>> mirror.force_head('foo^')
+ """
+
+
+def test_clone():
+ """
+ Clone a repository
+
+ Methods tested:
+ - L{gbp.git.GitRepository.clone}
+ - L{gbp.git.GitRepository.is_empty}
+ - L{gbp.git.GitRepository.set_branch}
+ - L{gbp.git.GitRepository.branch}
+ - L{gbp.git.GitRepository.get_merge_branch}
+ - L{gbp.git.GitRepository.get_remote_branches}
+ - L{gbp.git.GitRepository.get_local_branches}
+ - L{gbp.git.GitRepository.get_remote_repos}
+ - L{gbp.git.GitRepository.has_remote_repo}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.set_branch('master')
+ >>> clone = gbp.git.GitRepository.clone(dirs['clone'], repo.path)
+ >>> clone.is_empty()
+ False
+ >>> clone.branch
+ 'master'
+ >>> clone.get_remote_branches()
+ ['origin/HEAD', 'origin/foo', 'origin/master']
+ >>> clone.get_local_branches()
+ ['master']
+ >>> clone.get_merge_branch('master')
+ 'origin/master'
+ >>> clone.create_branch('foo', 'origin/foo')
+ >>> clone.get_merge_branch('foo')
+ 'origin/foo'
+ >>> clone.create_branch('bar')
+ >>> clone.get_merge_branch('bar') # None if no merge branch exists
+ >>> clone.get_local_branches()
+ ['bar', 'foo', 'master']
+ >>> clone.get_remote_repos()
+ ['origin']
+ >>> clone.has_remote_repo('origin')
+ True
+ >>> clone.has_branch('origin/master', remote=True)
+ True
+ >>> clone.has_remote_repo('godiug')
+ False
+ """
+
+
+def test_get_remotes():
+ """
+ Merge a branch
+
+ Methods tested:
+ - L{gbp.git.GitRepository.get_remotes}
+
+ >>> import os
+ >>> import gbp.git.repository
+ >>> repo = gbp.git.repository.GitRepository(os.path.join(dirs['clone'], 'repo'))
+ >>> remotes = repo.get_remotes()
+ >>> len(remotes)
+ 1
+ >>> origin = remotes['origin']
+ >>> origin.name
+ 'origin'
+ >>> origin.fetch_url == dirs['repo']
+ True
+ >>> origin.push_urls == [dirs['repo']]
+ True
+ """
+
+
+def test_merge():
+ """
+ Merge a branch
+
+ Methods tested:
+ - L{gbp.git.GitRepository.merge}
+ - L{gbp.git.GitRepository.set_branch}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.set_branch('master')
+ >>> repo.merge('foo')
+ """
+
+
+def test_pull():
+ """
+ Pull from a remote repository
+
+ Methods tested:
+ - L{gbp.git.GitRepository.set_branch}
+ - L{gbp.git.GitRepository.pull}
+
+ >>> import gbp.git, os
+ >>> d = os.path.join(dirs['clone'], 'repo')
+ >>> clone = gbp.git.GitRepository(d)
+ >>> clone.set_branch('master')
+ >>> clone.pull()
+ >>> clone.pull(all_remotes=True)
+ >>> clone.pull('origin', all_remotes=True)
+ """
+
+
+def test_fetch():
+ """
+ Fetch from a remote repository
+
+ Methods tested:
+ - L{gbp.git.GitRepository.fetch}
+ - L{gbp.git.GitRepository.push}
+ - L{gbp.git.GitRepository.push_tag}
+ - L{gbp.git.GitRepository.add_remote_repo}
+ - L{gbp.git.GitRepository.remove_remote_repo}
+
+ >>> import gbp.git, os
+ >>> d = os.path.join(dirs['clone'], 'repo')
+ >>> clone = gbp.git.GitRepository(d)
+ >>> clone.fetch()
+ >>> clone.push()
+ >>> clone.push('origin')
+ >>> clone.push('origin', 'master')
+ >>> clone.push('origin', 'master', force=True)
+ >>> clone.create_tag('tag3')
+ >>> clone.push_tag('origin', 'tag3')
+ >>> clone.create_tag('tag4')
+ >>> clone.push('origin', 'master', tags=True)
+ >>> clone.add_remote_repo('foo', dirs['repo'])
+ >>> clone.fetch('foo')
+ >>> clone.fetch('foo', tags=True)
+ >>> clone.fetch('foo', refspec='refs/heads/master')
+ >>> clone.fetch(all_remotes=True)
+ >>> clone.remove_remote_repo('foo')
+ """
+
+
+def test_create_bare():
+ """
+ Create a bare repository
+
+ Methods tested:
+ - L{gbp.git.GitRepository.create}
+ - L{gbp.git.GitRepository.is_empty}
+
+ >>> import gbp.git
+ >>> bare = gbp.git.GitRepository.create(dirs['bare'], bare=True, description="msg")
+ >>> bare.path == dirs['bare']
+ True
+ >>> bare.git_dir[:-1] == dirs['bare']
+ True
+ >>> type(bare) == gbp.git.GitRepository
+ True
+ >>> bare.is_empty()
+ True
+ >>> bare.is_clean()
+ (True, '')
+ """
+
+
+def test_nonexistent():
+ """
+ Check that accessing a non-existent repository fails.
+
+ Methods tested:
+ - L{gbp.git.GitRepository.__init__}
+
+ >>> import gbp.git
+ >>> bare = gbp.git.GitRepository("/does/not/exist")
+ Traceback (most recent call last):
+ ...
+ GitRepositoryError: No Git repository at '/does/not/exist'
+ """
+
+
+def test_create_noperm():
+ """
+ Check that creating a repository at a path that isn't writeable fails
+
+ Methods tested:
+ - L{gbp.git.GitRepository.create}
+
+ >>> import gbp.git
+ >>> gbp.git.GitRepository.create("/does/not/exist")
+ Traceback (most recent call last):
+ ...
+ GitRepositoryError: Cannot create Git repository at '/does/not/exist': Permission denied
+ """
+
+
+def test_checkout():
+ """
+ Checkout treeishs
+
+ Methods tested:
+ - L{gbp.git.GitRepository.checkout}
+ - L{gbp.git.GitRepository.get_branch}
+ - L{gbp.git.GitRepository.set_branch}
+ - L{gbp.git.GitRepository.rev_parse}
+
+ Properties tested:
+ - L{gbp.git.GitRepository.branch}
+ - L{gbp.git.GitRepository.tags}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.checkout('master')
+ >>> repo.branch
+ 'master'
+ >>> repo.rev_parse('doesnotexist')
+ Traceback (most recent call last):
+ ...
+ GitRepositoryError: revision 'doesnotexist' not found
+ >>> sha1 = repo.rev_parse('master', short=10)
+ >>> len(sha1)
+ 10
+ >>> sha1 = repo.rev_parse('master')
+ >>> len(sha1)
+ 40
+ >>> repo.checkout(sha1)
+ >>> repo.branch
+ >>> repo.get_branch()
+ Traceback (most recent call last):
+ ...
+ GitRepositoryError: Currently not on a branch
+ >>> tag = repo.tags[0]
+ >>> repo.checkout(tag)
+ >>> repo.branch
+ """
+
+
+def test_gc():
+ """
+ Test garbace collection
+
+ Methods tested:
+ - L{gbp.git.GitRepository.collect_garbage}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.collect_garbage()
+ """
+
+
+def test_grep_log():
+ """
+ Test grepping through commit messages
+
+ Methods tested:
+ - L{gbp.git.GitRepository.grep_log}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.set_branch('master')
+ >>> len(repo.grep_log('foo')) == 2
+ True
+ >>> len(repo.grep_log('foo', 'master')) == 2
+ True
+ >>> repo.grep_log('blafasel')
+ []
+ >>> repo.grep_log('foo', 'doesnotexist')
+ Traceback (most recent call last):
+ ...
+ GitRepositoryError: Error grepping log for foo: fatal: bad revision 'doesnotexist'
+ """
+
+
+def test_is_ff():
+ """
+ Test if branch is fast forwardable
+
+ Methods tested:
+ - L{gbp.git.GitRepository.is_fast_forward}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.is_fast_forward('master', 'foo')
+ (True, True)
+ >>> repo.create_branch('ff', 'HEAD^')
+ >>> repo.is_fast_forward('ff', 'master')
+ (True, False)
+ >>> repo.is_fast_forward('master', 'ff')
+ (False, True)
+ """
+
+
+def test_update_ref():
+ """
+ Test updating a reference
+
+ Methods tested:
+ - L{gbp.git.GitRepository.update_ref}
+
+ >>> import gbp.git, os
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.update_ref('new_ref', 'master', msg='update')
+ >>> os.path.exists(os.path.join(repo.git_dir, 'new_ref'))
+ True
+ """
+
+
+def test_make_tree():
+ """
+ Test git-mk-tree
+
+ Methods tested:
+ - L{gbp.git.GitRepository.write_file}
+ - L{gbp.git.GitRepository.list_tree}
+ - L{gbp.git.GitRepository.make_tree}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> sha1 = repo.write_file('testfile')
+ >>> sha1
+ '19af7398c894bc5e86e17259317e4db519e9241f'
+ >>> head = repo.list_tree('HEAD')
+ >>> head
+ [['100644', 'blob', '19af7398c894bc5e86e17259317e4db519e9241f', 'testfile']]
+ >>> head.append(['100644', 'blob', '19af7398c894bc5e86e17259317e4db519e9241f', 'testfile2'])
+ >>> newtree = repo.make_tree(head)
+ >>> newtree
+ '745951810c9e22fcc6de9b23f05efd6ab5512123'
+ >>> repo.list_tree(newtree, recurse=False, paths='testfile')
+ [['100644', 'blob', '19af7398c894bc5e86e17259317e4db519e9241f', 'testfile']]
+ """
+
+
+def test_update_submodules():
+ """
+ Updating submodules if we don't have any is a noop
+
+ Methods tested:
+ - L{gbp.git.GitRepository.has_submodules}
+ - L{gbp.git.GitRepository.update_submodules}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo.has_submodules()
+ False
+ >>> repo.update_submodules()
+ """
+
+
+def test_get_merge_base():
+ """
+ Find the common ancestor of two objects
+
+ Methods tested:
+ - L{gbp.git.GitRepository.get_merge_base}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> sha1 = repo.get_merge_base('master', 'foo')
+ >>> len(sha1)
+ 40
+ >>> repo.get_merge_base('master', 'doesnotexist')
+ Traceback (most recent call last):
+ ...
+ GitRepositoryError: Failed to get common ancestor: fatal: Not a valid object name doesnotexist
+ """
+
+
+def test_status():
+ r"""
+ Methods tested:
+ - L{gbp.git.GitRepository.status}
+
+ >>> import gbp.git, os, shutil
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> fname = os.path.join(repo.path, "test_status")
+ >>> ret = shutil.copy(os.path.join(repo.path, ".git/HEAD"), fname)
+ >>> list(repo.status().items())
+ [('??', ['test_status'])]
+ >>> list(repo.status(['bla*']).items())
+ []
+ >>> list(repo.status(['te*']).items())
+ [('??', ['test_status'])]
+ >>> repo.add_files(repo.path, force=True)
+ >>> repo.commit_all(msg='added %s' % fname)
+ >>> _ = repo._git_inout('mv', [fname, fname + 'new'])
+ >>> list(repo.status().items())
+ [('R ', ['test_status\x00test_statusnew'])]
+ """
+
+
+def test_cmd_has_feature():
+ r"""
+ Methods tested:
+ - L{gbp.git.GitRepository._cmd_has_feature}
+
+ >>> import gbp.git
+ >>> repo = gbp.git.GitRepository(dirs['repo'])
+ >>> repo._cmd_has_feature("commit", "a")
+ True
+ >>> repo._cmd_has_feature("commit", "reuse-message")
+ True
+ >>> repo._cmd_has_feature("merge", "n")
+ True
+ >>> repo._cmd_has_feature("merge", "stat")
+ True
+ >>> repo._cmd_has_feature("format-patch", "cc")
+ True
+ >>> repo._cmd_has_feature("merge", "foobaroption")
+ False
+ >>> repo._cmd_has_feature("foobarcmd", "foobaroption")
+ Traceback (most recent call last):
+ ...
+ GitRepositoryError: Invalid git command 'foobarcmd': No manual entry for gitfoobarcmd
+ >>> repo._cmd_has_feature("show", "standard-notes")
+ True
+ >>> repo._cmd_has_feature("show", "no-standard-notes")
+ True
+ """
+
+# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/tests/doctests/test_GitVfs.py b/tests/doctests/test_GitVfs.py
new file mode 100644
index 00000000..fb845e58
--- /dev/null
+++ b/tests/doctests/test_GitVfs.py
@@ -0,0 +1,56 @@
+# vim: set fileencoding=utf-8 :
+
+"""
+Test L{gbp.git.GitVfs}
+"""
+
+import gbp.log
+
+from .. import context # noqa: F401
+
+gbp.log.setup(color=False, verbose=True)
+
+
+def test_read():
+ """
+ Create a repository
+
+ Methods tested:
+ - L{gbp.git.GitVfs.open}
+ - L{gbp.git.GitVfs._File.readline}
+ - L{gbp.git.GitVfs._File.readlines}
+ - L{gbp.git.GitVfs._File.read}
+ - L{gbp.git.GitVfs._File.close}
+
+ >>> import os, gbp.git.vfs
+ >>> repo_dir = context.new_tmpdir(__name__)
+ >>> repo = gbp.git.GitRepository.create(str(repo_dir))
+ >>> f = open(os.path.join(repo.path, 'foo.txt'), 'w')
+ >>> content = 'al pha\\na\\nb\\nc'
+ >>> ret = f.write('al pha\\na\\nb\\nc')
+ >>> f.close()
+ >>> repo.add_files(repo.path, force=True)
+ >>> repo.commit_all(msg="foo")
+ >>> vfs = gbp.git.vfs.GitVfs(repo, 'HEAD')
+ >>> gf = vfs.open('foo.txt')
+ >>> gf.readline()
+ 'al pha\\n'
+ >>> gf.readline()
+ 'a\\n'
+ >>> gf.readlines()
+ ['b\\n', 'c']
+ >>> gf.readlines()
+ []
+ >>> gf.readline()
+ ''
+ >>> gf.readline()
+ ''
+ >>> gf.close()
+ >>> gbp.git.vfs.GitVfs(repo, 'HEAD').open('foo.txt').read() == content
+ True
+ >>> gf = vfs.open('doesnotexist')
+ Traceback (most recent call last):
+ ...
+ IOError: can't get HEAD:doesnotexist: fatal: Path 'doesnotexist' does not exist in 'HEAD'
+ >>> context.teardown()
+ """
diff --git a/tests/doctests/test_PristineTar.py b/tests/doctests/test_PristineTar.py
new file mode 100644
index 00000000..ab94ca1c
--- /dev/null
+++ b/tests/doctests/test_PristineTar.py
@@ -0,0 +1,158 @@
+# vim: set fileencoding=utf-8 :
+"""
+Test pristine-tar related methods in
+
+ - L{gbp.deb.DebianPristineTar}
+
+and
+
+ - L{gbp.deb.git.DebianGitRepository}
+
+This testcase creates this reposity:
+
+ - A repository at I{dirs['repo']} called I{repo}
+
+"""
+
+import os
+from .. import context
+
+
+test_data = os.path.join(context.projectdir, "tests/test_PristineTar_data")
+dirs = {}
+
+
+def setup_module():
+ dirs['repo'] = context.new_tmpdir(__name__).join('repo')
+
+
+def teardown_module():
+ del dirs['repo']
+ context.teardown()
+
+
+def test_create():
+ """
+ Create a repository
+
+ Methods tested:
+ - L{gbp.deb.git.DebianGitRepository.create}
+
+ >>> import os, gbp.deb.git
+ >>> repo = gbp.deb.git.DebianGitRepository.create(dirs['repo'])
+ """
+
+
+def test_empty_repo():
+ """
+ Empty repos have no branch pristine-tar branch
+
+ Methods tested:
+ - L{gbp.deb.git.DebianGitRepository.has_pristine_tar_branch}
+ - L{gbp.deb.pristinetar.DebianPristineTar.has_commit}
+
+ >>> import gbp.deb.git
+ >>> repo = gbp.deb.git.DebianGitRepository(dirs['repo'])
+ >>> repo.has_pristine_tar_branch()
+ False
+ >>> repo.pristine_tar.has_commit('upstream', '1.0', 'gzip')
+ False
+ """
+
+
+def test_commit_dir():
+ """
+ Empty repos have no branch pristine-tar branch
+
+ Methods tested:
+ - L{gbp.git.repository.GitRepository.commit_dir}
+ - L{gbp.git.repository.GitRepository.create_branch}
+
+ >>> import gbp.deb.git
+ >>> repo = gbp.deb.git.DebianGitRepository(dirs['repo'])
+ >>> commit = repo.commit_dir(test_data, msg="initial commit", branch=None)
+ >>> repo.create_branch('upstream')
+ """
+
+
+def test_create_tarball():
+ """
+ Create a tarball from a git tree
+
+ Methods tested:
+ - L{gbp.deb.git.DebianGitRepository.archive}
+
+ >>> import gbp.deb.git
+ >>> repo = gbp.deb.git.DebianGitRepository(dirs['repo'])
+ >>> repo.archive('tar', 'upstream/', '../upstream_1.0.orig.tar', 'upstream')
+ >>> gbp.command_wrappers.Command('gzip', [ '-n', '%s/../upstream_1.0.orig.tar' % dirs['repo']])()
+ """
+
+
+def test_pristine_tar_commit():
+ """
+ Commit the delta to the pristine-tar branch
+
+ Methods tested:
+ - L{gbp.deb.pristinetar.DebianPristineTar.commit}
+
+ >>> import gbp.deb.git
+ >>> repo = gbp.deb.git.DebianGitRepository(dirs['repo'])
+ >>> repo.pristine_tar.commit('../upstream_1.0.orig.tar.gz', 'upstream')
+ """
+
+
+def test_pristine_has_commit():
+ """
+ Find delta on the pristine tar branch
+
+ Methods tested:
+ - L{gbp.deb.pristinetar.DebianPristineTar.has_commit}
+ - L{gbp.pkg.pristinetar.PristineTar.get_commit}
+
+ >>> import gbp.deb.git
+ >>> repo = gbp.deb.git.DebianGitRepository(dirs['repo'])
+ >>> repo.pristine_tar.has_commit('upstream', '1.0', 'bzip2')
+ False
+ >>> repo.pristine_tar.has_commit('upstream', '1.0', 'gzip')
+ True
+ >>> repo.pristine_tar.has_commit('upstream', '1.0')
+ True
+ >>> branch = repo.rev_parse('pristine-tar')
+ >>> commit = repo.pristine_tar.get_commit('upstream_1.0.orig.tar.gz')
+ >>> branch == commit
+ True
+ """
+
+
+def test_pristine_tar_checkout():
+ """
+ Checkout a tarball using pristine-tar
+
+ Methods tested:
+ - L{gbp.deb.pristinetar.DebianPristineTar.checkout}
+
+ >>> import gbp.deb.git
+ >>> repo = gbp.deb.git.DebianGitRepository(dirs['repo'])
+ >>> repo.pristine_tar.checkout('upstream', '1.0', 'gzip', '..')
+ """
+
+
+def test_pristine_tar_checkout_nonexistent():
+ """
+ Checkout a tarball that does not exist using pristine-tar
+
+ Methods tested:
+ - L{gbp.deb.pristinetar.DebianPristineTar.checkout}
+
+ >>> import gbp.deb.git
+ >>> repo = gbp.deb.git.DebianGitRepository(dirs['repo'])
+ >>> repo.pristine_tar.checkout('upstream', '1.1', 'gzip', '..')
+ Traceback (most recent call last):
+ ...
+ CommandExecFailed: Pristine-tar couldn't checkout "upstream_1.1.orig.tar.gz": fatal: Path 'upstream_1.1.orig.tar.gz.delta' does not exist in 'refs/heads/pristine-tar'
+ pristine-tar: git show refs/heads/pristine-tar:upstream_1.1.orig.tar.gz.delta failed
+ """
+
+
+# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/tests/doctests/test_create_remote_repo.py b/tests/doctests/test_create_remote_repo.py
new file mode 100644
index 00000000..8188fb3c
--- /dev/null
+++ b/tests/doctests/test_create_remote_repo.py
@@ -0,0 +1,122 @@
+# vim: set fileencoding=utf-8 :
+
+from gbp.scripts.create_remote_repo import (build_remote_script, # noqa: F401
+ parse_url) # noqa: F401
+
+
+def test_build_remote_script():
+ """
+ >>> build_remote_script({'base': 'base', 'dir': 'dir', 'pkg': 'pkg', 'template-dir': None, 'bare': True}, 'branch')
+ '\\nset -e\\numask 002\\nif [ -d base"dir" ]; then\\n echo "Repository at "basedir" already exists - giving up."\\n exit 1\\nfi\\nmkdir -p base"dir"\\ncd base"dir"\\ngit init --shared --bare\\necho "pkg packaging" > ./description\\necho "ref: refs/heads/branch" > ./HEAD\\n'
+ """
+
+
+def test_build_remote_script_template_dir():
+ """
+ >>> build_remote_script({'base': 'base', 'dir': 'dir', 'pkg': 'pkg', 'template-dir': '/doesnot/exist', 'bare': True}, 'branch')
+ '\\nset -e\\numask 002\\nif [ -d base"dir" ]; then\\n echo "Repository at "basedir" already exists - giving up."\\n exit 1\\nfi\\nmkdir -p base"dir"\\ncd base"dir"\\ngit init --shared --bare --template=/doesnot/exist\\necho "pkg packaging" > ./description\\necho "ref: refs/heads/branch" > ./HEAD\\n'
+ """
+
+
+def test_build_remote_script_bare():
+ """
+ >>> build_remote_script({'base': 'base', 'dir': 'dir', 'pkg': 'pkg', 'template-dir': None, 'bare': False}, 'branch')
+ '\\nset -e\\numask 002\\nif [ -d base"dir" ]; then\\n echo "Repository at "basedir" already exists - giving up."\\n exit 1\\nfi\\nmkdir -p base"dir"\\ncd base"dir"\\ngit init --shared\\necho "pkg packaging" > .git/description\\necho "ref: refs/heads/branch" > .git/HEAD\\n'
+ """
+
+
+def test_parse_url():
+ """
+ >>> url = parse_url("ssh://host/path/%(pkg)s", "origin", "package")
+ >>> url['base']
+ ''
+ >>> url['dir']
+ '/path/package'
+ >>> url['host']
+ 'host'
+ >>> url['name']
+ 'origin'
+ >>> url['pkg']
+ 'package'
+ >>> url['port']
+ >>> url['scheme']
+ 'ssh'
+ >>> url['template-dir']
+ >>> url['url']
+ 'ssh://host/path/package'
+
+ >>> url = parse_url("ssh://host:22/path/to/repo.git", "origin", "package")
+ >>> url['base']
+ ''
+ >>> url['dir']
+ '/path/to/repo.git'
+ >>> url['host']
+ 'host'
+ >>> url['name']
+ 'origin'
+ >>> url['pkg']
+ 'package'
+ >>> url['port']
+ '22'
+ >>> url['scheme']
+ 'ssh'
+ >>> url['template-dir']
+ >>> url['url']
+ 'ssh://host:22/path/to/repo.git'
+
+ >>> url = parse_url("ssh://host:22/~/path/%(pkg)s.git", "origin", "package")
+ >>> url['dir']
+ 'path/package.git'
+ >>> url['host']
+ 'host'
+ >>> url['name']
+ 'origin'
+ >>> url['pkg']
+ 'package'
+ >>> url['port']
+ '22'
+ >>> url['scheme']
+ 'ssh'
+ >>> url['template-dir']
+ >>> url['url']
+ 'ssh://host:22/~/path/package.git'
+ >>> url['bare']
+ True
+
+ >>> url = parse_url("ssh://host:22/~user/path/%(pkg)s.git", "origin", "package", "/doesnot/exist", bare=False)
+ >>> url['dir']
+ 'path/package.git'
+ >>> url['host']
+ 'host'
+ >>> url['name']
+ 'origin'
+ >>> url['pkg']
+ 'package'
+ >>> url['port']
+ '22'
+ >>> url['scheme']
+ 'ssh'
+ >>> url['template-dir']
+ '/doesnot/exist'
+ >>> url['url']
+ 'ssh://host:22/~user/path/package.git'
+ >>> url['bare']
+ False
+
+ >>> parse_url("git://host/repo.git", "origin", "package")
+ Traceback (most recent call last):
+ ...
+ GbpError: URL must use ssh protocol.
+ >>> parse_url("ssh://host/path/repo", "origin", "package")
+ Traceback (most recent call last):
+ ...
+ GbpError: URL needs to contain either a repository name or '%(pkg)s'
+ >>> parse_url("ssh://host:asdf/path/%(pkg)s.git", "origin", "package")
+ Traceback (most recent call last):
+ ...
+ GbpError: URL contains invalid port.
+ >>> parse_url("ssh://host/~us er/path/%(pkg)s.git", "origin", "package")
+ Traceback (most recent call last):
+ ...
+ GbpError: URL contains invalid ~username expansion.
+ """