Files
git-upstream/git_upstream/tests/test_import_cmd.py
Darragh Bailey 2631be6cf8 Add option to perform finish only
To simplify finishing the import when manual intervention is required,
add a simple '--finish' option.

Change-Id: Ic9e5a38b90124213436ba650180a645144bc8ccc
2015-11-15 21:48:48 +00:00

428 lines
15 KiB
Python

# Copyright (c) 2012, 2013, 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Tests for the 'import' command"""
import inspect
from string import lower
import mock
from testtools.matchers import Equals
from git_upstream.lib.pygitcompat import Commit
from git_upstream import main
from git_upstream.tests.base import BaseTestCase
class SubstringMatcher(object):
def __init__(self, containing):
self.containing = lower(containing)
def __eq__(self, other):
return lower(other).find(self.containing) > -1
def __unicode__(self):
return 'a string containing "%s"' % self.containing
def __str__(self):
return unicode(self).encode('utf-8')
__repr__ = __unicode__
class TestImportCommand(BaseTestCase):
commands, parser = main.build_parsers()
def test_basic(self):
"""Test that default behaviour and options work
Repository layout being checked (assumed already replayed)
C---D local/master
/
A---B---E---F upstream/master
"""
tree = [
('A', []),
('B', ['A']),
('C', ['B']),
('D', ['C']),
('E', ['B']),
('F', ['E'])
]
branches = {
'head': ('master', 'D'),
'upstream': ('upstream/master', 'F')
}
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', 'upstream/master'])
self.assertThat(args.cmd.run(args), Equals(True),
"import command failed to complete succesfully")
def test_basic_additional(self):
"""Test that default behaviour and options work
Repository layout being checked (assumed already replayed)
C---D packaging/master
\
E---F local/master
/
A---B---G---H upstream/master
"""
tree = [
('A', []),
('B', ['A']),
('C', []),
('D', ['C']),
('E', ['B', 'D']),
('F', ['E']),
('G', ['B']),
('H', ['G'])
]
branches = {
'head': ('master', 'F'),
'upstream': ('upstream/master', 'H'),
'packaging': ('packaging/master', 'D')
}
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', 'upstream/master',
'packaging/master'])
self.assertThat(args.cmd.run(args), Equals(True),
"import command failed to complete succesfully")
def test_basic_additional_missed(self):
"""Test that forgetting an additional branch that was previously
included results in a warning to the user.
Repository layout being checked (assumed already replayed)
C---D packaging/master
\
E---F local/master
/
A---B---G---H upstream/master
"""
tree = [
('A', []),
('B', ['A']),
('C', []),
('D', ['C']),
('E', ['B', 'D']),
('F', ['E']),
('G', ['B']),
('H', ['G'])
]
branches = {
'head': ('master', 'F'),
'upstream': ('upstream/master', 'H'),
'packaging': ('packaging/master', 'D')
}
self._build_git_tree(tree, branches.values())
self.git.tag(inspect.currentframe().f_code.co_name, 'upstream/master')
args = self.parser.parse_args(['import', 'upstream/master'])
with mock.patch.object(args.cmd.log, 'warning') as mock_logger:
self.assertThat(args.cmd.run(args), Equals(True),
"import command failed to complete succesfully")
mock_logger.assert_called_with(
SubstringMatcher(
containing="Previous import merged additional"))
def test_import_switch_branches_search(self):
"""Test that the import sub-command can correctly switch branches when
importing from upstream when given a usable search-ref.
Repository layout being checked (assumed already replayed)
E---F local/master
/
C---D upstream/stable
/
A---B---G---H upstream/master
New branch to be tracked will be upstream/master, so the resulting
commits found should just be E & F.
Test that result is as follows
E---F---I local/master
/ /
C---D / upstream/stable
/ /
/ E1--F1
/ /
A---B---G---H upstream/master
"""
tree = [
('A', []),
('B', ['A']),
('C', ['B']),
('D', ['C']),
('E', ['D']),
('F', ['E']),
('G', ['B']),
('H', ['G'])
]
branches = {
'head': ('master', 'F'),
'upstream': ('upstream/master', 'H'),
'stable': ('upstream/stable', 'D')
}
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'])
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]))
for commit, node in zip(changes, ['F', 'E']):
subject = commit.message.splitlines()[0]
node_subject = self._graph[node].message.splitlines()[0]
self.assertThat(subject, Equals(node_subject),
"subject '%s' of commit '%s' does not match "
"subject '%s' of node '%s'" % (
subject, commit.hexsha, node_subject, node))
def test_import_switch_branches_fails_without_search_ref(self):
"""Test that the import sub-command finds additional changes when
not given a search-ref to look under.
Repository layout being checked (assumed already replayed)
E---F local/master
/
C---D upstream/stable
/
A---B---G---H upstream/master
New branch to be tracked will be upstream/master, so the resulting
commits found will be C, D, E & F because of not telling the searcher
to look under all of the namespace.
Test that result is as follows
E---F-------------I local/master
/ /
C---D / upstream/stable
/ /
/ C1---D1---E1--F1
/ /
A---B---G---H upstream/master
"""
tree = [
('A', []),
('B', ['A']),
('C', ['B']),
('D', ['C']),
('E', ['D']),
('F', ['E']),
('G', ['B']),
('H', ['G'])
]
# use 'custom/*' to ensure defaults are overriden correctly
branches = {
'head': ('master', 'F'),
'upstream': ('custom/master', 'H'),
'stable': ('custom/stable', 'D')
}
self._build_git_tree(tree, branches.values())
self.git.tag(inspect.currentframe().f_code.co_name, 'custom/master')
args = self.parser.parse_args(['-q', 'import',
'--into=master', 'custom/master'])
self.assertThat(args.cmd.run(args), Equals(True),
"import command failed to complete succesfully")
changes = list(Commit.iter_items(
self.repo, 'custom/master..master^2'))
local_rebased = ['F', 'E', 'D', 'C']
self.assertThat(len(changes), Equals(len(local_rebased)),
"should only have seen two changes, got: %s" %
", ".join(["%s:%s" % (commit.hexsha,
commit.message.splitlines()[0])
for commit in changes]))
for commit, node in zip(changes, local_rebased):
subject = commit.message.splitlines()[0]
node_subject = self._graph[node].message.splitlines()[0]
self.assertThat(subject, Equals(node_subject),
"subject '%s' of commit '%s' does not match "
"subject '%s' of node '%s'" % (
subject, commit.hexsha, node_subject, node))
def test_import_switch_branches_search_ref_custom_namespace(self):
"""Test that the import sub-command can correctly switch branches when
importing from upstream when given a usable search-ref.
Repository layout being checked (assumed already replayed)
E---F local/master
/
C---D upstream/stable
/
A---B---G---H upstream/master
New branch to be tracked will be upstream/master, so the resulting
commits found should just be E & F.
Test that result is as follows
E---F---I local/master
/ /
C---D / upstream/stable
/ /
/ E1--F1
/ /
A---B---G---H upstream/master
"""
tree = [
('A', []),
('B', ['A']),
('C', ['B']),
('D', ['C']),
('E', ['D']),
('F', ['E']),
('G', ['B']),
('H', ['G'])
]
# use 'custom/*' to ensure defaults are overriden correctly
branches = {
'head': ('master', 'F'),
'upstream': ('custom/master', 'H'),
'stable': ('custom/stable', 'D')
}
self._build_git_tree(tree, branches.values())
self.git.tag(inspect.currentframe().f_code.co_name, 'custom/master')
args = self.parser.parse_args(['-q', 'import',
'--search-refs=custom/*',
'--search-refs=custom-d/*',
'--into=master', 'custom/master'])
self.assertThat(args.cmd.run(args), Equals(True),
"import command failed to complete succesfully")
changes = list(Commit.iter_items(
self.repo, 'custom/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]))
for commit, node in zip(changes, ['F', 'E']):
subject = commit.message.splitlines()[0]
node_subject = self._graph[node].message.splitlines()[0]
self.assertThat(subject, Equals(node_subject),
"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")