diff --git a/git_upstream/commands/import.py b/git_upstream/commands/import.py index e8de145..f1d4276 100644 --- a/git_upstream/commands/import.py +++ b/git_upstream/commands/import.py @@ -51,6 +51,12 @@ class ImportCommand(LogDedentMixin, GitUpstreamCommand): '-f', '--force', dest='force', required=False, action='store_true', default=False, help='Force overwrite of existing import branch if it exists.') + # finish options + self.parser.add_argument( + '--finish', dest='finish', required=False, action='store_true', + default=False, + help='Merge the specified import branch into the target') + # result behaviour options self.parser.add_argument( '--merge', dest='merge', required=False, action='store_true', default=True, @@ -59,6 +65,7 @@ class ImportCommand(LogDedentMixin, GitUpstreamCommand): self.parser.add_argument( '--no-merge', dest='merge', required=False, action='store_false', help='Disable merge of the resulting import branch') + # search/include options self.parser.add_argument( '--search-refs', action='append_replace', metavar='', default=['upstream/*'], dest='search_refs', @@ -77,6 +84,7 @@ class ImportCommand(LogDedentMixin, GitUpstreamCommand): self.parser.add_argument( '--import-branch', metavar='', default='import/{describe}', help='Name of import branch to use') + # data args self.parser.add_argument( 'upstream_branch', metavar='', nargs='?', default='upstream/master', @@ -87,6 +95,32 @@ class ImportCommand(LogDedentMixin, GitUpstreamCommand): help='Branches to additionally merge into the import branch using ' 'default git merging behaviour') + def validate(self, args): + """Perform more complex validation of args that cannot be mixed""" + + # check if --finish set with --no-merge + if args.finish and args.merge is False: + self.parser.error( + "--finish cannot be used with '--no-merge'") + + def _finish(self, args, import_upstream): + self.log.notice("Merging import to requested branch '%s'", args.branch) + if import_upstream.finish(): + self.log.notice( + """\ + Successfully finished import: + target branch: '%s' + upstream branch: '%s' + import branch: '%s'""", args.branch, args.upstream_branch, + import_upstream.import_branch) + if args.branches: + for branch in args.branches: + self.log.notice(" extra branch: '%s'", branch, + dedent=False) + return True + else: + return False + def run(self, args): import_upstream = ImportUpstream( @@ -133,6 +167,11 @@ class ImportCommand(LogDedentMixin, GitUpstreamCommand): """, "\n ".join(commit_list)) return True + # finish and return if thats all + if args.finish: + return self._finish(args, import_upstream) + + # otherwise perform fresh import self.log.notice("Starting import of upstream") import_upstream.create_import(force=args.force) self.log.notice("Successfully created import branch") @@ -149,22 +188,6 @@ class ImportCommand(LogDedentMixin, GitUpstreamCommand): """, args.branch) return True - self.log.notice("Merging import to requested branch '%s'", args.branch) - if import_upstream.finish(): - self.log.notice( - """\ - Successfully finished import: - target branch: '%s' - upstream branch: '%s' - import branch: '%s'""", args.branch, args.upstream_branch, - import_upstream.import_branch) - if args.branches: - for branch in args.branches: - self.log.notice(" extra branch: '%s'", branch, - dedent=False) - return True - else: - return False - + return self._finish(args, import_upstream) # vim:sw=4:sts=4:ts=4:et: diff --git a/git_upstream/tests/test_import_cmd.py b/git_upstream/tests/test_import_cmd.py index bb583c4..7c4a426 100644 --- a/git_upstream/tests/test_import_cmd.py +++ b/git_upstream/tests/test_import_cmd.py @@ -357,3 +357,71 @@ class TestImportCommand(BaseTestCase): "subject '%s' of commit '%s' does not match " "subject '%s' of node '%s'" % ( subject, commit.hexsha, node_subject, node)) + + def test_import_finish(self): + """Test the --finish option to the import command + + Given manual intervention to resolve conflicts and complete + the import, check that we can finish the import by manually + requesting the merge to be performed by this tool. + + Repository layout being checked (assumed already replayed) + + C---D local/master + / + / C1---D1 import/F + / / + A---B---E---F upstream/master + + + Test that result is as follows + + C---D------- G local/master + / / + / C1---D1 import/F + / / + A---B---E---F upstream/master + + """ + + tree = [ + ('A', []), + ('B', ['A']), + ('C', ['B']), + ('D', ['C']), + ('E', ['B']), + ('F', ['E']), + ('C1', ['F']), + ('D1', ['C1']) + ] + + branches = { + 'head': ('master', 'D'), + 'upstream': ('upstream/master', 'F'), + 'import': ('import/F', 'D1') + } + + self._build_git_tree(tree, branches.values()) + + self.git.tag(inspect.currentframe().f_code.co_name, 'upstream/master') + args = self.parser.parse_args(['-q', 'import', '--finish', + '--import-branch=import/F', + '--into=master', 'upstream/master']) + self.assertThat(args.cmd.run(args), Equals(True), + "import command failed to complete succesfully") + changes = list(Commit.iter_items( + self.repo, 'upstream/master..master^2')) + self.assertThat(len(changes), Equals(2), + "should only have seen two changes, got: %s" % + ", ".join(["%s:%s" % (commit.hexsha, + commit.message.splitlines()[0]) + for commit in changes])) + self.assertThat(self.repo.git.rev_parse('master^{tree}'), + Equals(self.repo.git.rev_parse('import/F^{tree}')), + "--finish option failed to merge correctly") + commit = self.git.rev_list('master', parents=True, max_count=1).split() + parents = commit[1:] + self.assertThat(parents, Equals([self._graph['D'].hexsha, + self._graph['D1'].hexsha]), + "import --finish merge does contain the correct " + "parents")