Files
git-upstream/git_upstream/tests/test_import_cmd.py
Darragh Bailey a4342f4474 Remove upstream branch requirement from '--finish'
The '--finish' option to the import command has no need of the upstream
branch, so allow it to be skipped by simply using the import branch name
as the upstream branch.

This still ensures the correct previous merge base will be found, but
since we have no need to scan the original upstream branch, can just use
the import branch named by the user instead and finish the merge.

Change-Id: I58ef4d05c52ecc684bebf5c9fecd6926871d3746
2016-01-21 22:20:27 +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 successfully")
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 successfully")
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 successfully")
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 successfully")
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 overridden 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 successfully")
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 overridden 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 successfully")
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': ('custom/master', 'F'),
'import': ('import/F', 'D1')
}
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', '--finish',
'--import-branch=import/F',
'--into=master'])
self.assertThat(args.cmd.run(args), Equals(True),
"import command failed to complete successfully")
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]))
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")