aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarkus Lehtonen <markus.lehtonen@linux.intel.com>2012-01-12 15:37:49 +0200
committerGuido Günther <agx@sigxcpu.org>2014-07-24 23:33:36 +0200
commit736b9d889b5ff5d3a5abd6ec18564ff81696d8c4 (patch)
treee52136846adfaa4483e8230538e4e49bd9279d50
parent00db052c6e2e1865a7981f5fbe48841a6185f9e2 (diff)
Introduce git-import-srpm tool
Initial version of the git-import-srpm: a tool for importing source rpms. Signed-off-by: Markus Lehtonen <markus.lehtonen@linux.intel.com> Signed-off-by: Ed Bartosh <eduard.bartosh@intel.com>
-rw-r--r--.gitmodules3
-rw-r--r--gbp/config.py30
-rwxr-xr-xgbp/scripts/import_srpm.py461
-rw-r--r--tests/01_test_help.py9
-rw-r--r--tests/component/rpm/__init__.py30
m---------tests/component/rpm/data0
-rw-r--r--tests/component/rpm/test_import_srpm.py343
7 files changed, 876 insertions, 0 deletions
diff --git a/.gitmodules b/.gitmodules
index 98279cc0..3b52b91f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
[submodule "tests/component/deb/data"]
path = tests/component/deb/data
url = git://honk.sigxcpu.org/git/gbp/deb-testdata
+[submodule "tests/component/rpm/data"]
+ path = tests/component/rpm/data
+ url = git://github.com/marquiz/git-buildpackage-rpm-testdata.git
diff --git a/gbp/config.py b/gbp/config.py
index 3fa59186..02a6f06f 100644
--- a/gbp/config.py
+++ b/gbp/config.py
@@ -516,4 +516,34 @@ class GbpOptionParserDebian(GbpOptionParser):
'cleaner' : '/bin/true',
} )
+
+class GbpOptionParserRpm(GbpOptionParser):
+ """
+ Handles commandline options and parsing of config files for rpm tools
+ """
+ defaults = dict(GbpOptionParser.defaults)
+ defaults.update({
+ 'tmp-dir' : '/var/tmp/gbp/',
+ 'packaging-branch' : 'master',
+ 'packaging-dir' : '',
+ 'packaging-tag' : 'packaging/%(version)s',
+ })
+
+ help = dict(GbpOptionParser.help)
+ help.update({
+ 'tmp-dir':
+ "Base directory under which temporary directories are "
+ "created, default is '%(tmp-dir)s'",
+ 'packaging-branch':
+ "Branch the packaging is being maintained on, rpm counterpart "
+ "of the 'debian-branch' option, default is "
+ "'%(packaging-branch)s'",
+ 'packaging-dir':
+ "Subdir for RPM packaging files, default is "
+ "'%(packaging-dir)s'",
+ 'packaging-tag':
+ "Format string for packaging tags, RPM counterpart of the "
+ "'debian-tag' option, default is '%(packaging-tag)s'",
+ })
+
# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/gbp/scripts/import_srpm.py b/gbp/scripts/import_srpm.py
new file mode 100755
index 00000000..7fd5a4e7
--- /dev/null
+++ b/gbp/scripts/import_srpm.py
@@ -0,0 +1,461 @@
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2006,2007,2011 Guido Guenther <agx@sigxcpu.org>
+# (C) 2012 Intel Corporation <markus.lehtonen@linux.intel.com>
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""Import an RPM source package into a git repository"""
+
+import ConfigParser
+import sys
+import re
+import os
+import glob
+import time
+import shutil
+import errno
+import urllib2
+
+import gbp.tmpfile as tempfile
+import gbp.command_wrappers as gbpc
+from gbp.rpm import (parse_srpm, guess_spec, SpecFile, NoSpecError,
+ RpmUpstreamSource, compose_version_str)
+from gbp.rpm.git import (RpmGitRepository, GitRepositoryError)
+from gbp.git.modifier import GitModifier
+from gbp.config import (GbpOptionParserRpm, GbpOptionGroup,
+ no_upstream_branch_msg)
+from gbp.errors import GbpError
+import gbp.log
+from gbp.pkg import parse_archive_filename
+
+no_packaging_branch_msg = """
+Repository does not have branch '%s' for packaging/distribution sources.
+You need to reate it or use --packaging-branch to specify it.
+"""
+
+class SkipImport(Exception):
+ """Nothing imported"""
+ pass
+
+
+def download_file(target_dir, url):
+ """Download a remote file"""
+ gbp.log.info("Downloading '%s'..." % url)
+ try:
+ urlobj = urllib2.urlopen(url)
+ local_fn = os.path.join(target_dir, os.path.basename(url))
+ with open(local_fn, "wb") as local_file:
+ local_file.write(urlobj.read())
+ except urllib2.HTTPError as err:
+ raise GbpError("Download failed: %s" % err)
+ except urllib2.URLError as err:
+ raise GbpError("Download failed: %s" % err.reason)
+ return local_fn
+
+def download_source(pkg, dirs):
+ """Download package from a remote location"""
+ if re.match(r'[a-z]{1,5}://', pkg):
+ mode = 'python urllib2'
+ else:
+ mode = 'yumdownloader'
+
+ tmpdir = tempfile.mkdtemp(dir=dirs['tmp_base'], prefix='download_')
+ gbp.log.info("Trying to download '%s' using '%s'..." % (pkg, mode))
+ if mode == 'yumdownloader':
+ gbpc.RunAtCommand('yumdownloader',
+ ['--source', '--destdir=', '.', pkg],
+ shell=False)(dir=tmpdir)
+ else:
+ download_file(tmpdir, pkg)
+ srpm = glob.glob(os.path.join(tmpdir, '*.src.rpm'))[0]
+ return srpm
+
+
+def committer_from_author(author, options):
+ """Get committer info based on options"""
+ committer = GitModifier()
+ if options.author_is_committer:
+ committer.name = author.name
+ committer.email = author.email
+ return committer
+
+
+def move_tag_stamp(repo, tag_format, tag_str_fields):
+ "Move tag out of the way appending the current timestamp"
+ old = repo.version_to_tag(tag_format, tag_str_fields)
+ new = repo.version_to_tag('%s~%d' % (tag_format, int(time.time())),
+ tag_str_fields)
+ repo.move_tag(old, new)
+
+
+def set_bare_repo_options(options):
+ """Modify options for import into a bare repository"""
+ if options.pristine_tar:
+ gbp.log.info("Bare repository: setting %s option '--no-pristine-tar'")
+ options.pristine_tar = False
+
+
+def force_to_branch_head(repo, branch):
+ """Checkout branch and reset --hard"""
+ if repo.get_branch() == branch:
+ # Update HEAD if we modified the checked out branch
+ repo.force_head(branch, hard=True)
+ # Checkout packaging branch
+ repo.set_branch(branch)
+
+
+def parse_args(argv):
+ """Parse commandline arguments"""
+ try:
+ parser = GbpOptionParserRpm(command=os.path.basename(argv[0]),
+ prefix='',
+ usage='%prog [options] /path/to/package'
+ '.src.rpm')
+ except ConfigParser.ParsingError, err:
+ gbp.log.err(err)
+ return None, None
+
+ import_group = GbpOptionGroup(parser, "import options",
+ "pristine-tar and filtering")
+ tag_group = GbpOptionGroup(parser, "tag options",
+ "options related to git tag creation")
+ branch_group = GbpOptionGroup(parser, "version and branch naming options",
+ "version number and branch layout options")
+
+ for group in [import_group, branch_group, tag_group ]:
+ parser.add_option_group(group)
+
+ parser.add_option("-v", "--verbose", action="store_true", dest="verbose",
+ default=False, help="verbose command execution")
+ parser.add_config_file_option(option_name="color", dest="color",
+ type='tristate')
+ parser.add_config_file_option(option_name="color-scheme",
+ dest="color_scheme")
+ parser.add_config_file_option(option_name="tmp-dir", dest="tmp_dir")
+ parser.add_option("--download", action="store_true", dest="download",
+ default=False, help="download source package")
+ branch_group.add_config_file_option(option_name="packaging-branch",
+ dest="packaging_branch")
+ branch_group.add_config_file_option(option_name="upstream-branch",
+ dest="upstream_branch")
+ branch_group.add_boolean_config_file_option(
+ option_name="create-missing-branches",
+ dest="create_missing_branches")
+ branch_group.add_option("--orphan-packaging", action="store_true",
+ dest="orphan_packaging", default=False,
+ help="The packaging branch doesn't base on upstream")
+ branch_group.add_option("--native", action="store_true",
+ dest="native", default=False,
+ help="This is a dist native package, no separate "
+ "upstream branch")
+
+ tag_group.add_boolean_config_file_option(option_name="sign-tags",
+ dest="sign_tags")
+ tag_group.add_config_file_option(option_name="keyid",
+ dest="keyid")
+ tag_group.add_config_file_option(option_name="packaging-tag",
+ dest="packaging_tag")
+ tag_group.add_config_file_option(option_name="upstream-tag",
+ dest="upstream_tag")
+
+ import_group.add_config_file_option(option_name="filter",
+ dest="filters", action="append")
+ import_group.add_boolean_config_file_option(option_name="pristine-tar",
+ dest="pristine_tar")
+ import_group.add_option("--allow-same-version", action="store_true",
+ dest="allow_same_version", default=False,
+ help="allow to import already imported version")
+ import_group.add_boolean_config_file_option(
+ option_name="author-is-committer",
+ dest="author_is_committer")
+ import_group.add_config_file_option(option_name="packaging-dir",
+ dest="packaging_dir")
+ (options, args) = parser.parse_args(argv[1:])
+ gbp.log.setup(options.color, options.verbose, options.color_scheme)
+ return options, args
+
+
+def main(argv):
+ """Main function of the git-import-srpm script"""
+ dirs = dict(top=os.path.abspath(os.curdir))
+
+ ret = 0
+ skipped = False
+
+ options, args = parse_args(argv)
+
+ if len(args) != 1:
+ gbp.log.err("Need to give exactly one package to import. Try --help.")
+ return 1
+ try:
+ dirs['tmp_base'] = tempfile.mkdtemp(dir=options.tmp_dir,
+ prefix='import-srpm')
+ except GbpError as err:
+ gbp.log.err(err)
+ return 1
+ try:
+ srpm = args[0]
+ if options.download:
+ srpm = download_source(srpm, dirs)
+
+ # Real srpm, we need to unpack, first
+ true_srcrpm = False
+ if not os.path.isdir(srpm) and not srpm.endswith(".spec"):
+ src = parse_srpm(srpm)
+ true_srcrpm = True
+ dirs['pkgextract'] = tempfile.mkdtemp(dir=dirs['tmp_base'],
+ prefix='pkgextract_')
+ gbp.log.info("Extracting src rpm to '%s'" % dirs['pkgextract'])
+ src.unpack(dirs['pkgextract'])
+ preferred_spec = src.name + '.spec'
+ srpm = dirs['pkgextract']
+ elif os.path.isdir(srpm):
+ preferred_spec = os.path.basename(srpm.rstrip('/')) + '.spec'
+ else:
+ preferred_spec = None
+
+ # Find and parse spec file
+ if os.path.isdir(srpm):
+ gbp.log.debug("Trying to import an unpacked srpm from '%s'" % srpm)
+ dirs['src'] = os.path.abspath(srpm)
+ spec = guess_spec(srpm, True, preferred_spec)
+ else:
+ gbp.log.debug("Trying to import an srpm from '%s' with spec "\
+ "file '%s'" % (os.path.dirname(srpm), srpm))
+ dirs['src'] = os.path.abspath(os.path.dirname(srpm))
+ spec = SpecFile(srpm)
+
+ # Check the repository state
+ try:
+ repo = RpmGitRepository('.')
+ is_empty = repo.is_empty()
+
+ (clean, out) = repo.is_clean()
+ if not clean and not is_empty:
+ gbp.log.err("Repository has uncommitted changes, commit "
+ "these first: ")
+ raise GbpError, out
+
+ except GitRepositoryError:
+ gbp.log.info("No git repository found, creating one.")
+ is_empty = True
+ repo = RpmGitRepository.create(spec.name)
+ os.chdir(repo.path)
+
+ if repo.bare:
+ set_bare_repo_options(options)
+
+ # Create more tempdirs
+ dirs['origsrc'] = tempfile.mkdtemp(dir=dirs['tmp_base'],
+ prefix='origsrc_')
+ dirs['packaging_base'] = tempfile.mkdtemp(dir=dirs['tmp_base'],
+ prefix='packaging_')
+ dirs['packaging'] = os.path.join(dirs['packaging_base'],
+ options.packaging_dir)
+ try:
+ os.mkdir(dirs['packaging'])
+ except OSError as err:
+ if err.errno != errno.EEXIST:
+ raise
+
+ if true_srcrpm:
+ # For true src.rpm we just take everything
+ files = os.listdir(dirs['src'])
+ else:
+ # Need to copy files to the packaging directory given by caller
+ files = [os.path.basename(patch.path) \
+ for patch in spec.patchseries(unapplied=True, ignored=True)]
+ for filename in spec.sources().values():
+ files.append(os.path.basename(filename))
+ files.append(os.path.join(spec.specdir, spec.specfile))
+ # Don't copy orig source archive, though
+ if spec.orig_src and spec.orig_src['filename'] in files:
+ files.remove(spec.orig_src['filename'])
+
+ for fname in files:
+ fpath = os.path.join(dirs['src'], fname)
+ if os.path.exists(fpath):
+ shutil.copy2(fpath, dirs['packaging'])
+ else:
+ gbp.log.err("File '%s' listed in spec not found" % fname)
+ raise GbpError
+
+ # Unpack orig source archive
+ if spec.orig_src:
+ orig_tarball = os.path.join(dirs['src'], spec.orig_src['filename'])
+ sources = RpmUpstreamSource(orig_tarball)
+ sources.unpack(dirs['origsrc'], options.filters)
+ else:
+ sources = None
+
+ src_tag_format = options.packaging_tag if options.native \
+ else options.upstream_tag
+ tag_str_fields = spec.version
+ src_tag = repo.version_to_tag(src_tag_format, tag_str_fields)
+ ver_str = compose_version_str(spec.version)
+
+ if repo.find_version(options.packaging_tag, tag_str_fields):
+ gbp.log.warn("Version %s already imported." % ver_str)
+ if options.allow_same_version:
+ gbp.log.info("Moving tag of version '%s' since import forced" %
+ ver_str)
+ move_tag_stamp(repo, options.packaging_tag, tag_str_fields)
+ else:
+ raise SkipImport
+
+ if is_empty:
+ options.create_missing_branches = True
+
+ # Determine author and committer info, currently same info is used
+ # for both sources and packaging files
+ author = None
+ if spec.packager:
+ match = re.match(r'(?P<name>.*[^ ])\s*<(?P<email>\S*)>',
+ spec.packager.strip())
+ if match:
+ author = GitModifier(match.group('name'), match.group('email'))
+ if not author:
+ author = GitModifier()
+ gbp.log.debug("Couldn't determine packager info")
+ committer = committer_from_author(author, options)
+
+ # Import sources
+ if sources:
+ src_commit = repo.find_version(src_tag_format, tag_str_fields)
+ if not src_commit:
+ gbp.log.info("Tag %s not found, importing sources" % src_tag)
+
+ branch = [options.upstream_branch,
+ options.packaging_branch][options.native]
+ if not repo.has_branch(branch):
+ if options.create_missing_branches:
+ gbp.log.info("Will create missing branch '%s'" %
+ branch)
+ else:
+ gbp.log.err(no_upstream_branch_msg % branch + "\n"
+ "Also check the --create-missing-branches option.")
+ raise GbpError
+ src_vendor = "Native" if options.native else "Upstream"
+ msg = "%s version %s" % (src_vendor, spec.upstreamversion)
+ src_commit = repo.commit_dir(sources.unpacked,
+ "Imported %s" % msg,
+ branch,
+ author=author,
+ committer=committer,
+ create_missing_branch=options.create_missing_branches)
+ repo.create_tag(name=src_tag,
+ msg=msg,
+ commit=src_commit,
+ sign=options.sign_tags,
+ keyid=options.keyid)
+
+ if not options.native:
+ if options.pristine_tar:
+ archive_fmt = parse_archive_filename(orig_tarball)[1]
+ if archive_fmt == 'tar':
+ repo.pristine_tar.commit(orig_tarball,
+ 'refs/heads/%s' %
+ options.upstream_branch)
+ else:
+ gbp.log.warn('Ignoring pristine-tar, %s archives '
+ 'not supported' % archive_fmt)
+ else:
+ gbp.log.info("No orig source archive imported")
+
+ # Import packaging files. For native packages we assume that also
+ # packaging files are found in the source tarball
+ if not options.native or not sources:
+ gbp.log.info("Importing packaging files")
+ branch = options.packaging_branch
+ if not repo.has_branch(branch):
+ if options.create_missing_branches:
+ gbp.log.info("Will create missing branch '%s'" % branch)
+ else:
+ gbp.log.err(no_packaging_branch_msg % branch + "\n"
+ "Also check the --create-missing-branches "
+ "option.")
+ raise GbpError
+
+ tag = repo.version_to_tag(options.packaging_tag, tag_str_fields)
+ pkg_vendor = "Native" if options.native else "Downstrean"
+ msg = "%s release %s" % (pkg_vendor, ver_str)
+
+ if options.orphan_packaging or not sources:
+ commit = repo.commit_dir(dirs['packaging_base'],
+ "Imported %s" % msg,
+ branch,
+ author=author,
+ committer=committer,
+ create_missing_branch=options.create_missing_branches)
+ else:
+ # Copy packaging files to the unpacked sources dir
+ try:
+ pkgsubdir = os.path.join(sources.unpacked,
+ options.packaging_dir)
+ os.mkdir(pkgsubdir)
+ except OSError as err:
+ if err.errno != errno.EEXIST:
+ raise
+ for fname in os.listdir(dirs['packaging']):
+ shutil.copy2(os.path.join(dirs['packaging'], fname),
+ pkgsubdir)
+ commit = repo.commit_dir(sources.unpacked,
+ "Imported %s" % msg,
+ branch,
+ other_parents=[src_commit],
+ author=author,
+ committer=committer,
+ create_missing_branch=options.create_missing_branches)
+ # Import patches on top of the source tree
+ # (only for non-native packages with non-orphan packaging)
+ force_to_branch_head(repo, options.packaging_branch)
+
+ # Create packaging tag
+ repo.create_tag(name=tag,
+ msg=msg,
+ commit=commit,
+ sign=options.sign_tags,
+ keyid=options.keyid)
+
+ force_to_branch_head(repo, options.packaging_branch)
+
+ except KeyboardInterrupt:
+ ret = 1
+ gbp.log.err("Interrupted. Aborting.")
+ except gbpc.CommandExecFailed:
+ ret = 1
+ except GitRepositoryError as err:
+ gbp.log.err("Git command failed: %s" % err)
+ ret = 1
+ except GbpError as err:
+ if len(err.__str__()):
+ gbp.log.err(err)
+ ret = 1
+ except NoSpecError as err:
+ gbp.log.err("Failed determine spec file: %s" % err)
+ ret = 1
+ except SkipImport:
+ skipped = True
+ finally:
+ os.chdir(dirs['top'])
+ gbpc.RemoveTree(dirs['tmp_base'])()
+
+ if not ret and not skipped:
+ gbp.log.info("Version '%s' imported under '%s'" % (ver_str, spec.name))
+ return ret
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
+
+# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/tests/01_test_help.py b/tests/01_test_help.py
index 673d8708..331d7cc6 100644
--- a/tests/01_test_help.py
+++ b/tests/01_test_help.py
@@ -25,4 +25,13 @@ class TestHelp(unittest.TestCase):
m.main,
['doesnotmatter', '--help'])
+ """Test help output of RPM-specific commands"""
+ def testHelpRpm(self):
+ for script in ['import_srpm']:
+ module = 'gbp.scripts.%s' % script
+ m = __import__(module, globals(), locals(), ['main'], -1)
+ self.assertRaises(SystemExit,
+ m.main,
+ ['doesnotmatter', '--help'])
+
# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/tests/component/rpm/__init__.py b/tests/component/rpm/__init__.py
new file mode 100644
index 00000000..e84fca94
--- /dev/null
+++ b/tests/component/rpm/__init__.py
@@ -0,0 +1,30 @@
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2012 Intel Corporation <markus.lehtonen@linux.intel.com>
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""Test module for RPM command line tools of the git-buildpackage suite"""
+
+import os
+
+from tests.component import ComponentTestGitRepository
+
+RPM_TEST_DATA_SUBMODULE = os.path.join('tests', 'component', 'rpm', 'data')
+RPM_TEST_DATA_DIR = os.path.abspath(RPM_TEST_DATA_SUBMODULE)
+
+def setup():
+ """Test Module setup"""
+ ComponentTestGitRepository.check_testdata(RPM_TEST_DATA_SUBMODULE)
+
+# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/tests/component/rpm/data b/tests/component/rpm/data
new file mode 160000
+Subproject 90bf36d7981fdd1677cf7e734d9e1056a5fced1
diff --git a/tests/component/rpm/test_import_srpm.py b/tests/component/rpm/test_import_srpm.py
new file mode 100644
index 00000000..8c3f69e2
--- /dev/null
+++ b/tests/component/rpm/test_import_srpm.py
@@ -0,0 +1,343 @@
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2012 Intel Corporation <markus.lehtonen@linux.intel.com>
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""Basic tests for the git-import-srpm tool"""
+
+import os
+import shutil
+import urllib2
+from nose.plugins.skip import SkipTest
+from nose.tools import assert_raises, eq_, ok_ # pylint: disable=E0611
+from mock import Mock
+
+from gbp.scripts.import_srpm import main as import_srpm
+from gbp.git import GitRepository
+from gbp.rpm import SrcRpmFile
+
+from tests.component import ComponentTestBase
+from tests.component.rpm import RPM_TEST_DATA_DIR as DATA_DIR
+
+# Disable "Method could be a function warning"
+# pylint: disable=R0201
+
+def mock_import(args):
+ """Wrapper for import-srpm"""
+ # Call import-orig-rpm with added arg0
+ return import_srpm(['arg0'] + args)
+
+
+class TestImportPacked(ComponentTestBase):
+ """Test importing of src.rpm files"""
+
+ def test_invalid_args(self):
+ """See that import-srpm fails gracefully if called with invalid args"""
+ eq_(mock_import([]), 1)
+ with assert_raises(SystemExit):
+ mock_import(['--invalid-arg=123'])
+
+ def test_basic_import(self):
+ """Test importing of non-native src.rpm"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test-1.0-1.src.rpm')
+ eq_(mock_import([srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test')
+ files = {'Makefile', 'README', 'bar.tar.gz', 'dummy.sh', 'foo.txt',
+ 'gbp-test.spec', 'my.patch', 'my2.patch', 'my3.patch'}
+ self._check_repo_state(repo, 'master', ['master', 'upstream'], files)
+ # Two commits: upstream and packaging files
+ eq_(len(repo.get_commits()), 2)
+
+ def test_basic_import2(self):
+ """Import package with multiple spec files and full url patch"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test2-2.0-0.src.rpm')
+ eq_(mock_import([srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test2')
+ files = {'Makefile', 'README', 'bar.tar.gz', 'dummy.sh', 'foo.txt',
+ 'gbp-test2.spec', 'gbp-test2-alt.spec', 'my.patch',
+ 'my2.patch', 'my3.patch'}
+ self._check_repo_state(repo, 'master', ['master', 'upstream'], files)
+
+ # Two commits: upstream and packaging files
+ eq_(len(repo.get_commits()), 2)
+
+ def test_basic_import_orphan(self):
+ """
+ Test importing of non-native src.rpm to separate packaging and
+ development branches
+ """
+ srpm = os.path.join(DATA_DIR, 'gbp-test2-2.0-0.src.rpm')
+ eq_(mock_import(['--orphan-packaging', srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test2')
+ files = {'bar.tar.gz', 'foo.txt', 'gbp-test2.spec',
+ 'gbp-test2-alt.spec', 'my.patch', 'my2.patch', 'my3.patch'}
+ self._check_repo_state(repo, 'master', ['master', 'upstream'], files)
+ # Only one commit: the packaging files
+ eq_(len(repo.get_commits()), 1)
+
+ def test_basic_native_import(self):
+ """Test importing of native src.rpm"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test-native-1.0-1.src.rpm')
+ eq_(mock_import(['--native', srpm]), 0)
+ # Check repository state
+ files = {'.gbp.conf', 'Makefile', 'README', 'dummy.sh', 'packaging/',
+ 'packaging/gbp-test-native.spec'}
+ repo = GitRepository('gbp-test-native')
+ self._check_repo_state(repo, 'master', ['master'], files)
+ # Only one commit: the imported source tarball
+ eq_(len(repo.get_commits()), 1)
+
+ def test_import_no_orig_src(self):
+ """Test importing of (native) srpm without orig tarball"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test-native2-2.0-0.src.rpm')
+ eq_(mock_import([srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test-native2')
+ self._check_repo_state(repo, 'master', ['master'])
+ # Only one commit: packaging files
+ eq_(len(repo.get_commits()), 1)
+
+ def test_multiple_versions(self):
+ """Test importing of multiple versions"""
+ srpms = [ os.path.join(DATA_DIR, 'gbp-test-1.0-1.src.rpm'),
+ os.path.join(DATA_DIR, 'gbp-test-1.0-1.other.src.rpm'),
+ os.path.join(DATA_DIR, 'gbp-test-1.1-1.src.rpm') ]
+ eq_(mock_import([srpms[0]]), 0)
+ repo = GitRepository('gbp-test')
+ self._check_repo_state(repo, 'master', ['master', 'upstream'])
+ eq_(len(repo.get_commits()), 2)
+ # Try to import same version again
+ eq_(mock_import([srpms[1]]), 0)
+ eq_(len(repo.get_commits()), 2)
+ eq_(len(repo.get_commits(until='upstream')), 1)
+ eq_(mock_import(['--allow-same-version', srpms[1]]), 0)
+ # Added new version of packaging
+ eq_(len(repo.get_commits()), 3)
+ eq_(len(repo.get_commits(until='upstream')), 1)
+ # Import new version
+ eq_(mock_import([srpms[2]]), 0)
+ files = {'Makefile', 'README', 'bar.tar.gz', 'dummy.sh', 'foo.txt',
+ 'gbp-test.spec', 'my.patch', 'my2.patch', 'my3.patch'}
+ self._check_repo_state(repo, 'master', ['master', 'upstream'], files)
+ eq_(len(repo.get_commits()), 5)
+ eq_(len(repo.get_commits(until='upstream')), 2)
+ # Check number of tags
+ eq_(len(repo.get_tags('upstream/*')), 2)
+ eq_(len(repo.get_tags('packaging/*')), 3)
+
+ def test_import_to_existing(self):
+ """Test importing to an existing repo"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test-1.0-1.src.rpm')
+
+ # Create new repo
+ repo = GitRepository.create('myrepo')
+ os.chdir('myrepo')
+ shutil.copy2('.git/HEAD', 'foobar')
+ repo.add_files('.')
+ repo.commit_all('First commit')
+
+ # Test importing to non-clean repo
+ shutil.copy2('.git/HEAD', 'foobaz')
+ eq_(mock_import(['--create-missing', srpm]), 1)
+ self._check_log(0, 'gbp:error: Repository has uncommitted changes')
+ self._clear_log()
+ os.unlink('foobaz')
+
+ # The first import should fail because upstream branch is missing
+ eq_(mock_import([srpm]), 1)
+ self._check_log(-1, 'Also check the --create-missing-branches')
+ eq_(mock_import(['--create-missing', srpm]), 0)
+ self._check_repo_state(repo, 'master', ['master', 'upstream'])
+ # Four commits: our initial, upstream and packaging files
+ eq_(len(repo.get_commits()), 3)
+
+ # The import should fail because missing packaging-branch
+ srpm = os.path.join(DATA_DIR, 'gbp-test-1.1-1.src.rpm')
+ eq_(mock_import(['--packaging-branch=foo', srpm]), 1)
+ self._check_log(-1, 'Also check the --create-missing-branches')
+
+
+ def test_filter(self):
+ """Test filter option"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test-1.0-1.src.rpm')
+ eq_(mock_import(['--filter=README', '--filter=mydir', srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test')
+ files = set(['Makefile', 'dummy.sh', 'bar.tar.gz', 'foo.txt',
+ 'gbp-test.spec', 'my.patch', 'my2.patch', 'my3.patch'])
+ self._check_repo_state(repo, 'master', ['master', 'upstream'], files)
+
+ def test_misc_options(self):
+ """Test various options of git-import-srpm"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test2-2.0-0.src.rpm')
+
+ eq_(mock_import([
+ '--packaging-branch=pack',
+ '--upstream-branch=orig',
+ '--packaging-dir=packaging',
+ '--packaging-tag=ver_%(upstreamversion)s-rel_%(release)s',
+ '--upstream-tag=orig/%(upstreamversion)s',
+ '--author-is-committer',
+ srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test2')
+ files = {'Makefile', 'README', 'dummy.sh', 'packaging/',
+ 'packaging/bar.tar.gz', 'packaging/foo.txt',
+ 'packaging/gbp-test2.spec', 'packaging/gbp-test2-alt.spec',
+ 'packaging/my.patch', 'packaging/my2.patch',
+ 'packaging/my3.patch'}
+ self._check_repo_state(repo, 'pack', ['pack', 'orig'], files)
+ eq_(len(repo.get_commits()), 2)
+ # Check packaging dir
+ eq_(len(repo.get_commits(paths='packaging')), 1)
+ # Check tags
+ tags = repo.get_tags()
+ eq_(set(tags), set(['orig/2.0', 'ver_2.0-rel_0']))
+ # Check git committer/author
+ info = repo.get_commit_info('pack')
+ eq_(info['author'].name, 'Markus Lehtonen')
+ eq_(info['author'].email, 'markus.lehtonen@linux.intel.com')
+ eq_(info['author'].name, info['committer'].name)
+ eq_(info['author'].email, info['committer'].email)
+
+
+class TestImportUnPacked(ComponentTestBase):
+ """Test importing of unpacked source rpms"""
+
+ def setup(self):
+ super(TestImportUnPacked, self).setup()
+ # Unpack some source rpms
+ os.mkdir('multi-unpack')
+ for pkg in ['gbp-test-1.0-1.src.rpm', 'gbp-test2-2.0-0.src.rpm']:
+ unpack_dir = pkg.replace('.src.rpm', '-unpack')
+ os.mkdir(unpack_dir)
+ pkg_path = os.path.join(DATA_DIR, pkg)
+ SrcRpmFile(pkg_path).unpack(unpack_dir)
+ SrcRpmFile(pkg_path).unpack('multi-unpack')
+
+ def test_import_dir(self):
+ """Test importing of directories"""
+ eq_(mock_import(['gbp-test-1.0-1-unpack']), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test')
+ self._check_repo_state(repo, 'master', ['master', 'upstream'])
+
+ # Check that importing dir with multiple spec files fails
+ eq_(mock_import(['multi-unpack']), 1)
+ self._check_log(-1, 'gbp:error: Failed determine spec file: '
+ 'Multiple spec files found')
+
+ def test_import_spec(self):
+ """Test importing of spec file"""
+ specfile = 'gbp-test2-2.0-0-unpack/gbp-test2.spec'
+ eq_(mock_import([specfile]), 0)
+ # Check repository state
+ ok_(GitRepository('gbp-test2').is_clean())
+
+ def test_missing_files(self):
+ """Test importing of directory with missing packaging files"""
+ specfile = 'gbp-test2-2.0-0-unpack/gbp-test2.spec'
+ os.unlink('gbp-test2-2.0-0-unpack/my.patch')
+ eq_(mock_import([specfile]), 1)
+ self._check_log(-1, "gbp:error: File 'my.patch' listed in spec "
+ "not found")
+
+
+class TestDownloadImport(ComponentTestBase):
+ """Test download functionality"""
+
+ def test_urldownload(self):
+ """Test downloading and importing src.rpm from remote url"""
+ srpm = 'http://raw.github.com/marquiz/git-buildpackage-rpm-testdata/'\
+ 'master/gbp-test-1.0-1.src.rpm'
+ # Mock to use local files instead of really downloading
+ local_fn = os.path.join(DATA_DIR, os.path.basename(srpm))
+ urllib2.urlopen = Mock()
+ urllib2.urlopen.return_value = open(local_fn, 'r')
+
+ eq_(mock_import(['--download', srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test')
+ self._check_repo_state(repo, 'master', ['master', 'upstream'])
+
+ def test_nonexistent_url(self):
+ """Test graceful failure when trying download from nonexistent url"""
+ srpm = 'http://url.does.not.exist.com/foo.src.rpm'
+ # Do not connect to remote, mock failure
+ urllib2.urlopen = Mock()
+ urllib2.urlopen.side_effect = urllib2.HTTPError(srpm, 404, "Not found",
+ None, None)
+
+ eq_(mock_import(['--download', srpm]), 1)
+ self._check_log(-1, "gbp:error: Download failed: HTTP Error 404")
+ self._clear_log()
+
+ def test_invalid_url(self):
+ """Test graceful failure when trying download from invalid url"""
+ srpm = 'foob://url.does.not.exist.com/foo.src.rpm'
+ eq_(mock_import(['--download', srpm]), 1)
+ self._check_log(-1, "gbp:error: Download failed: unknown url type:")
+ self._clear_log()
+
+
+class TestPristineTar(ComponentTestBase):
+ """Test importing with pristine-tar"""
+
+ @classmethod
+ def setup_class(cls):
+ if not os.path.exists('/usr/bin/pristine-tar'):
+ raise SkipTest('Skipping %s:%s as pristine-tar tool is not '
+ 'available' % (__name__, cls.__name__))
+ super(TestPristineTar, cls).setup_class()
+
+ def test_basic_import_pristine_tar(self):
+ """Test importing of non-native src.rpm, with pristine-tar"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test-1.0-1.src.rpm')
+ eq_(mock_import(['--pristine-tar', srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test')
+ self._check_repo_state(repo, 'master', ['master', 'upstream',
+ 'pristine-tar'])
+ # Two commits: upstream and packaging files
+ eq_(len(repo.get_commits()), 2)
+
+ def test_unsupported_archive(self):
+ """Test importing of src.rpm with a zip source archive"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test-native-1.0-1.src.rpm')
+ eq_(mock_import(['--pristine-tar', srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test-native')
+ self._check_repo_state(repo, 'master', ['master', 'upstream'])
+ # Check that a warning is printed
+ self._check_log(-1, "gbp:warning: Ignoring pristine-tar")
+
+
+class TestBareRepo(ComponentTestBase):
+ """Test importing to a bare repository"""
+
+ def test_basic_import_to_bare_repo(self):
+ """Test importing of srpm to a bare git repository"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test-1.0-1.src.rpm')
+ # Create new repo
+ repo = GitRepository.create('myrepo', bare=True)
+ os.chdir('myrepo')
+ eq_(mock_import([srpm]), 0)
+ self._check_repo_state(repo, 'master', ['master', 'upstream'])
+ # Patch import to bare repos not supported -> only 2 commits
+ eq_(len(repo.get_commits(until='master')), 2)
+
+# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: