From 9e5a5d978127b273a437c4d3426dc3a76bcd536a Mon Sep 17 00:00:00 2001 From: Ales Raszka Date: Apr 05 2016 06:22:55 +0000 Subject: push: check for missing patches Resolves: bz879634 Signed-off-by: Ales Raszka --- diff --git a/src/pyrpkg/__init__.py b/src/pyrpkg/__init__.py index 23d1866..3ffb558 100644 --- a/src/pyrpkg/__init__.py +++ b/src/pyrpkg/__init__.py @@ -29,6 +29,7 @@ import tempfile import fnmatch import urlparse import posixpath +import git # Try to import krb, it's OK if it fails try: import krbV @@ -1705,7 +1706,7 @@ class Commands(object): self._run_command(cmd, cwd=self.path) return - def push(self): + def push(self, force=False): """Push changes to the remote repository""" # see if our branch is tracking anything @@ -1713,6 +1714,24 @@ class Commands(object): self.load_branch_merge() except: self.log.warn('Current branch cannot be pushed anywhere!') + # check missing patches + ts = rpm.TransactionSet() + specfile = ts.parseSpec(self.spec) + missing_patches = [] + for source in specfile.sources: + if source[0].endswith('.patch'): + patch = source[0] + hdc = self.repo.head.commit.tree + try: + # check if patch is in the repository + hdc[patch] + except KeyError: + missing_patches.append(patch) + if missing_patches: + if not force: + raise rpkgError("%s contains untracked patches.\n%s\nConsider " + "to add them to repository or use --force " + "option" % (self.spec, missing_patches)) cmd = ['git', 'push'] if self.quiet: cmd.append('-q') diff --git a/src/pyrpkg/cli.py b/src/pyrpkg/cli.py index 37578d2..71b876d 100755 --- a/src/pyrpkg/cli.py +++ b/src/pyrpkg/cli.py @@ -681,6 +681,8 @@ defined, packages will be built sequentially.""" % {'name': self.name}) push_parser = self.subparsers.add_parser( 'push', help='Push changes to remote repository') + push_parser.add_argument('--force', '-f', help='Force push', + action='store_true') push_parser.set_defaults(command=self.push) def register_scratch_build(self): @@ -1219,7 +1221,7 @@ see API KEY section of copr-cli(1) man page. norebase=self.args.no_rebase) def push(self): - self.cmd.push() + self.cmd.push(self.args.force) def scratch_build(self): # A scratch build is just a build with --scratch diff --git a/src/rpkg.bash b/src/rpkg.bash index d89568e..0248d92 100644 --- a/src/rpkg.bash +++ b/src/rpkg.bash @@ -95,7 +95,7 @@ _rpkg() local after= after_more= case $command in - help|gimmespec|gitbuildhash|giturl|lint|new|push|unused-patches|verrel) + help|gimmespec|gitbuildhash|giturl|lint|new|unused-patches|verrel) ;; build) options="--nowait --background --skip-tag --scratch --md5" @@ -179,6 +179,9 @@ _rpkg() pull) options="--rebase --no-rebase" ;; + push) + options="--force" + ;; scratch-build) options="--nowait --background --md5" options_target="--target" diff --git a/test/commands/test_push.py b/test/commands/test_push.py new file mode 100644 index 0000000..5a076a9 --- /dev/null +++ b/test/commands/test_push.py @@ -0,0 +1,192 @@ +import os +import shutil +import tempfile + +import git +import subprocess + +from . import CommandTestCase + + +SPECFILE_TEMPLATE="""Name: test +Version: 1.0 +Release: 1.0 +Summary: test + +Group: Applications/System +License: GPLv2+ + +%s + +%%description +Test + +%%install +rm -f $RPM_BUILD_ROOT%%{_sysconfdir}/""" + +CLONE_CONFIG = ''' + bz.default-component %(module)s + sendemail.to %(module)s-owner@fedoraproject.org +''' +class CommandPushTestCase(CommandTestCase): + def test_push_without_patches(self): + self.make_new_git(self.module) + + import pyrpkg + cmd = pyrpkg.Commands(self.path, self.lookaside, + self.lookasidehash, + self.lookaside_cgi, self.gitbaseurl, + self.anongiturl, self.branchre, self.kojiconfig, + self.build_client, self.user, self.dist, + self.target, self.quiet) + cmd.clone_config = CLONE_CONFIG + cmd.clone(self.module, anon=True) + cmd.path = os.path.join(self.path, self.module) + os.chdir(os.path.join(self.path, self.module)) + + specfile_path = self.module + ".spec" + + # specfile with no patches + with open(specfile_path, 'w') as specfile: + specfile.write(SPECFILE_TEMPLATE % "") + specfile.close() + + try: + cmd.push() + except pyrpkg.rpkgError: + self.fail("No unpushed patches. This shouldn't raise exception") + + + def test_push_one_uncommited_patch(self): + self.make_new_git(self.module) + + import pyrpkg + cmd = pyrpkg.Commands(self.path, self.lookaside, + self.lookasidehash, + self.lookaside_cgi, self.gitbaseurl, + self.anongiturl, self.branchre, self.kojiconfig, + self.build_client, self.user, self.dist, + self.target, self.quiet) + cmd.clone_config = CLONE_CONFIG + cmd.clone(self.module, anon=True) + cmd.path = os.path.join(self.path, self.module) + os.chdir(os.path.join(self.path, self.module)) + + specfile_path = self.module + ".spec" + + # add uncommited patch + with open(specfile_path, 'w') as specfile: + specfile.write(SPECFILE_TEMPLATE % "Patch: test.patch") + specfile.close() + + with open("test.patch", 'w') as f: + f.close() + + def raises(): + cmd.push() + + self.assertRaises(pyrpkg.rpkgError, raises) + + def test_push_uncommited_patch_with_force_option(self): + self.make_new_git(self.module) + + import pyrpkg + cmd = pyrpkg.Commands(self.path, self.lookaside, + self.lookasidehash, + self.lookaside_cgi, self.gitbaseurl, + self.anongiturl, self.branchre, self.kojiconfig, + self.build_client, self.user, self.dist, + self.target, self.quiet) + cmd.clone_config = CLONE_CONFIG + cmd.clone(self.module, anon=True) + cmd.path = os.path.join(self.path, self.module) + os.chdir(os.path.join(self.path, self.module)) + + specfile_path = self.module + ".spec" + + with open(specfile_path, 'w') as specfile: + specfile.write(SPECFILE_TEMPLATE % "Patch: test.patch") + specfile.close() + + with open("test.patch", 'w') as f: + f.close() + + # Don't check uncommited patches + try: + cmd.push(force=True) + except pyrpkg.rpkgError: + self.fail("No unpushed patches. This shouldn't raise exception") + + def test_push_commited_patch(self): + self.make_new_git(self.module) + + import pyrpkg + cmd = pyrpkg.Commands(self.path, self.lookaside, + self.lookasidehash, + self.lookaside_cgi, self.gitbaseurl, + self.anongiturl, self.branchre, self.kojiconfig, + self.build_client, self.user, self.dist, + self.target, self.quiet) + cmd.clone_config = CLONE_CONFIG + cmd.clone(self.module, anon=True) + cmd.path = os.path.join(self.path, self.module) + os.chdir(os.path.join(self.path, self.module)) + + specfile_path = self.module + ".spec" + + # add patch and commit it + patch = "test.patch" + with open(specfile_path, 'w') as specfile: + specfile.write(SPECFILE_TEMPLATE % ("Patch: %s" % patch)) + specfile.close() + + with open("test.patch", 'w') as f: + f.close() + + cmd.repo.index.add([specfile_path, patch]) + cmd.repo.index.commit("add Patch") + + try: + cmd.push() + except pyrpkg.rpkgError: + self.fail("No unpushed patches. This shouldn't raise exception") + + def test_push_part_commited_patches(self): + self.make_new_git(self.module) + + import pyrpkg + cmd = pyrpkg.Commands(self.path, self.lookaside, + self.lookasidehash, + self.lookaside_cgi, self.gitbaseurl, + self.anongiturl, self.branchre, self.kojiconfig, + self.build_client, self.user, self.dist, + self.target, self.quiet) + cmd.clone_config = CLONE_CONFIG + cmd.clone(self.module, anon=True) + cmd.path = os.path.join(self.path, self.module) + os.chdir(os.path.join(self.path, self.module)) + + specfile_path = self.module + ".spec" + + # add two patches and commit only one + patch = "test.patch" + patch2 = "test2.patch" + + with open(specfile_path, 'w') as specfile: + specfile.write(SPECFILE_TEMPLATE % ("Patch: %s\nPatch1: %s" % + (patch, patch2))) + specfile.close() + + with open(patch, 'w') as f: + f.close() + with open(patch2, 'w') as f: + f.close() + + # add only one patch + cmd.repo.index.add([specfile_path, patch]) + cmd.repo.index.commit("add Patch") + + def raises(): + cmd.push() + + self.assertRaises(pyrpkg.rpkgError, raises)