diff options
author | Markus Lehtonen <markus.lehtonen@linux.intel.com> | 2012-01-12 15:37:49 +0200 |
---|---|---|
committer | Guido Günther <agx@sigxcpu.org> | 2014-07-24 23:33:36 +0200 |
commit | 736b9d889b5ff5d3a5abd6ec18564ff81696d8c4 (patch) | |
tree | e52136846adfaa4483e8230538e4e49bd9279d50 | |
parent | 00db052c6e2e1865a7981f5fbe48841a6185f9e2 (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-- | .gitmodules | 3 | ||||
-rw-r--r-- | gbp/config.py | 30 | ||||
-rwxr-xr-x | gbp/scripts/import_srpm.py | 461 | ||||
-rw-r--r-- | tests/01_test_help.py | 9 | ||||
-rw-r--r-- | tests/component/rpm/__init__.py | 30 | ||||
m--------- | tests/component/rpm/data | 0 | ||||
-rw-r--r-- | tests/component/rpm/test_import_srpm.py | 343 |
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\:·: |