Ejemplo n.º 1
0
class MercurialClientTests(MercurialTestBase):
    """Unit tests for MercurialClient."""

    TESTSERVER = 'http://127.0.0.1:8080'
    CLONE_HGRC = dedent("""
    [ui]
    username = test user <user at example.com>

    [paths]
    default = %(hg_dir)s
    cloned = %(clone_dir)s

    [reviewboard]
    url = %(test_server)s

    [diff]
    git = true
    """).rstrip()

    def setUp(self):
        super(MercurialClientTests, self).setUp()
        if not is_exe_in_path('hg'):
            raise SkipTest('hg not found in path')

        self.hg_dir = os.path.join(self.testdata_dir, 'hg-repo')
        self.clone_dir = self.chdir_tmp()

        self._run_hg(['clone', self.hg_dir, self.clone_dir])
        self.client = MercurialClient(options=self.options)

        clone_hgrc = open(self.clone_hgrc_path, 'w')
        clone_hgrc.write(
            self.CLONE_HGRC % {
                'hg_dir': self.hg_dir,
                'clone_dir': self.clone_dir,
                'test_server': self.TESTSERVER,
            })
        clone_hgrc.close()

        self.options.parent_branch = None

    def _hg_get_tip(self):
        return self._run_hg(['identify']).split()[0]

    @property
    def clone_hgrc_path(self):
        return os.path.join(self.clone_dir, '.hg', 'hgrc')

    def test_get_repository_info_simple(self):
        """Testing MercurialClient get_repository_info, simple case"""
        ri = self.client.get_repository_info()

        self.assertTrue(isinstance(ri, RepositoryInfo))
        self.assertEqual('', ri.base_path)

        hgpath = ri.path

        if os.path.basename(hgpath) == '.hg':
            hgpath = os.path.dirname(hgpath)

        self.assertEqual(self.hg_dir, hgpath)
        self.assertTrue(ri.supports_parent_diffs)
        self.assertFalse(ri.supports_changesets)

    def test_scan_for_server_simple(self):
        """Testing MercurialClient scan_for_server, simple case"""
        os.rename(self.clone_hgrc_path,
                  os.path.join(self.clone_dir, '._disabled_hgrc'))

        self.client.hgrc = {}
        self.client._load_hgrc()
        ri = self.client.get_repository_info()

        server = self.client.scan_for_server(ri)
        self.assertTrue(server is None)

    def test_scan_for_server_when_present_in_hgrc(self):
        """Testing MercurialClient scan_for_server when present in hgrc"""
        ri = self.client.get_repository_info()

        server = self.client.scan_for_server(ri)
        self.assertEqual(self.TESTSERVER, server)

    def test_scan_for_server_reviewboardrc(self):
        """Testing MercurialClient scan_for_server when in .reviewboardrc"""
        rc = open(os.path.join(self.clone_dir, '.reviewboardrc'), 'w')
        rc.write('REVIEWBOARD_URL = "%s"' % self.TESTSERVER)
        rc.close()
        self.client.config = load_config()

        ri = self.client.get_repository_info()
        server = self.client.scan_for_server(ri)
        self.assertEqual(self.TESTSERVER, server)

    def test_diff_simple(self):
        """Testing MercurialClient diff, simple case"""
        self._hg_add_file_commit('foo.txt', FOO1, 'delete and modify stuff')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '68c2bdccf52a4f0baddd0ac9f2ecb7d2')

    def test_diff_simple_multiple(self):
        """Testing MercurialClient diff with multiple commits"""
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        self._hg_add_file_commit('foo.txt', FOO3, 'commit 3')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '9c8796936646be5c7349973b0fceacbd')

    def test_diff_exclude(self):
        """Testing MercurialClient diff with file exclusion"""
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._hg_add_file_commit('exclude.txt', FOO2, 'commit 2')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions, exclude_patterns=['exclude.txt'])
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '68c2bdccf52a4f0baddd0ac9f2ecb7d2')

    def test_diff_exclude_empty(self):
        """Testing MercurialClient diff with empty file exclusion"""
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._hg_add_file_commit('empty.txt', b'', 'commit 2')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions, exclude_patterns=['empty.txt'])
        self.assertTrue(isinstance(revisions, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '68c2bdccf52a4f0baddd0ac9f2ecb7d2')

    def test_diff_branch_diverge(self):
        """Testing MercurialClient diff with diverged branch"""
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')

        self._run_hg(['branch', 'diverged'])
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '6b12723baab97f346aa938005bc4da4d')

        self._run_hg(['update', '-C', 'default'])

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '68c2bdccf52a4f0baddd0ac9f2ecb7d2')

    def test_diff_parent_diff_simple(self):
        """Testing MercurialClient parent diffs with a simple case"""
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        self._hg_add_file_commit('foo.txt', FOO3, 'commit 3')

        revisions = self.client.parse_revision_spec(['2', '3'])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('parent_diff' in result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '7a897f68a9dc034fc1e42fe7a33bb808')
        self.assertEqual(
            md5(result['parent_diff']).hexdigest(),
            '5cacbd79800a9145f982dcc0908b6068')

    def test_diff_parent_diff_branch_diverge(self):
        """Testing MercurialClient parent diffs with a diverged branch"""

        # This test is very similar to test_diff_parent_diff_simple except
        # we throw a branch into the mix.
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._run_hg(['branch', 'diverged'])
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        self._hg_add_file_commit('foo.txt', FOO3, 'commit 3')

        revisions = self.client.parse_revision_spec(['2', '3'])
        result = self.client.diff(revisions)
        self.assertTrue('parent_diff' in result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '7a897f68a9dc034fc1e42fe7a33bb808')
        self.assertEqual(
            md5(result['parent_diff']).hexdigest(),
            '5cacbd79800a9145f982dcc0908b6068')

    def test_diff_parent_diff_simple_with_arg(self):
        """Testing MercurialClient parent diffs with a diverged branch and
        --parent option"""
        # This test is very similar to test_diff_parent_diff_simple except
        # we use the --parent option to post without explicit revisions
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        self._hg_add_file_commit('foo.txt', FOO3, 'commit 3')

        self.options.parent_branch = '2'

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('parent_diff' in result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '7a897f68a9dc034fc1e42fe7a33bb808')
        self.assertEqual(
            md5(result['parent_diff']).hexdigest(),
            '5cacbd79800a9145f982dcc0908b6068')

    def test_parse_revision_spec_no_args(self):
        """Testing MercurialClient.parse_revision_spec with no arguments"""
        base = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        tip = self._hg_get_tip()

        revisions = self.client.parse_revision_spec([])
        self.assertTrue(isinstance(revisions, dict))
        self.assertTrue('base' in revisions)
        self.assertTrue('tip' in revisions)
        self.assertTrue('parent_base' not in revisions)
        self.assertEqual(revisions['base'], base)
        self.assertEqual(revisions['tip'], tip)

    def test_parse_revision_spec_one_arg_periods(self):
        """Testing MercurialClient.parse_revision_spec with r1..r2 syntax"""
        base = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        tip = self._hg_get_tip()

        revisions = self.client.parse_revision_spec(['0..1'])
        self.assertTrue(isinstance(revisions, dict))
        self.assertTrue('base' in revisions)
        self.assertTrue('tip' in revisions)
        self.assertTrue('parent_base' not in revisions)
        self.assertEqual(revisions['base'], base)
        self.assertEqual(revisions['tip'], tip)

    def test_parse_revision_spec_one_arg_colons(self):
        """Testing MercurialClient.parse_revision_spec with r1::r2 syntax"""
        base = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        tip = self._hg_get_tip()

        revisions = self.client.parse_revision_spec(['0..1'])
        self.assertTrue(isinstance(revisions, dict))
        self.assertTrue('base' in revisions)
        self.assertTrue('tip' in revisions)
        self.assertTrue('parent_base' not in revisions)
        self.assertEqual(revisions['base'], base)
        self.assertEqual(revisions['tip'], tip)

    def test_parse_revision_spec_one_arg(self):
        """Testing MercurialClient.parse_revision_spec with one revision"""
        base = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        tip = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')

        revisions = self.client.parse_revision_spec(['1'])
        self.assertTrue(isinstance(revisions, dict))
        self.assertTrue('base' in revisions)
        self.assertTrue('tip' in revisions)
        self.assertTrue('parent_base' not in revisions)
        self.assertEqual(revisions['base'], base)
        self.assertEqual(revisions['tip'], tip)

    def test_parse_revision_spec_two_args(self):
        """Testing MercurialClient.parse_revision_spec with two revisions"""
        base = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        tip = self._hg_get_tip()

        revisions = self.client.parse_revision_spec(['0', '2'])
        self.assertTrue(isinstance(revisions, dict))
        self.assertTrue('base' in revisions)
        self.assertTrue('tip' in revisions)
        self.assertTrue('parent_base' not in revisions)
        self.assertEqual(revisions['base'], base)
        self.assertEqual(revisions['tip'], tip)

    def test_parse_revision_spec_parent_base(self):
        """Testing MercurialClient.parse_revision_spec with parent base"""
        start_base = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        commit1 = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        commit2 = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO3, 'commit 3')
        commit3 = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO4, 'commit 4')
        commit4 = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO5, 'commit 5')

        self.assertEqual(
            self.client.parse_revision_spec(['1', '2']),
            dict(base=commit1, tip=commit2, parent_base=start_base))

        self.assertEqual(
            self.client.parse_revision_spec(['4']),
            dict(base=commit3,
                 tip=commit4,
                 parent_base=start_base,
                 commit_id=commit4))

        self.assertEqual(
            self.client.parse_revision_spec(['2', '4']),
            dict(base=commit2, tip=commit4, parent_base=start_base))

    def test_guess_summary_description_one(self):
        """Testing MercurialClient guess summary & description 1 commit"""
        self.options.guess_summary = True
        self.options.guess_description = True

        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')

        revisions = self.client.parse_revision_spec([])
        commit_message = self.client.get_commit_message(revisions)

        self.assertEqual(commit_message['summary'], 'commit 1')

    def test_guess_summary_description_two(self):
        """Testing MercurialClient guess summary & description 2 commits"""
        self.options.guess_summary = True
        self.options.guess_description = True

        self._hg_add_file_commit('foo.txt', FOO1, 'summary 1\n\nbody 1')
        self._hg_add_file_commit('foo.txt', FOO2, 'summary 2\n\nbody 2')

        revisions = self.client.parse_revision_spec([])
        commit_message = self.client.get_commit_message(revisions)

        self.assertEqual(commit_message['summary'], 'summary 1')
        self.assertEqual(commit_message['description'],
                         'body 1\n\nsummary 2\n\nbody 2')

    def test_guess_summary_description_three(self):
        """Testing MercurialClient guess summary & description 3 commits"""
        self.options.guess_summary = True
        self.options.guess_description = True

        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1\n\ndesc1')
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2\n\ndesc2')
        self._hg_add_file_commit('foo.txt', FOO3, 'commit 3\n\ndesc3')

        revisions = self.client.parse_revision_spec([])
        commit_message = self.client.get_commit_message(revisions)

        self.assertEqual(commit_message['summary'], 'commit 1')
        self.assertEqual(commit_message['description'],
                         'desc1\n\ncommit 2\n\ndesc2\n\ncommit 3\n\ndesc3')

    def test_guess_summary_description_one_middle(self):
        """Testing MercurialClient guess summary & description middle commit"""
        self.options.guess_summary = True
        self.options.guess_description = True

        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1\n\ndesc1')
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2\n\ndesc2')
        tip = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO3, 'commit 3\n\ndesc3')

        revisions = self.client.parse_revision_spec([tip])
        commit_message = self.client.get_commit_message(revisions)

        self.assertEqual(commit_message['summary'], 'commit 2')
        self.assertEqual(commit_message['description'], 'desc2')
Ejemplo n.º 2
0
class MercurialClientTests(MercurialTestBase):
    """Unit tests for MercurialClient."""

    TESTSERVER = 'http://127.0.0.1:8080'
    CLONE_HGRC = dedent("""
    [ui]
    username = test user <user at example.com>

    [paths]
    default = %(hg_dir)s
    cloned = %(clone_dir)s

    [reviewboard]
    url = %(test_server)s

    [diff]
    git = true
    """).rstrip()

    def setUp(self):
        super(MercurialClientTests, self).setUp()
        if not is_exe_in_path('hg'):
            raise SkipTest('hg not found in path')

        self.hg_dir = os.path.join(self.testdata_dir, 'hg-repo')
        self.clone_dir = self.chdir_tmp()

        self._run_hg(['clone', self.hg_dir, self.clone_dir])
        self.client = MercurialClient(options=self.options)

        clone_hgrc = open(self.clone_hgrc_path, 'w')
        clone_hgrc.write(self.CLONE_HGRC % {
            'hg_dir': self.hg_dir,
            'clone_dir': self.clone_dir,
            'test_server': self.TESTSERVER,
        })
        clone_hgrc.close()

        self.options.parent_branch = None

    def _hg_get_tip(self):
        return self._run_hg(['identify']).split()[0]

    @property
    def clone_hgrc_path(self):
        return os.path.join(self.clone_dir, '.hg', 'hgrc')

    def test_get_repository_info_simple(self):
        """Testing MercurialClient get_repository_info, simple case"""
        ri = self.client.get_repository_info()

        self.assertTrue(isinstance(ri, RepositoryInfo))
        self.assertEqual('', ri.base_path)

        hgpath = ri.path

        if os.path.basename(hgpath) == '.hg':
            hgpath = os.path.dirname(hgpath)

        self.assertEqual(self.hg_dir, hgpath)
        self.assertTrue(ri.supports_parent_diffs)
        self.assertFalse(ri.supports_changesets)

    def test_scan_for_server_simple(self):
        """Testing MercurialClient scan_for_server, simple case"""
        os.rename(self.clone_hgrc_path,
                  os.path.join(self.clone_dir, '._disabled_hgrc'))

        self.client.hgrc = {}
        self.client._load_hgrc()
        ri = self.client.get_repository_info()

        server = self.client.scan_for_server(ri)
        self.assertTrue(server is None)

    def test_scan_for_server_when_present_in_hgrc(self):
        """Testing MercurialClient scan_for_server when present in hgrc"""
        ri = self.client.get_repository_info()

        server = self.client.scan_for_server(ri)
        self.assertEqual(self.TESTSERVER, server)

    def test_scan_for_server_reviewboardrc(self):
        """Testing MercurialClient scan_for_server when in .reviewboardrc"""
        with self.reviewboardrc({'REVIEWBOARD_URL': self.TESTSERVER}):
            self.client.config = load_config()

            ri = self.client.get_repository_info()
            server = self.client.scan_for_server(ri)
            self.assertEqual(self.TESTSERVER, server)

    def test_diff_simple(self):
        """Testing MercurialClient diff, simple case"""
        self._hg_add_file_commit('foo.txt', FOO1, 'delete and modify stuff')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(md5(result['diff']).hexdigest(),
                         '68c2bdccf52a4f0baddd0ac9f2ecb7d2')

    def test_diff_simple_multiple(self):
        """Testing MercurialClient diff with multiple commits"""
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        self._hg_add_file_commit('foo.txt', FOO3, 'commit 3')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(md5(result['diff']).hexdigest(),
                         '9c8796936646be5c7349973b0fceacbd')

    def test_diff_exclude(self):
        """Testing MercurialClient diff with file exclusion"""
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._hg_add_file_commit('exclude.txt', FOO2, 'commit 2')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions, exclude_patterns=['exclude.txt'])
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(md5(result['diff']).hexdigest(),
                         '68c2bdccf52a4f0baddd0ac9f2ecb7d2')

    def test_diff_exclude_empty(self):
        """Testing MercurialClient diff with empty file exclusion"""
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._hg_add_file_commit('empty.txt', b'', 'commit 2')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions, exclude_patterns=['empty.txt'])
        self.assertTrue(isinstance(revisions, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(md5(result['diff']).hexdigest(),
                         '68c2bdccf52a4f0baddd0ac9f2ecb7d2')

    def test_diff_branch_diverge(self):
        """Testing MercurialClient diff with diverged branch"""
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')

        self._run_hg(['branch', 'diverged'])
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(md5(result['diff']).hexdigest(),
                         '6b12723baab97f346aa938005bc4da4d')

        self._run_hg(['update', '-C', 'default'])

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(md5(result['diff']).hexdigest(),
                         '68c2bdccf52a4f0baddd0ac9f2ecb7d2')

    def test_diff_parent_diff_simple(self):
        """Testing MercurialClient parent diffs with a simple case"""
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        self._hg_add_file_commit('foo.txt', FOO3, 'commit 3')

        revisions = self.client.parse_revision_spec(['2', '3'])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('parent_diff' in result)
        self.assertEqual(md5(result['diff']).hexdigest(),
                         '7a897f68a9dc034fc1e42fe7a33bb808')
        self.assertEqual(md5(result['parent_diff']).hexdigest(),
                         '5cacbd79800a9145f982dcc0908b6068')

    def test_diff_parent_diff_branch_diverge(self):
        """Testing MercurialClient parent diffs with a diverged branch"""

        # This test is very similar to test_diff_parent_diff_simple except
        # we throw a branch into the mix.
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._run_hg(['branch', 'diverged'])
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        self._hg_add_file_commit('foo.txt', FOO3, 'commit 3')

        revisions = self.client.parse_revision_spec(['2', '3'])
        result = self.client.diff(revisions)
        self.assertTrue('parent_diff' in result)
        self.assertEqual(md5(result['diff']).hexdigest(),
                         '7a897f68a9dc034fc1e42fe7a33bb808')
        self.assertEqual(md5(result['parent_diff']).hexdigest(),
                         '5cacbd79800a9145f982dcc0908b6068')

    def test_diff_parent_diff_simple_with_arg(self):
        """Testing MercurialClient parent diffs with a diverged branch and
        --parent option"""
        # This test is very similar to test_diff_parent_diff_simple except
        # we use the --parent option to post without explicit revisions
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        self._hg_add_file_commit('foo.txt', FOO3, 'commit 3')

        self.options.parent_branch = '2'

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('parent_diff' in result)
        self.assertEqual(md5(result['diff']).hexdigest(),
                         '7a897f68a9dc034fc1e42fe7a33bb808')
        self.assertEqual(md5(result['parent_diff']).hexdigest(),
                         '5cacbd79800a9145f982dcc0908b6068')

    def test_parse_revision_spec_no_args(self):
        """Testing MercurialClient.parse_revision_spec with no arguments"""
        base = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        tip = self._hg_get_tip()

        revisions = self.client.parse_revision_spec([])
        self.assertTrue(isinstance(revisions, dict))
        self.assertTrue('base' in revisions)
        self.assertTrue('tip' in revisions)
        self.assertTrue('parent_base' not in revisions)
        self.assertEqual(revisions['base'], base)
        self.assertEqual(revisions['tip'], tip)

    def test_parse_revision_spec_one_arg_periods(self):
        """Testing MercurialClient.parse_revision_spec with r1..r2 syntax"""
        base = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        tip = self._hg_get_tip()

        revisions = self.client.parse_revision_spec(['0..1'])
        self.assertTrue(isinstance(revisions, dict))
        self.assertTrue('base' in revisions)
        self.assertTrue('tip' in revisions)
        self.assertTrue('parent_base' not in revisions)
        self.assertEqual(revisions['base'], base)
        self.assertEqual(revisions['tip'], tip)

    def test_parse_revision_spec_one_arg_colons(self):
        """Testing MercurialClient.parse_revision_spec with r1::r2 syntax"""
        base = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        tip = self._hg_get_tip()

        revisions = self.client.parse_revision_spec(['0..1'])
        self.assertTrue(isinstance(revisions, dict))
        self.assertTrue('base' in revisions)
        self.assertTrue('tip' in revisions)
        self.assertTrue('parent_base' not in revisions)
        self.assertEqual(revisions['base'], base)
        self.assertEqual(revisions['tip'], tip)

    def test_parse_revision_spec_one_arg(self):
        """Testing MercurialClient.parse_revision_spec with one revision"""
        base = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        tip = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')

        revisions = self.client.parse_revision_spec(['1'])
        self.assertTrue(isinstance(revisions, dict))
        self.assertTrue('base' in revisions)
        self.assertTrue('tip' in revisions)
        self.assertTrue('parent_base' not in revisions)
        self.assertEqual(revisions['base'], base)
        self.assertEqual(revisions['tip'], tip)

    def test_parse_revision_spec_two_args(self):
        """Testing MercurialClient.parse_revision_spec with two revisions"""
        base = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        tip = self._hg_get_tip()

        revisions = self.client.parse_revision_spec(['0', '2'])
        self.assertTrue(isinstance(revisions, dict))
        self.assertTrue('base' in revisions)
        self.assertTrue('tip' in revisions)
        self.assertTrue('parent_base' not in revisions)
        self.assertEqual(revisions['base'], base)
        self.assertEqual(revisions['tip'], tip)

    def test_parse_revision_spec_parent_base(self):
        """Testing MercurialClient.parse_revision_spec with parent base"""
        start_base = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        commit1 = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        commit2 = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO3, 'commit 3')
        commit3 = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO4, 'commit 4')
        commit4 = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO5, 'commit 5')

        self.assertEqual(
            self.client.parse_revision_spec(['1', '2']),
            dict(base=commit1, tip=commit2, parent_base=start_base))

        self.assertEqual(
            self.client.parse_revision_spec(['4']),
            dict(base=commit3, tip=commit4, parent_base=start_base,
                 commit_id=commit4))

        self.assertEqual(
            self.client.parse_revision_spec(['2', '4']),
            dict(base=commit2, tip=commit4, parent_base=start_base))

    def test_guess_summary_description_one(self):
        """Testing MercurialClient guess summary & description 1 commit"""
        self.options.guess_summary = True
        self.options.guess_description = True

        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')

        revisions = self.client.parse_revision_spec([])
        commit_message = self.client.get_commit_message(revisions)

        self.assertEqual(commit_message['summary'], 'commit 1')

    def test_guess_summary_description_two(self):
        """Testing MercurialClient guess summary & description 2 commits"""
        self.options.guess_summary = True
        self.options.guess_description = True

        self._hg_add_file_commit('foo.txt', FOO1, 'summary 1\n\nbody 1')
        self._hg_add_file_commit('foo.txt', FOO2, 'summary 2\n\nbody 2')

        revisions = self.client.parse_revision_spec([])
        commit_message = self.client.get_commit_message(revisions)

        self.assertEqual(commit_message['summary'], 'summary 1')
        self.assertEqual(commit_message['description'],
                         'body 1\n\nsummary 2\n\nbody 2')

    def test_guess_summary_description_three(self):
        """Testing MercurialClient guess summary & description 3 commits"""
        self.options.guess_summary = True
        self.options.guess_description = True

        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1\n\ndesc1')
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2\n\ndesc2')
        self._hg_add_file_commit('foo.txt', FOO3, 'commit 3\n\ndesc3')

        revisions = self.client.parse_revision_spec([])
        commit_message = self.client.get_commit_message(revisions)

        self.assertEqual(commit_message['summary'], 'commit 1')
        self.assertEqual(commit_message['description'],
                         'desc1\n\ncommit 2\n\ndesc2\n\ncommit 3\n\ndesc3')

    def test_guess_summary_description_one_middle(self):
        """Testing MercurialClient guess summary & description middle commit"""
        self.options.guess_summary = True
        self.options.guess_description = True

        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1\n\ndesc1')
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2\n\ndesc2')
        tip = self._hg_get_tip()
        self._hg_add_file_commit('foo.txt', FOO3, 'commit 3\n\ndesc3')

        revisions = self.client.parse_revision_spec([tip])
        commit_message = self.client.get_commit_message(revisions)

        self.assertEqual(commit_message['summary'], 'commit 2')
        self.assertEqual(commit_message['description'], 'desc2')
Ejemplo n.º 3
0
class MercurialSubversionClientTests(MercurialTestBase):
    """Unit tests for hgsubversion."""

    TESTSERVER = "http://127.0.0.1:8080"

    def __init__(self, *args, **kwargs):
        self._tmpbase = ''
        self.clone_dir = ''
        self.svn_repo = ''
        self.svn_checkout = ''
        self.client = None
        self._svnserve_pid = 0
        self._max_svnserve_pid_tries = 12
        self._svnserve_port = os.environ.get('SVNSERVE_PORT')
        self._required_exes = ('svnadmin', 'svnserve', 'svn')
        MercurialTestBase.__init__(self, *args, **kwargs)

    def setUp(self):
        super(MercurialSubversionClientTests, self).setUp()
        self._hg_env = {'FOO': 'BAR'}

        # Make sure hgsubversion is enabled.
        #
        # This will modify the .hgrc in the temp home directory created
        # for these tests.
        #
        # The "hgsubversion =" tells Mercurial to check for hgsubversion
        # in the default PYTHONPATH.
        fp = open('%s/.hgrc' % os.environ['HOME'], 'w')
        fp.write('[extensions]\n')
        fp.write('hgsubversion =\n')
        fp.close()

        for exe in self._required_exes:
            if not is_exe_in_path(exe):
                raise SkipTest('missing svn stuff!  giving up!')

        if not self._has_hgsubversion():
            raise SkipTest('unable to use `hgsubversion` extension!  '
                           'giving up!')

        if not self._tmpbase:
            self._tmpbase = self.create_tmp_dir()

        self._create_svn_repo()
        self._fire_up_svnserve()
        self._fill_in_svn_repo()

        try:
            self._get_testing_clone()
        except (OSError, IOError):
            msg = 'could not clone from svn repo!  skipping...'
            raise SkipTest(msg).with_traceback(sys.exc_info()[2])

        self._spin_up_client()
        self._stub_in_config_and_options()

    def _has_hgsubversion(self):
        try:
            output = self._run_hg(['svn', '--help'],
                                  ignore_errors=True,
                                  extra_ignore_errors=(255))
        except OSError:
            return False

        return not re.search("unknown command ['\"]svn['\"]", output, re.I)

    def tearDown(self):
        super(MercurialSubversionClientTests, self).tearDown()

        os.kill(self._svnserve_pid, 9)

    def _svn_add_file_commit(self, filename, data, msg, add_file=True):
        outfile = open(filename, 'w')
        outfile.write(data)
        outfile.close()

        if add_file:
            execute(['svn', 'add', filename], ignore_errors=True)

        execute(['svn', 'commit', '-m', msg])

    def _create_svn_repo(self):
        self.svn_repo = os.path.join(self._tmpbase, 'svnrepo')
        execute(['svnadmin', 'create', self.svn_repo])

    def _fire_up_svnserve(self):
        if not self._svnserve_port:
            self._svnserve_port = str(randint(30000, 40000))

        pid_file = os.path.join(self._tmpbase, 'svnserve.pid')
        execute([
            'svnserve', '--pid-file', pid_file, '-d', '--listen-port',
            self._svnserve_port, '-r', self._tmpbase
        ])

        for i in range(0, self._max_svnserve_pid_tries):
            try:
                self._svnserve_pid = int(open(pid_file).read().strip())
                return

            except (IOError, OSError):
                time.sleep(0.25)

        # This will re-raise the last exception, which will be either
        # IOError or OSError if the above fails and this branch is reached
        raise

    def _fill_in_svn_repo(self):
        self.svn_checkout = os.path.join(self._tmpbase, 'checkout.svn')
        execute([
            'svn', 'checkout',
            'file://%s' % self.svn_repo, self.svn_checkout
        ])
        os.chdir(self.svn_checkout)

        for subtree in ('trunk', 'branches', 'tags'):
            execute(['svn', 'mkdir', subtree])

        execute(['svn', 'commit', '-m', 'filling in T/b/t'])
        os.chdir(os.path.join(self.svn_checkout, 'trunk'))

        for i, data in enumerate([FOO, FOO1, FOO2]):
            self._svn_add_file_commit('foo.txt',
                                      data,
                                      'foo commit %s' % i,
                                      add_file=(i == 0))

    def _get_testing_clone(self):
        self.clone_dir = os.path.join(self._tmpbase, 'checkout.hg')
        self._run_hg([
            'clone',
            'svn://127.0.0.1:%s/svnrepo' % self._svnserve_port,
            self.clone_dir,
        ])

    def _spin_up_client(self):
        os.chdir(self.clone_dir)
        self.client = MercurialClient(options=self.options)

    def _stub_in_config_and_options(self):
        self.options.parent_branch = None

    def testGetRepositoryInfoSimple(self):
        """Testing MercurialClient (+svn) get_repository_info, simple case"""
        ri = self.client.get_repository_info()

        self.assertEqual('svn', self.client._type)
        self.assertEqual('/trunk', ri.base_path)
        self.assertEqual('svn://127.0.0.1:%s/svnrepo' % self._svnserve_port,
                         ri.path)

    def testCalculateRepositoryInfo(self):
        """Testing MercurialClient (+svn)
        _calculate_hgsubversion_repository_info properly determines repository
        and base paths"""
        info = (
            "URL: svn+ssh://[email protected]/repo/trunk\n"
            "Repository Root: svn+ssh://[email protected]/repo\n"
            "Repository UUID: bfddb570-5023-0410-9bc8-bc1659bf7c01\n"
            "Revision: 9999\n"
            "Node Kind: directory\n"
            "Last Changed Author: user\n"
            "Last Changed Rev: 9999\n"
            "Last Changed Date: 2012-09-05 18:04:28 +0000 (Wed, 05 Sep 2012)")

        repo_info = self.client._calculate_hgsubversion_repository_info(info)

        self.assertEqual(repo_info.path, "svn+ssh://svn.example.net/repo")
        self.assertEqual(repo_info.base_path, "/trunk")

    def testScanForServerSimple(self):
        """Testing MercurialClient (+svn) scan_for_server, simple case"""
        ri = self.client.get_repository_info()
        server = self.client.scan_for_server(ri)

        self.assertTrue(server is None)

    def testScanForServerReviewboardrc(self):
        """Testing MercurialClient (+svn) scan_for_server in .reviewboardrc"""
        rc_filename = os.path.join(self.clone_dir, '.reviewboardrc')
        rc = open(rc_filename, 'w')
        rc.write('REVIEWBOARD_URL = "%s"' % self.TESTSERVER)
        rc.close()
        self.client.config = load_config()

        ri = self.client.get_repository_info()
        server = self.client.scan_for_server(ri)

        self.assertEqual(self.TESTSERVER, server)

    def testScanForServerProperty(self):
        """Testing MercurialClient (+svn) scan_for_server in svn property"""
        os.chdir(self.svn_checkout)
        execute(['svn', 'update'])
        execute([
            'svn', 'propset', 'reviewboard:url', self.TESTSERVER,
            self.svn_checkout
        ])
        execute(['svn', 'commit', '-m', 'adding reviewboard:url property'])

        os.chdir(self.clone_dir)
        self._run_hg(['pull'])
        self._run_hg(['update', '-C'])

        ri = self.client.get_repository_info()

        self.assertEqual(self.TESTSERVER, self.client.scan_for_server(ri))

    def testDiffSimple(self):
        """Testing MercurialClient (+svn) diff, simple case"""
        self.client.get_repository_info()

        self._hg_add_file_commit('foo.txt', FOO4, 'edit 4')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '2eb0a5f2149232c43a1745d90949fcd5')
        self.assertEqual(result['parent_diff'], None)

    def testDiffSimpleMultiple(self):
        """Testing MercurialClient (+svn) diff with multiple commits"""
        self.client.get_repository_info()

        self._hg_add_file_commit('foo.txt', FOO4, 'edit 4')
        self._hg_add_file_commit('foo.txt', FOO5, 'edit 5')
        self._hg_add_file_commit('foo.txt', FOO6, 'edit 6')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '3d007394de3831d61e477cbcfe60ece8')
        self.assertEqual(result['parent_diff'], None)

    def testDiffOfRevision(self):
        """Testing MercurialClient (+svn) diff specifying a revision"""
        self.client.get_repository_info()

        self._hg_add_file_commit('foo.txt', FOO4, 'edit 4', branch='b')
        self._hg_add_file_commit('foo.txt', FOO5, 'edit 5', branch='b')
        self._hg_add_file_commit('foo.txt', FOO6, 'edit 6', branch='b')
        self._hg_add_file_commit('foo.txt', FOO4, 'edit 7', branch='b')

        revisions = self.client.parse_revision_spec(['3'])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '2eb0a5f2149232c43a1745d90949fcd5')
        self.assertEqual(result['parent_diff'], None)
Ejemplo n.º 4
0
class MercurialSubversionClientTests(MercurialTestBase):
    TESTSERVER = "http://127.0.0.1:8080"

    def __init__(self, *args, **kwargs):
        self._tmpbase = ''
        self.clone_dir = ''
        self.svn_repo = ''
        self.svn_checkout = ''
        self.client = None
        self._svnserve_pid = 0
        self._max_svnserve_pid_tries = 12
        self._svnserve_port = os.environ.get('SVNSERVE_PORT')
        self._required_exes = ('svnadmin', 'svnserve', 'svn')
        MercurialTestBase.__init__(self, *args, **kwargs)

    def setUp(self):
        MercurialTestBase.setUp(self)
        self._hg_env = {'FOO': 'BAR'}

        for exe in self._required_exes:
            if not is_exe_in_path(exe):
                raise nose.SkipTest('missing svn stuff!  giving up!')

        if not self._has_hgsubversion():
            raise nose.SkipTest('unable to use `hgsubversion` extension!  '
                                'giving up!')

        if not self._tmpbase:
            self._tmpbase = _get_tmpdir()

        self._create_svn_repo()
        self._fire_up_svnserve()
        self._fill_in_svn_repo()

        try:
            self._get_testing_clone()
        except (OSError, IOError):
            msg = 'could not clone from svn repo!  skipping...'
            raise nose.SkipTest(msg), None, sys.exc_info()[2]

        self._spin_up_client()
        self._stub_in_config_and_options()
        os.chdir(self.clone_dir)

    def _has_hgsubversion(self):
        output = self._hgcmd(['svn', '--help'],
                             ignore_errors=True, extra_ignore_errors=(255))

        return not re.search("unknown command ['\"]svn['\"]", output, re.I)

    def tearDown(self):
        shutil.rmtree(self.clone_dir)
        os.kill(self._svnserve_pid, 9)

        if self._tmpbase:
            shutil.rmtree(self._tmpbase)

    def _svn_add_file_commit(self, filename, data, msg):
        outfile = open(filename, 'w')
        outfile.write(data)
        outfile.close()
        execute(['svn', 'add', filename])
        execute(['svn', 'commit', '-m', msg])

    def _create_svn_repo(self):
        self.svn_repo = os.path.join(self._tmpbase, 'svnrepo')
        execute(['svnadmin', 'create', self.svn_repo])

    def _fire_up_svnserve(self):
        if not self._svnserve_port:
            self._svnserve_port = str(randint(30000, 40000))

        pid_file = os.path.join(self._tmpbase, 'svnserve.pid')
        execute(['svnserve', '--pid-file', pid_file, '-d',
                 '--listen-port', self._svnserve_port, '-r', self._tmpbase])

        for i in range(0, self._max_svnserve_pid_tries):
            try:
                self._svnserve_pid = int(open(pid_file).read().strip())
                return

            except (IOError, OSError):
                time.sleep(0.25)

        # This will re-raise the last exception, which will be either
        # IOError or OSError if the above fails and this branch is reached
        raise

    def _fill_in_svn_repo(self):
        self.svn_checkout = os.path.join(self._tmpbase, 'checkout.svn')
        execute(['svn', 'checkout', 'file://%s' % self.svn_repo,
                 self.svn_checkout])
        os.chdir(self.svn_checkout)

        for subtree in ('trunk', 'branches', 'tags'):
            execute(['svn', 'mkdir', subtree])

        execute(['svn', 'commit', '-m', 'filling in T/b/t'])
        os.chdir(os.path.join(self.svn_checkout, 'trunk'))

        for i, data in enumerate([FOO, FOO1, FOO2]):
            self._svn_add_file_commit('foo.txt', data, 'foo commit %s' % i)

    def _get_testing_clone(self):
        self.clone_dir = os.path.join(self._tmpbase, 'checkout.hg')
        self._hgcmd([
            'clone', 'svn://127.0.0.1:%s/svnrepo' % self._svnserve_port,
            self.clone_dir,
        ])

    def _spin_up_client(self):
        os.chdir(self.clone_dir)
        self.client = MercurialClient(options=postreview.options)

    def _stub_in_config_and_options(self):
        postreview.user_config = {}
        postreview.configs = []
        self.client.user_config = postreview.user_config
        self.client.configs = postreview.configs
        postreview.options.parent_branch = None

    def testGetRepositoryInfoSimple(self):
        """Test MercurialClient (+svn) get_repository_info, simple case"""
        ri = self.client.get_repository_info()

        self.assertEqual('svn', self.client._type)
        self.assertEqual('/trunk', ri.base_path)
        self.assertEqual('svn://127.0.0.1:%s/svnrepo' % self._svnserve_port,
                        ri.path)

    def testScanForServerSimple(self):
        """Test MercurialClient (+svn) scan_for_server, simple case"""
        ri = self.client.get_repository_info()
        server = self.client.scan_for_server(ri)

        self.assertTrue(server is None)

    def testScanForServerReviewboardrc(self):
        """Test MercurialClient (+svn) scan_for_server in .reviewboardrc"""
        rc_filename = os.path.join(self.clone_dir, '.reviewboardrc')
        rc = open(rc_filename, 'w')
        rc.write('REVIEWBOARD_URL = "%s"' % self.TESTSERVER)
        rc.close()

        ri = self.client.get_repository_info()
        server = self.client.scan_for_server(ri)

        self.assertEqual(self.TESTSERVER, server)

    def testScanForServerProperty(self):
        """Test MercurialClient (+svn) scan_for_server in svn property"""
        os.chdir(self.svn_checkout)
        execute(['svn', 'update'])
        execute(['svn', 'propset', 'reviewboard:url', self.TESTSERVER,
                 self.svn_checkout])
        execute(['svn', 'commit', '-m', 'adding reviewboard:url property'])

        os.chdir(self.clone_dir)
        self._hgcmd(['pull'])
        self._hgcmd(['update', '-C'])

        ri = self.client.get_repository_info()

        self.assertEqual(self.TESTSERVER, self.client.scan_for_server(ri))

    def testDiffSimple(self):
        """Test MercurialClient (+svn) diff, simple case"""
        self.client.get_repository_info()

        self._hg_add_file_commit('foo.txt', FOO4, 'edit 4')

        self.assertEqual(EXPECTED_HG_SVN_DIFF_0, self.client.diff(None)[0])

    def testDiffSimpleMultiple(self):
        """Test MercurialClient (+svn) diff with multiple commits"""
        self.client.get_repository_info()

        self._hg_add_file_commit('foo.txt', FOO4, 'edit 4')
        self._hg_add_file_commit('foo.txt', FOO5, 'edit 5')
        self._hg_add_file_commit('foo.txt', FOO6, 'edit 6')

        self.assertEqual(EXPECTED_HG_SVN_DIFF_1, self.client.diff(None)[0])
Ejemplo n.º 5
0
class MercurialSubversionClientTests(MercurialTestBase):
    """Unit tests for hgsubversion."""

    TESTSERVER = 'http://127.0.0.1:8080'

    def __init__(self, *args, **kwargs):
        self._tmpbase = ''
        self.clone_dir = ''
        self.svn_repo = ''
        self.svn_checkout = ''
        self.client = None
        self._svnserve_pid = 0
        self._max_svnserve_pid_tries = 12
        self._svnserve_port = os.environ.get('SVNSERVE_PORT')
        self._required_exes = ('svnadmin', 'svnserve', 'svn')
        MercurialTestBase.__init__(self, *args, **kwargs)

    def setUp(self):
        super(MercurialSubversionClientTests, self).setUp()
        self._hg_env = {'FOO': 'BAR'}

        # Make sure hgsubversion is enabled.
        #
        # This will modify the .hgrc in the temp home directory created
        # for these tests.
        #
        # The "hgsubversion =" tells Mercurial to check for hgsubversion
        # in the default PYTHONPATH.
        fp = open('%s/.hgrc' % os.environ['HOME'], 'w')
        fp.write('[extensions]\n')
        fp.write('hgsubversion =\n')
        fp.close()

        for exe in self._required_exes:
            if not is_exe_in_path(exe):
                raise SkipTest('missing svn stuff!  giving up!')

        if not self._has_hgsubversion():
            raise SkipTest('unable to use `hgsubversion` extension!  '
                           'giving up!')

        if not self._tmpbase:
            self._tmpbase = make_tempdir()

        self._create_svn_repo()
        self._fire_up_svnserve()
        self._fill_in_svn_repo()

        try:
            self._get_testing_clone()
        except (OSError, IOError):
            msg = 'could not clone from svn repo!  skipping...'
            raise SkipTest(msg).with_traceback(sys.exc_info()[2])

        self._spin_up_client()
        self._stub_in_config_and_options()

    def _has_hgsubversion(self):
        try:
            output = self._run_hg(['svn', '--help'], ignore_errors=True,
                                  extra_ignore_errors=(255))
        except OSError:
            return False

        return not re.search('unknown command [\'"]svn[\'"]', output, re.I)

    def tearDown(self):
        super(MercurialSubversionClientTests, self).tearDown()

        os.kill(self._svnserve_pid, 9)

    def _svn_add_file_commit(self, filename, data, msg, add_file=True):
        outfile = open(filename, 'w')
        outfile.write(data)
        outfile.close()

        if add_file:
            execute(['svn', 'add', filename], ignore_errors=True)

        execute(['svn', 'commit', '-m', msg])

    def _create_svn_repo(self):
        self.svn_repo = os.path.join(self._tmpbase, 'svnrepo')
        execute(['svnadmin', 'create', self.svn_repo])

    def _fire_up_svnserve(self):
        if not self._svnserve_port:
            self._svnserve_port = str(randint(30000, 40000))

        pid_file = os.path.join(self._tmpbase, 'svnserve.pid')
        execute(['svnserve', '--single-thread', '--pid-file', pid_file, '-d',
                 '--listen-port', self._svnserve_port, '-r', self._tmpbase])

        for i in range(0, self._max_svnserve_pid_tries):
            try:
                self._svnserve_pid = int(open(pid_file).read().strip())
                return

            except (IOError, OSError):
                time.sleep(0.25)

        # This will re-raise the last exception, which will be either
        # IOError or OSError if the above fails and this branch is reached
        raise

    def _fill_in_svn_repo(self):
        self.svn_checkout = os.path.join(self._tmpbase, 'checkout.svn')
        execute(['svn', 'checkout', 'file://%s' % self.svn_repo,
                 self.svn_checkout])
        os.chdir(self.svn_checkout)

        for subtree in ('trunk', 'branches', 'tags'):
            execute(['svn', 'mkdir', subtree])

        execute(['svn', 'commit', '-m', 'filling in T/b/t'])
        os.chdir(os.path.join(self.svn_checkout, 'trunk'))

        for i, data in enumerate([FOO, FOO1, FOO2]):
            self._svn_add_file_commit('foo.txt', data, 'foo commit %s' % i,
                                      add_file=(i == 0))

    def _get_testing_clone(self):
        self.clone_dir = os.path.join(self._tmpbase, 'checkout.hg')
        self._run_hg([
            'clone', 'svn://127.0.0.1:%s/svnrepo' % self._svnserve_port,
            self.clone_dir,
        ])

    def _spin_up_client(self):
        os.chdir(self.clone_dir)
        self.client = MercurialClient(options=self.options)

    def _stub_in_config_and_options(self):
        self.options.parent_branch = None

    def testGetRepositoryInfoSimple(self):
        """Testing MercurialClient (+svn) get_repository_info, simple case"""
        ri = self.client.get_repository_info()

        self.assertEqual('svn', self.client._type)
        self.assertEqual('/trunk', ri.base_path)
        self.assertEqual('svn://127.0.0.1:%s/svnrepo' % self._svnserve_port,
                         ri.path)

    def testCalculateRepositoryInfo(self):
        """Testing MercurialClient (+svn)
        _calculate_hgsubversion_repository_info properly determines repository
        and base paths"""
        info = (
            'URL: svn+ssh://[email protected]/repo/trunk\n'
            'Repository Root: svn+ssh://[email protected]/repo\n'
            'Repository UUID: bfddb570-5023-0410-9bc8-bc1659bf7c01\n'
            'Revision: 9999\n'
            'Node Kind: directory\n'
            'Last Changed Author: user\n'
            'Last Changed Rev: 9999\n'
            'Last Changed Date: 2012-09-05 18:04:28 +0000 (Wed, 05 Sep 2012)')

        repo_info = self.client._calculate_hgsubversion_repository_info(info)

        self.assertEqual(repo_info.path, 'svn+ssh://svn.example.net/repo')
        self.assertEqual(repo_info.base_path, '/trunk')

    def testScanForServerSimple(self):
        """Testing MercurialClient (+svn) scan_for_server, simple case"""
        ri = self.client.get_repository_info()
        server = self.client.scan_for_server(ri)

        self.assertTrue(server is None)

    def testScanForServerReviewboardrc(self):
        """Testing MercurialClient (+svn) scan_for_server in .reviewboardrc"""
        with self.reviewboardrc({'REVIEWBOARD_URL': self.TESTSERVER}):
            self.client.config = load_config()

            ri = self.client.get_repository_info()
            server = self.client.scan_for_server(ri)

            self.assertEqual(self.TESTSERVER, server)

    def testScanForServerProperty(self):
        """Testing MercurialClient (+svn) scan_for_server in svn property"""
        os.chdir(self.svn_checkout)
        execute(['svn', 'update'])
        execute(['svn', 'propset', 'reviewboard:url', self.TESTSERVER,
                 self.svn_checkout])
        execute(['svn', 'commit', '-m', 'adding reviewboard:url property'])

        os.chdir(self.clone_dir)
        self._run_hg(['pull'])
        self._run_hg(['update', '-C'])

        ri = self.client.get_repository_info()

        self.assertEqual(self.TESTSERVER, self.client.scan_for_server(ri))

    def testDiffSimple(self):
        """Testing MercurialClient (+svn) diff, simple case"""
        self.client.get_repository_info()

        self._hg_add_file_commit('foo.txt', FOO4, 'edit 4')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(md5(result['diff']).hexdigest(),
                         '2eb0a5f2149232c43a1745d90949fcd5')
        self.assertEqual(result['parent_diff'], None)

    def testDiffSimpleMultiple(self):
        """Testing MercurialClient (+svn) diff with multiple commits"""
        self.client.get_repository_info()

        self._hg_add_file_commit('foo.txt', FOO4, 'edit 4')
        self._hg_add_file_commit('foo.txt', FOO5, 'edit 5')
        self._hg_add_file_commit('foo.txt', FOO6, 'edit 6')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(md5(result['diff']).hexdigest(),
                         '3d007394de3831d61e477cbcfe60ece8')
        self.assertEqual(result['parent_diff'], None)

    def testDiffOfRevision(self):
        """Testing MercurialClient (+svn) diff specifying a revision"""
        self.client.get_repository_info()

        self._hg_add_file_commit('foo.txt', FOO4, 'edit 4', branch='b')
        self._hg_add_file_commit('foo.txt', FOO5, 'edit 5', branch='b')
        self._hg_add_file_commit('foo.txt', FOO6, 'edit 6', branch='b')
        self._hg_add_file_commit('foo.txt', FOO4, 'edit 7', branch='b')

        revisions = self.client.parse_revision_spec(['3'])
        result = self.client.diff(revisions)
        self.assertTrue(isinstance(result, dict))
        self.assertTrue('diff' in result)
        self.assertEqual(md5(result['diff']).hexdigest(),
                         '2eb0a5f2149232c43a1745d90949fcd5')
        self.assertEqual(result['parent_diff'], None)
Ejemplo n.º 6
0
class MercurialClientTests(MercurialTestBase):
    TESTSERVER = 'http://127.0.0.1:8080'
    CLONE_HGRC = dedent("""
    [paths]
    default = %(hg_dir)s
    cloned = %(clone_dir)s

    [reviewboard]
    url = %(test_server)s

    [diff]
    git = true
    """).rstrip()

    def setUp(self):
        MercurialTestBase.setUp(self)
        if not is_exe_in_path('hg'):
            raise nose.SkipTest('hg not found in path')

        self.orig_dir = os.getcwd()

        self.hg_dir = _get_tmpdir()
        os.chdir(self.hg_dir)
        self._hgcmd(['init'], hg_dir=self.hg_dir)
        foo = open(os.path.join(self.hg_dir, 'foo.txt'), 'w')
        foo.write(FOO)
        foo.close()

        self._hgcmd(['add', 'foo.txt'])
        self._hgcmd(['commit', '-m', 'initial commit'])

        self.clone_dir = _get_tmpdir()
        os.rmdir(self.clone_dir)
        self._hgcmd(['clone', self.hg_dir, self.clone_dir])
        os.chdir(self.clone_dir)
        self.client = MercurialClient(options=postreview.options)

        clone_hgrc = open(self.clone_hgrc_path, 'wb')
        clone_hgrc.write(self.CLONE_HGRC % {
            'hg_dir': self.hg_dir,
            'clone_dir': self.clone_dir,
            'test_server': self.TESTSERVER,
        })
        clone_hgrc.close()

        self.client.get_repository_info()
        postreview.user_config = {}
        postreview.configs = []
        self.client.user_config = postreview.user_config
        self.client.configs = postreview.configs
        postreview.options.parent_branch = None
        os.chdir(self.clone_dir)

    @property
    def clone_hgrc_path(self):
        return os.path.join(self.clone_dir, '.hg', 'hgrc')

    @property
    def hgrc_path(self):
        return os.path.join(self.hg_dir, '.hg', 'hgrc')

    def tearDown(self):
        os.chdir(self.orig_dir)
        shutil.rmtree(self.hg_dir)
        shutil.rmtree(self.clone_dir)

    def testGetRepositoryInfoSimple(self):
        """Test MercurialClient get_repository_info, simple case"""
        ri = self.client.get_repository_info()

        self.assertTrue(isinstance(ri, RepositoryInfo))
        self.assertEqual('', ri.base_path)

        hgpath = ri.path

        if os.path.basename(hgpath) == '.hg':
            hgpath = os.path.dirname(hgpath)

        self.assertEqual(self.hg_dir, hgpath)
        self.assertTrue(ri.supports_parent_diffs)
        self.assertFalse(ri.supports_changesets)

    def testScanForServerSimple(self):
        """Test MercurialClient scan_for_server, simple case"""
        os.rename(self.clone_hgrc_path,
            os.path.join(self.clone_dir, '._disabled_hgrc'))

        self.client.hgrc = {}
        self.client._load_hgrc()
        ri = self.client.get_repository_info()

        server = self.client.scan_for_server(ri)
        self.assertTrue(server is None)

    def testScanForServerWhenPresentInHgrc(self):
        """Test MercurialClient scan_for_server when present in hgrc"""
        ri = self.client.get_repository_info()

        server = self.client.scan_for_server(ri)
        self.assertEqual(self.TESTSERVER, server)

    def testScanForServerReviewboardrc(self):
        """Test MercurialClient scan_for_server when in .reviewboardrc"""
        rc = open(os.path.join(self.clone_dir, '.reviewboardrc'), 'w')
        rc.write('REVIEWBOARD_URL = "%s"' % self.TESTSERVER)
        rc.close()

        ri = self.client.get_repository_info()
        server = self.client.scan_for_server(ri)
        self.assertEqual(self.TESTSERVER, server)

    def testDiffSimple(self):
        """Test MercurialClient diff, simple case"""
        self.client.get_repository_info()

        self._hg_add_file_commit('foo.txt', FOO1, 'delete and modify stuff')

        diff_result = self.client.diff(None)
        self.assertEqual((EXPECTED_HG_DIFF_0, None), diff_result)

    def testDiffSimpleMultiple(self):
        """Test MercurialClient diff with multiple commits"""
        self.client.get_repository_info()

        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        self._hg_add_file_commit('foo.txt', FOO3, 'commit 3')

        diff_result = self.client.diff(None)

        self.assertEqual((EXPECTED_HG_DIFF_1, None), diff_result)

    def testDiffBranchDiverge(self):
        """Test MercurialClient diff with diverged branch"""
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')

        self._hgcmd(['branch', 'diverged'])
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        self.client.get_repository_info()

        self.assertEqual((EXPECTED_HG_DIFF_2, None), self.client.diff(None))

        self._hgcmd(['update', '-C', 'default'])
        self.client.get_repository_info()

        self.assertEqual((EXPECTED_HG_DIFF_3, None), self.client.diff(None))
Ejemplo n.º 7
0
class MercurialClientTests(SpyAgency, MercurialTestBase):
    """Unit tests for MercurialClient."""

    TESTSERVER = 'http://127.0.0.1:8080'
    CLONE_HGRC = dedent("""
        [ui]
        username = test user <user at example.com>

        [paths]
        default = %(hg_dir)s
        cloned = %(clone_dir)s

        [reviewboard]
        url = %(test_server)s

        [diff]
        git = true
    """).rstrip()

    AUTHOR = type(str('Author'), (object, ), {
        'fullname': 'name',
        'email': 'email',
    })

    def setUp(self):
        super(MercurialClientTests, self).setUp()

        if not is_exe_in_path('hg'):
            raise SkipTest('hg not found in path')

        self.hg_dir = os.path.join(self.testdata_dir, 'hg-repo')
        self.clone_dir = self.chdir_tmp()
        self.clone_hgrc_path = os.path.join(self.clone_dir, '.hg', 'hgrc')

        self.run_hg(['clone', '--stream', self.hg_dir, self.clone_dir])
        self.client = MercurialClient(options=self.options)

        with open(self.clone_hgrc_path, 'w') as fp:
            fp.write(
                self.CLONE_HGRC % {
                    'hg_dir': self.hg_dir,
                    'clone_dir': self.clone_dir,
                    'test_server': self.TESTSERVER,
                })

        self.options.parent_branch = None

    def test_get_repository_info(self):
        """Testing MercurialClient.get_repository_info"""
        ri = self.client.get_repository_info()

        self.assertIsInstance(ri, RepositoryInfo)
        self.assertEqual(ri.base_path, '')

        hgpath = ri.path

        if os.path.basename(hgpath) == '.hg':
            hgpath = os.path.dirname(hgpath)

        self.assertEqual(self.hg_dir, hgpath)
        self.assertTrue(ri.supports_parent_diffs)
        self.assertFalse(ri.supports_changesets)

    def test_scan_for_server(self):
        """Testing MercurialClient.scan_for_server"""
        os.rename(self.clone_hgrc_path,
                  os.path.join(self.clone_dir, '._disabled_hgrc'))

        self.client.hgrc = {}
        self.client._load_hgrc()
        ri = self.client.get_repository_info()

        self.assertIsNone(self.client.scan_for_server(ri))

    def test_scan_for_server_when_present_in_hgrc(self):
        """Testing MercurialClient.scan_for_server when present in hgrc"""
        ri = self.client.get_repository_info()

        self.assertEqual(self.client.scan_for_server(ri), self.TESTSERVER)

    def test_scan_for_server_reviewboardrc(self):
        """Testing MercurialClient.scan_for_server when in .reviewboardrc"""
        with self.reviewboardrc({'REVIEWBOARD_URL': self.TESTSERVER}):
            self.client.config = load_config()
            ri = self.client.get_repository_info()

            self.assertEqual(self.client.scan_for_server(ri), self.TESTSERVER)

    def test_diff(self):
        """Testing MercurialClient.diff"""
        self.hg_add_file_commit(filename='foo.txt',
                                data=FOO1,
                                msg='delete and modify stuff')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)

        self.assertIsInstance(result, dict)
        self.assertIn('diff', result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '68c2bdccf52a4f0baddd0ac9f2ecb7d2')

    def test_diff_with_multiple(self):
        """Testing MercurialClient.diff with multiple commits"""
        self.hg_add_file_commit(filename='foo.txt', data=FOO1, msg='commit 1')
        self.hg_add_file_commit(filename='foo.txt', data=FOO2, msg='commit 2')
        self.hg_add_file_commit(filename='foo.txt', data=FOO3, msg='commit 3')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)

        self.assertIsInstance(result, dict)
        self.assertIn('diff', result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '9c8796936646be5c7349973b0fceacbd')

    def test_diff_with_exclude_patterns(self):
        """Testing MercurialClient.diff with exclude_patterns"""
        self.hg_add_file_commit(filename='foo.txt', data=FOO1, msg='commit 1')
        self.hg_add_file_commit(filename='exclude.txt',
                                data=FOO2,
                                msg='commit 2')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions, exclude_patterns=['exclude.txt'])

        self.assertIsInstance(result, dict)
        self.assertIn('diff', result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '68c2bdccf52a4f0baddd0ac9f2ecb7d2')

    def test_diff_with_exclude_patterns_no_matches(self):
        """Testing MercurialClient.diff with exclude_patterns and no matched
        files
        """
        self.hg_add_file_commit(filename='foo.txt', data=FOO1, msg='commit 1')
        self.hg_add_file_commit(filename='empty.txt', data=b'', msg='commit 2')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions, exclude_patterns=['empty.txt'])

        self.assertIsInstance(revisions, dict)
        self.assertIn('diff', result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '68c2bdccf52a4f0baddd0ac9f2ecb7d2')

    def test_diff_with_diverged_branch(self):
        """Testing MercurialClient.diff with diverged branch"""
        self.hg_add_file_commit(filename='foo.txt', data=FOO1, msg='commit 1')

        self.run_hg(['branch', 'diverged'])
        self.hg_add_file_commit(filename='foo.txt', data=FOO2, msg='commit 2')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)

        self.assertIsInstance(result, dict)
        self.assertIn('diff', result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '6b12723baab97f346aa938005bc4da4d')

        self.run_hg(['update', '-C', 'default'])

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)

        self.assertIsInstance(result, dict)
        self.assertIn('diff', result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '68c2bdccf52a4f0baddd0ac9f2ecb7d2')

    def test_diff_with_parent_diff(self):
        """Testing MercurialClient.diff with parent diffs"""
        self.hg_add_file_commit(filename='foo.txt', data=FOO1, msg='commit 1')
        self.hg_add_file_commit(filename='foo.txt', data=FOO2, msg='commit 2')
        self.hg_add_file_commit(filename='foo.txt', data=FOO3, msg='commit 3')

        revisions = self.client.parse_revision_spec(['2', '3'])
        result = self.client.diff(revisions)

        self.assertIsInstance(result, dict)
        self.assertIn('parent_diff', result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '7a897f68a9dc034fc1e42fe7a33bb808')
        self.assertEqual(
            md5(result['parent_diff']).hexdigest(),
            '5cacbd79800a9145f982dcc0908b6068')

    def test_diff_with_parent_diff_and_diverged_branch(self):
        """Testing MercurialClient.diff with parent diffs and diverged branch
        """
        # This test is very similar to test_diff_with_parent_diff except we
        # throw a branch into the mix.
        self.hg_add_file_commit(filename='foo.txt', data=FOO1, msg='commit 1')
        self.run_hg(['branch', 'diverged'])
        self.hg_add_file_commit(filename='foo.txt', data=FOO2, msg='commit 2')
        self.hg_add_file_commit(filename='foo.txt', data=FOO3, msg='commit 3')

        revisions = self.client.parse_revision_spec(['2', '3'])
        result = self.client.diff(revisions)

        self.assertIn('parent_diff', result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '7a897f68a9dc034fc1e42fe7a33bb808')
        self.assertEqual(
            md5(result['parent_diff']).hexdigest(),
            '5cacbd79800a9145f982dcc0908b6068')

    def test_diff_with_parent_diff_using_option(self):
        """Testing MercurialClient.diff with parent diffs using --parent"""
        # This test is very similar to test_diff_with_parent_diff except we
        # use the --parent option to post without explicit revisions
        self.hg_add_file_commit(filename='foo.txt', data=FOO1, msg='commit 1')
        self.hg_add_file_commit(filename='foo.txt', data=FOO2, msg='commit 2')
        self.hg_add_file_commit(filename='foo.txt', data=FOO3, msg='commit 3')

        self.options.parent_branch = '2'

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)

        self.assertIsInstance(result, dict)
        self.assertIn('parent_diff', result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '7a897f68a9dc034fc1e42fe7a33bb808')
        self.assertEqual(
            md5(result['parent_diff']).hexdigest(),
            '5cacbd79800a9145f982dcc0908b6068')

    def test_parse_revision_spec_with_no_args(self):
        """Testing MercurialClient.parse_revision_spec with no arguments"""
        base = self._hg_get_tip()
        self.hg_add_file_commit(filename='foo.txt', data=FOO1, msg='commit 1')
        self.hg_add_file_commit(filename='foo.txt', data=FOO2, msg='commit 2')

        tip = self._hg_get_tip()
        revisions = self.client.parse_revision_spec([])

        self.assertIsInstance(revisions, dict)
        self.assertIn('base', revisions)
        self.assertIn('tip', revisions)
        self.assertNotIn('parent_base', revisions)
        self.assertEqual(revisions['base'], base)
        self.assertEqual(revisions['tip'], tip)

    def test_parse_revision_spec_with_one_arg_periods(self):
        """Testing MercurialClient.parse_revision_spec with r1..r2 syntax"""
        base = self._hg_get_tip()
        self.hg_add_file_commit(filename='foo.txt', data=FOO1, msg='commit 1')

        tip = self._hg_get_tip()
        revisions = self.client.parse_revision_spec(['0..1'])

        self.assertIsInstance(revisions, dict)
        self.assertIn('base', revisions)
        self.assertIn('tip', revisions)
        self.assertNotIn('parent_base', revisions)
        self.assertEqual(revisions['base'], base)
        self.assertEqual(revisions['tip'], tip)

    def test_parse_revision_spec_with_one_arg_colons(self):
        """Testing MercurialClient.parse_revision_spec with r1::r2 syntax"""
        base = self._hg_get_tip()
        self.hg_add_file_commit(filename='foo.txt', data=FOO1, msg='commit 1')

        tip = self._hg_get_tip()
        revisions = self.client.parse_revision_spec(['0..1'])

        self.assertIsInstance(revisions, dict)
        self.assertIn('base', revisions)
        self.assertIn('tip', revisions)
        self.assertNotIn('parent_base', revisions)
        self.assertEqual(revisions['base'], base)
        self.assertEqual(revisions['tip'], tip)

    def test_parse_revision_spec_with_one_arg(self):
        """Testing MercurialClient.parse_revision_spec with one revision"""
        base = self._hg_get_tip()
        self.hg_add_file_commit(filename='foo.txt', data=FOO1, msg='commit 1')
        tip = self._hg_get_tip()
        self.hg_add_file_commit(filename='foo.txt', data=FOO2, msg='commit 2')

        revisions = self.client.parse_revision_spec(['1'])

        self.assertIsInstance(revisions, dict)
        self.assertIn('base', revisions)
        self.assertIn('tip', revisions)
        self.assertNotIn('parent_base', revisions)
        self.assertEqual(revisions['base'], base)
        self.assertEqual(revisions['tip'], tip)

    def test_parse_revision_spec_with_two_args(self):
        """Testing MercurialClient.parse_revision_spec with two revisions"""
        base = self._hg_get_tip()
        self.hg_add_file_commit(filename='foo.txt', data=FOO1, msg='commit 1')
        self.hg_add_file_commit(filename='foo.txt', data=FOO2, msg='commit 2')
        tip = self._hg_get_tip()

        revisions = self.client.parse_revision_spec(['0', '2'])

        self.assertIsInstance(revisions, dict)
        self.assertIn('base', revisions)
        self.assertIn('tip', revisions)
        self.assertNotIn('parent_base', revisions)
        self.assertEqual(revisions['base'], base)
        self.assertEqual(revisions['tip'], tip)

    def test_parse_revision_spec_with_parent_base(self):
        """Testing MercurialClient.parse_revision_spec with parent base"""
        start_base = self._hg_get_tip()
        self.hg_add_file_commit(filename='foo.txt', data=FOO1, msg='commit 1')
        commit1 = self._hg_get_tip()
        self.hg_add_file_commit(filename='foo.txt', data=FOO2, msg='commit 2')
        commit2 = self._hg_get_tip()
        self.hg_add_file_commit(filename='foo.txt', data=FOO3, msg='commit 3')
        commit3 = self._hg_get_tip()
        self.hg_add_file_commit(filename='foo.txt', data=FOO4, msg='commit 4')
        commit4 = self._hg_get_tip()
        self.hg_add_file_commit(filename='foo.txt', data=FOO5, msg='commit 5')

        self.assertEqual(self.client.parse_revision_spec(['1', '2']), {
            'base': commit1,
            'tip': commit2,
            'parent_base': start_base,
        })

        self.assertEqual(
            self.client.parse_revision_spec(['4']), {
                'base': commit3,
                'tip': commit4,
                'parent_base': start_base,
                'commit_id': commit4,
            })

        self.assertEqual(self.client.parse_revision_spec(['2', '4']), {
            'base': commit2,
            'tip': commit4,
            'parent_base': start_base,
        })

    def test_get_hg_ref_type(self):
        """Testing MercurialClient.get_hg_ref_type"""
        self.hg_add_file_commit(branch='test-branch',
                                bookmark='test-bookmark',
                                tag='test-tag')
        tip = self._hg_get_tip()

        self.assertEqual(self.client.get_hg_ref_type('test-branch'),
                         MercurialRefType.BRANCH)
        self.assertEqual(self.client.get_hg_ref_type('test-bookmark'),
                         MercurialRefType.BOOKMARK)
        self.assertEqual(self.client.get_hg_ref_type('test-tag'),
                         MercurialRefType.TAG)
        self.assertEqual(self.client.get_hg_ref_type(tip),
                         MercurialRefType.REVISION)
        self.assertEqual(self.client.get_hg_ref_type('something-invalid'),
                         MercurialRefType.UNKNOWN)

    def test_get_commit_message_with_one_commit_in_range(self):
        """Testing MercurialClient.get_commit_message with range containing
        only one commit
        """
        self.options.guess_summary = True
        self.options.guess_description = True

        self.hg_add_file_commit(filename='foo.txt', data=FOO1, msg='commit 1')

        revisions = self.client.parse_revision_spec([])
        commit_message = self.client.get_commit_message(revisions)

        self.assertEqual(commit_message['summary'], 'commit 1')

    def test_get_commit_message_with_commit_range(self):
        """Testing MercurialClient.get_commit_message with commit range"""
        self.options.guess_summary = True
        self.options.guess_description = True

        self.hg_add_file_commit(filename='foo.txt',
                                data=FOO1,
                                msg='commit 1\n\ndesc1')
        self.hg_add_file_commit(filename='foo.txt',
                                data=FOO2,
                                msg='commit 2\n\ndesc2')
        self.hg_add_file_commit(filename='foo.txt',
                                data=FOO3,
                                msg='commit 3\n\ndesc3')

        revisions = self.client.parse_revision_spec([])
        commit_message = self.client.get_commit_message(revisions)

        self.assertEqual(commit_message['summary'], 'commit 1')
        self.assertEqual(commit_message['description'],
                         'desc1\n\ncommit 2\n\ndesc2\n\ncommit 3\n\ndesc3')

    def test_get_commit_message_with_specific_commit(self):
        """Testing MercurialClient.get_commit_message with specific commit"""
        self.options.guess_summary = True
        self.options.guess_description = True

        self.hg_add_file_commit(filename='foo.txt',
                                data=FOO1,
                                msg='commit 1\n\ndesc1')
        self.hg_add_file_commit(filename='foo.txt',
                                data=FOO2,
                                msg='commit 2\n\ndesc2')
        tip = self._hg_get_tip()
        self.hg_add_file_commit(filename='foo.txt',
                                data=FOO3,
                                msg='commit 3\n\ndesc3')

        revisions = self.client.parse_revision_spec([tip])
        commit_message = self.client.get_commit_message(revisions)

        self.assertEqual(commit_message['summary'], 'commit 2')
        self.assertEqual(commit_message['description'], 'desc2')

    def test_create_commit_with_run_editor_true(self):
        """Testing MercurialClient.create_commit with run_editor set to True"""
        self.spy_on(self.client._execute)

        with open('foo.txt', 'w') as fp:
            fp.write('change')

        self.client.create_commit(message='Test commit message.',
                                  author=self.AUTHOR,
                                  run_editor=True,
                                  files=['foo.txt'])

        self.assertTrue(
            self.client._execute.last_called_with([
                'hg', 'commit', '-m', 'TEST COMMIT MESSAGE.', '-u',
                'name <email>', 'foo.txt'
            ]))

    def test_create_commit_with_run_editor_false(self):
        """Testing MercurialClient.create_commit with run_editor set to False
        """
        self.spy_on(self.client._execute)

        with open('foo.txt', 'w') as fp:
            fp.write('change')

        self.client.create_commit(message='Test commit message.',
                                  author=self.AUTHOR,
                                  run_editor=False,
                                  files=['foo.txt'])

        self.assertTrue(
            self.client._execute.last_called_with([
                'hg', 'commit', '-m', 'Test commit message.', '-u',
                'name <email>', 'foo.txt'
            ]))

    def test_create_commit_with_all_files_true(self):
        """Testing MercurialClient.create_commit with all_files set to True"""
        self.spy_on(self.client._execute)

        with open('foo.txt', 'w') as fp:
            fp.write('change')

        self.client.create_commit(message='message',
                                  author=self.AUTHOR,
                                  run_editor=False,
                                  files=[],
                                  all_files=True)

        self.assertTrue(
            self.client._execute.last_called_with(
                ['hg', 'commit', '-m', 'message', '-u', 'name <email>', '-A']))

    def test_create_commit_with_all_files_false(self):
        """Testing MercurialClient.create_commit with all_files set to False"""
        self.spy_on(self.client._execute)

        with open('foo.txt', 'w') as fp:
            fp.write('change')

        self.client.create_commit(message='message',
                                  author=self.AUTHOR,
                                  run_editor=False,
                                  files=['foo.txt'],
                                  all_files=False)

        self.assertTrue(
            self.client._execute.last_called_with([
                'hg', 'commit', '-m', 'message', '-u', 'name <email>',
                'foo.txt'
            ]))

    def test_create_commit_with_empty_commit_message(self):
        """Testing MercurialClient.create_commit with empty commit message"""
        with open('foo.txt', 'w') as fp:
            fp.write('change')

        message = (
            "A commit message wasn't provided. The patched files are in "
            "your tree but haven't been committed.")

        with self.assertRaisesMessage(CreateCommitError, message):
            self.client.create_commit(message='',
                                      author=self.AUTHOR,
                                      run_editor=True,
                                      files=['foo.txt'])

    def test_create_commit_without_author(self):
        """Testing MercurialClient.create_commit without author information"""
        self.spy_on(self.client._execute)

        with open('foo.txt', 'w') as fp:
            fp.write('change')

        self.client.create_commit(message='Test commit message.',
                                  author=None,
                                  run_editor=True,
                                  files=['foo.txt'])

        self.assertTrue(
            self.client._execute.last_called_with(
                ['hg', 'commit', '-m', 'TEST COMMIT MESSAGE.', 'foo.txt']))

    def test_merge_with_branch_and_close_branch_false(self):
        """Testing MercurialClient.merge with target branch and
        close_branch=False
        """
        self.hg_add_file_commit(branch='test-branch')

        self.spy_on(self.client._execute)
        self.client.merge(target='test-branch',
                          destination='default',
                          message='My merge commit',
                          author=self.AUTHOR,
                          close_branch=False)

        calls = self.client._execute.calls
        self.assertEqual(len(calls), 5)
        self.assertTrue(calls[0].called_with(
            ['hg', 'log', '-ql1', '-r', 'bookmark(test-branch)']))
        self.assertTrue(calls[1].called_with(['hg', 'branches', '-q']))
        self.assertTrue(calls[2].called_with(['hg', 'update', 'default']))
        self.assertTrue(calls[3].called_with(['hg', 'merge', 'test-branch']))
        self.assertTrue(calls[4].called_with(
            ['hg', 'commit', '-m', 'My merge commit', '-u', 'name <email>']))

    def test_merge_with_branch_and_close_branch_true(self):
        """Testing MercurialClient.merge with target branch and
        close_branch=True
        """
        self.hg_add_file_commit(branch='test-branch')

        self.spy_on(self.client._execute)
        self.client.merge(target='test-branch',
                          destination='default',
                          message='My merge commit',
                          author=self.AUTHOR,
                          close_branch=True)

        calls = self.client._execute.calls
        self.assertEqual(len(calls), 7)
        self.assertTrue(calls[0].called_with(
            ['hg', 'log', '-ql1', '-r', 'bookmark(test-branch)']))
        self.assertTrue(calls[1].called_with(['hg', 'branches', '-q']))
        self.assertTrue(calls[2].called_with(['hg', 'update', 'test-branch']))
        self.assertTrue(calls[3].called_with(
            ['hg', 'commit', '-m', 'My merge commit', '--close-branch']))
        self.assertTrue(calls[4].called_with(['hg', 'update', 'default']))
        self.assertTrue(calls[5].called_with(['hg', 'merge', 'test-branch']))
        self.assertTrue(calls[6].called_with(
            ['hg', 'commit', '-m', 'My merge commit', '-u', 'name <email>']))

    def test_merge_with_bookmark_and_close_branch_false(self):
        """Testing MercurialClient.merge with target bookmark and
        close_branch=False
        """
        self.run_hg(['branch', 'feature-work'])
        self.hg_add_file_commit(bookmark='test-bookmark')

        self.spy_on(self.client._execute)
        self.client.merge(target='test-bookmark',
                          destination='default',
                          message='My merge commit',
                          author=self.AUTHOR,
                          close_branch=False)

        calls = self.client._execute.calls
        self.assertEqual(len(calls), 4)
        self.assertTrue(calls[0].called_with(
            ['hg', 'log', '-ql1', '-r', 'bookmark(test-bookmark)']))
        self.assertTrue(calls[1].called_with(['hg', 'update', 'default']))
        self.assertTrue(calls[2].called_with(['hg', 'merge', 'test-bookmark']))
        self.assertTrue(calls[3].called_with(
            ['hg', 'commit', '-m', 'My merge commit', '-u', 'name <email>']))

    def test_merge_with_bookmark_and_close_branch_true(self):
        """Testing MercurialClient.merge with target bookmark and
        close_branch=True
        """
        self.run_hg(['branch', 'feature-work'])
        self.hg_add_file_commit(bookmark='test-bookmark')

        self.spy_on(self.client._execute)
        self.client.merge(target='test-bookmark',
                          destination='default',
                          message='My merge commit',
                          author=self.AUTHOR,
                          close_branch=True)

        calls = self.client._execute.calls
        self.assertEqual(len(calls), 5)
        self.assertTrue(calls[0].called_with(
            ['hg', 'log', '-ql1', '-r', 'bookmark(test-bookmark)']))
        self.assertTrue(calls[1].called_with(['hg', 'update', 'default']))
        self.assertTrue(calls[2].called_with(['hg', 'merge', 'test-bookmark']))
        self.assertTrue(calls[3].called_with(
            ['hg', 'commit', '-m', 'My merge commit', '-u', 'name <email>']))
        self.assertTrue(calls[4].called_with(
            ['hg', 'bookmark', '-d', 'test-bookmark']))

    def test_merge_with_tag(self):
        """Testing MercurialClient.merge with target tag"""
        self.run_hg(['branch', 'feature-work'])
        self.hg_add_file_commit(tag='test-tag')

        self.spy_on(self.client._execute)
        self.client.merge(target='test-tag',
                          destination='default',
                          message='My merge commit',
                          author=self.AUTHOR,
                          close_branch=True)

        calls = self.client._execute.calls
        self.assertEqual(len(calls), 6)
        self.assertTrue(calls[0].called_with(
            ['hg', 'log', '-ql1', '-r', 'bookmark(test-tag)']))
        self.assertTrue(calls[1].called_with(['hg', 'branches', '-q']))
        self.assertTrue(calls[2].called_with(
            ['hg', 'log', '-ql1', '-r', 'tag(test-tag)']))
        self.assertTrue(calls[3].called_with(['hg', 'update', 'default']))
        self.assertTrue(calls[4].called_with(['hg', 'merge', 'test-tag']))
        self.assertTrue(calls[5].called_with(
            ['hg', 'commit', '-m', 'My merge commit', '-u', 'name <email>']))

    def test_merge_with_revision(self):
        """Testing MercurialClient.merge with target revision"""
        self.run_hg(['branch', 'feature-work'])
        self.hg_add_file_commit()
        tip = self._hg_get_tip()

        self.spy_on(self.client._execute)
        self.client.merge(target=tip,
                          destination='default',
                          message='My merge commit',
                          author=self.AUTHOR,
                          close_branch=True)

        calls = self.client._execute.calls
        self.assertEqual(len(calls), 7)
        self.assertTrue(calls[0].called_with(
            ['hg', 'log', '-ql1', '-r',
             'bookmark(%s)' % tip]))
        self.assertTrue(calls[1].called_with(['hg', 'branches', '-q']))
        self.assertTrue(calls[2].called_with(
            ['hg', 'log', '-ql1', '-r',
             'tag(%s)' % tip]))
        self.assertTrue(calls[3].called_with(['hg', 'identify', '-r', tip]))
        self.assertTrue(calls[4].called_with(['hg', 'update', 'default']))
        self.assertTrue(calls[5].called_with(['hg', 'merge', tip]))
        self.assertTrue(calls[6].called_with(
            ['hg', 'commit', '-m', 'My merge commit', '-u', 'name <email>']))

    def test_merge_with_invalid_target(self):
        """Testing MercurialClient.merge with an invalid target"""
        expected_message = (
            'Could not find a valid branch, tag, bookmark, or revision called '
            '"invalid".')

        with self.assertRaisesMessage(MergeError, expected_message):
            self.client.merge(target='invalid',
                              destination='default',
                              message='commit message',
                              author=self.AUTHOR)

    def test_merge_with_invalid_destination(self):
        """Testing MercurialClient.merge with an invalid destination branch"""
        expected_message = 'Could not switch to branch "non-existent-branch".'

        with self.assertRaisesMessage(MergeError, expected_message):
            self.client.merge(target='default',
                              destination='non-existent-branch',
                              message='commit message',
                              author=self.AUTHOR)

    def _hg_get_tip(self):
        """Return the revision at the tip of the branch.

        Returns:
            unicode:
            The tip revision.
        """
        return force_unicode(self.run_hg(['identify']).split()[0])
Ejemplo n.º 8
0
class MercurialSubversionClientTests(MercurialTestBase):
    """Unit tests for hgsubversion."""

    TESTSERVER = 'http://127.0.0.1:8080'

    SVNSERVE_MAX_RETRIES = 12

    _svnserve_pid = None
    _svn_temp_base_path = None
    _skip_reason = None

    @classmethod
    def setUpClass(cls):
        for exe in ('svnadmin', 'svnserve', 'svn'):
            if not is_exe_in_path(exe):
                cls._skip_reason = '%s is not available on the system.' % exe
                break
        else:
            has_hgsubversion = False

            try:
                output = execute([
                    'hg', '--config', 'extensions.hgsubversion=', 'svn',
                    '--help'
                ],
                                 ignore_errors=True,
                                 extra_ignore_errors=(255, ))
                has_hgsubversion = \
                    not re.search('unknown command [\'"]svn[\'"]',
                                  output, re.I)
            except OSError:
                has_hgsubversion = False

            if not has_hgsubversion:
                cls._skip_reason = \
                    'hgsubversion is not available or cannot be used.'

        super(MercurialSubversionClientTests, cls).setUpClass()

        # Don't do any of the following expensive stuff if we know we're just
        # going to skip all the tests.
        if cls._skip_reason:
            return

        # Create the repository that we'll be populating and later cloning.
        temp_base_path = tempfile.mkdtemp(prefix='rbtools.')
        cls._svn_temp_base_path = temp_base_path

        svn_repo_path = os.path.join(temp_base_path, 'svnrepo')
        execute(['svnadmin', 'create', svn_repo_path])

        # Fill it with content. First, though, we have to clone it.
        svn_checkout_path = os.path.join(temp_base_path, 'checkout.svn')
        execute([
            'svn', 'checkout',
            'file://%s' % svn_repo_path, svn_checkout_path
        ])
        os.chdir(svn_checkout_path)

        execute([
            'svn', 'propset', 'reviewboard:url', cls.TESTSERVER,
            svn_checkout_path
        ])
        execute(['svn', 'mkdir', 'trunk', 'branches', 'tags'])
        execute(['svn', 'commit', '-m', 'Initial commit.'])
        os.chdir(os.path.join(svn_checkout_path, 'trunk'))

        for i, data in enumerate([FOO, FOO1, FOO2]):
            cls.svn_add_file_commit(filename='foo.txt',
                                    data=data,
                                    msg='Test commit %s' % i,
                                    add_file=(i == 0))

        # Launch svnserve so Mercurial can pull from it.
        svnserve_port = (os.environ.get('SVNSERVE_PORT')
                         or str(randint(30000, 40000)))

        pid_file = os.path.join(temp_base_path, 'svnserve.pid')
        execute([
            'svnserve', '--single-thread', '--pid-file', pid_file, '-d',
            '--listen-port', svnserve_port, '-r', temp_base_path
        ])

        for i in range(0, cls.SVNSERVE_MAX_RETRIES):
            try:
                cls._svnserve_pid = int(open(pid_file).read().strip())
            except (IOError, OSError):
                # Wait to see if svnserve has launched yet.
                time.sleep(0.25)

        if not cls._svnserve_pid:
            raise cls.failureException('Unable to launch svnserve on port %s' %
                                       svnserve_port)

        cls.svn_checkout_url = 'svn://127.0.0.1:%s/svnrepo' % svnserve_port

    @classmethod
    def tearDownClass(cls):
        if cls._svnserve_pid:
            os.kill(cls._svnserve_pid, 9)

        if cls._svn_temp_base_path:
            shutil.rmtree(cls._svn_temp_base_path, ignore_errors=True)

        super(MercurialSubversionClientTests, cls).tearDownClass()

    def setUp(self):
        super(MercurialSubversionClientTests, self).setUp()

        if self._skip_reason:
            raise SkipTest(self._skip_reason)

        home_dir = self.get_user_home()
        hgrc_path = os.path.join(home_dir, '.hgrc')

        # Make sure hgsubversion is enabled.
        #
        # This will modify the .hgrc in the temp home directory created for
        # these tests.
        #
        # The "hgsubversion =" tells Mercurial to check for hgsubversion in
        # the default PYTHONPATH
        with open(hgrc_path, 'w') as fp:
            fp.write('[extensions]\n')
            fp.write('hgsubversion =\n')

        try:
            self.clone_dir = os.path.join(home_dir, 'checkout.hg')
            self.run_hg(
                ['clone', '--stream', self.svn_checkout_url, self.clone_dir])
        except (OSError, IOError) as e:
            self.fail('Unable to clone Subversion repository: %s' % e)

        os.chdir(self.clone_dir)
        self.options.parent_branch = None
        self.client = MercurialClient(options=self.options)

    @classmethod
    def svn_add_file_commit(self, filename, data, msg, add_file=True):
        with open(filename, 'wb') as fp:
            fp.write(data)

        if add_file:
            execute(['svn', 'add', filename], ignore_errors=True)

        execute(['svn', 'commit', '-m', msg])

    def test_get_repository_info(self):
        """Testing MercurialClient.get_repository_info with SVN"""
        ri = self.client.get_repository_info()

        self.assertEqual(self.client._type, 'svn')
        self.assertEqual(ri.base_path, '/trunk')
        self.assertEqual(ri.path, self.svn_checkout_url)

    def test_calculate_repository_info(self):
        """Testing MercurialClient._calculate_hgsubversion_repository_info
        with SVN determines repository and base paths
        """
        repo_info = self.client._calculate_hgsubversion_repository_info(
            'URL: svn+ssh://[email protected]/repo/trunk\n'
            'Repository Root: svn+ssh://[email protected]/repo\n'
            'Repository UUID: bfddb570-5023-0410-9bc8-bc1659bf7c01\n'
            'Revision: 9999\n'
            'Node Kind: directory\n'
            'Last Changed Author: user\n'
            'Last Changed Rev: 9999\n'
            'Last Changed Date: 2012-09-05 18:04:28 +0000 (Wed, 05 Sep 2012)')

        self.assertEqual(repo_info.path, 'svn+ssh://svn.example.net/repo')
        self.assertEqual(repo_info.base_path, '/trunk')

    def test_scan_for_server_with_reviewboardrc(self):
        """Testing MercurialClient.scan_for_server with SVN and configured
        .reviewboardrc
        """
        with self.reviewboardrc({'REVIEWBOARD_URL': 'https://example.com/'}):
            self.client.config = load_config()
            ri = self.client.get_repository_info()

            self.assertEqual(self.client.scan_for_server(ri),
                             'https://example.com/')

    def test_scan_for_server_with_property(self):
        """Testing MercurialClient.scan_for_server with SVN and reviewboard:url
        property
        """
        ri = self.client.get_repository_info()

        self.assertEqual(self.client.scan_for_server(ri), self.TESTSERVER)

    def test_diff(self):
        """Testing MercurialClient.diff with SVN"""
        self.client.get_repository_info()

        self.hg_add_file_commit(filename='foo.txt', data=FOO4, msg='edit 4')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)

        self.assertIsInstance(result, dict)
        self.assertIn('diff', result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '2eb0a5f2149232c43a1745d90949fcd5')
        self.assertIsNone(result['parent_diff'])

    def test_diff_with_multiple_commits(self):
        """Testing MercurialClient.diff with SVN and multiple commits"""
        self.client.get_repository_info()

        self.hg_add_file_commit(filename='foo.txt', data=FOO4, msg='edit 4')
        self.hg_add_file_commit(filename='foo.txt', data=FOO5, msg='edit 5')
        self.hg_add_file_commit(filename='foo.txt', data=FOO6, msg='edit 6')

        revisions = self.client.parse_revision_spec([])
        result = self.client.diff(revisions)

        self.assertIsInstance(result, dict)
        self.assertIn('diff', result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '3d007394de3831d61e477cbcfe60ece8')
        self.assertIsNone(result['parent_diff'])

    def test_diff_with_revision(self):
        """Testing MercurialClient.diff with SVN and specific revision"""
        self.client.get_repository_info()

        self.hg_add_file_commit(filename='foo.txt',
                                data=FOO4,
                                msg='edit 4',
                                branch='b')
        self.hg_add_file_commit(filename='foo.txt',
                                data=FOO5,
                                msg='edit 5',
                                branch='b')
        self.hg_add_file_commit(filename='foo.txt',
                                data=FOO6,
                                msg='edit 6',
                                branch='b')
        self.hg_add_file_commit(filename='foo.txt',
                                data=FOO4,
                                msg='edit 7',
                                branch='b')

        revisions = self.client.parse_revision_spec(['3'])
        result = self.client.diff(revisions)

        self.assertIsInstance(result, dict)
        self.assertIn('diff', result)
        self.assertEqual(
            md5(result['diff']).hexdigest(),
            '2eb0a5f2149232c43a1745d90949fcd5')
        self.assertIsNone(result['parent_diff'])
Ejemplo n.º 9
0
class MercurialClientTests(MercurialTestBase):
    TESTSERVER = 'http://127.0.0.1:8080'
    CLONE_HGRC = dedent("""
    [paths]
    default = %(hg_dir)s
    cloned = %(clone_dir)s

    [reviewboard]
    url = %(test_server)s

    [diff]
    git = true
    """).rstrip()

    def setUp(self):
        super(MercurialClientTests, self).setUp()
        if not self.is_exe_in_path('hg'):
            raise SkipTest('hg not found in path')

        self.hg_dir = self.chdir_tmp()
        self._hgcmd(['init'], hg_dir=self.hg_dir)
        foo = open(os.path.join(self.hg_dir, 'foo.txt'), 'w')
        foo.write(FOO)
        foo.close()

        self._hgcmd(['add', 'foo.txt'])
        self._hgcmd(['commit', '-m', 'initial commit'])

        self.clone_dir = self.chdir_tmp(self.hg_dir)
        self._hgcmd(['clone', self.hg_dir, self.clone_dir])
        self.client = MercurialClient(options=self.options)

        clone_hgrc = open(self.clone_hgrc_path, 'wb')
        clone_hgrc.write(self.CLONE_HGRC % {
            'hg_dir': self.hg_dir,
            'clone_dir': self.clone_dir,
            'test_server': self.TESTSERVER,
        })
        clone_hgrc.close()

        self.client.get_repository_info()
        self.user_config = {}
        self.configs = []
        self.client.user_config = self.user_config
        self.client.configs = self.configs
        self.options.parent_branch = None

    @property
    def clone_hgrc_path(self):
        return os.path.join(self.clone_dir, '.hg', 'hgrc')

    @property
    def hgrc_path(self):
        return os.path.join(self.hg_dir, '.hg', 'hgrc')

    def testGetRepositoryInfoSimple(self):
        """Test MercurialClient get_repository_info, simple case"""
        ri = self.client.get_repository_info()

        self.assertTrue(isinstance(ri, RepositoryInfo))
        self.assertEqual('', ri.base_path)

        hgpath = ri.path

        if os.path.basename(hgpath) == '.hg':
            hgpath = os.path.dirname(hgpath)

        self.assertEqual(self.hg_dir, hgpath)
        self.assertTrue(ri.supports_parent_diffs)
        self.assertFalse(ri.supports_changesets)

    def testScanForServerSimple(self):
        """Test MercurialClient scan_for_server, simple case"""
        os.rename(self.clone_hgrc_path,
            os.path.join(self.clone_dir, '._disabled_hgrc'))

        self.client.hgrc = {}
        self.client._load_hgrc()
        ri = self.client.get_repository_info()

        server = self.client.scan_for_server(ri)
        self.assertTrue(server is None)

    def testScanForServerWhenPresentInHgrc(self):
        """Test MercurialClient scan_for_server when present in hgrc"""
        ri = self.client.get_repository_info()

        server = self.client.scan_for_server(ri)
        self.assertEqual(self.TESTSERVER, server)

    def testScanForServerReviewboardrc(self):
        """Test MercurialClient scan_for_server when in .reviewboardrc"""
        rc = open(os.path.join(self.clone_dir, '.reviewboardrc'), 'w')
        rc.write('REVIEWBOARD_URL = "%s"' % self.TESTSERVER)
        rc.close()

        ri = self.client.get_repository_info()
        server = self.client.scan_for_server(ri)
        self.assertEqual(self.TESTSERVER, server)

    def testDiffSimple(self):
        """Test MercurialClient diff, simple case"""
        self.client.get_repository_info()

        self._hg_add_file_commit('foo.txt', FOO1, 'delete and modify stuff')

        diff_result = self.client.diff(None)
        self.assertEqual((EXPECTED_HG_DIFF_0, None), diff_result)

    def testDiffSimpleMultiple(self):
        """Test MercurialClient diff with multiple commits"""
        self.client.get_repository_info()

        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        self._hg_add_file_commit('foo.txt', FOO3, 'commit 3')

        diff_result = self.client.diff(None)

        self.assertEqual((EXPECTED_HG_DIFF_1, None), diff_result)

    def testDiffBranchDiverge(self):
        """Test MercurialClient diff with diverged branch"""
        self._hg_add_file_commit('foo.txt', FOO1, 'commit 1')

        self._hgcmd(['branch', 'diverged'])
        self._hg_add_file_commit('foo.txt', FOO2, 'commit 2')
        self.client.get_repository_info()

        self.assertEqual((EXPECTED_HG_DIFF_2, None), self.client.diff(None))

        self._hgcmd(['update', '-C', 'default'])
        self.client.get_repository_info()

        self.assertEqual((EXPECTED_HG_DIFF_3, None), self.client.diff(None))
Ejemplo n.º 10
0
class MercurialSubversionClientTests(MercurialTestBase):
    TESTSERVER = "http://127.0.0.1:8080"

    def __init__(self, *args, **kwargs):
        self._tmpbase = ''
        self.clone_dir = ''
        self.svn_repo = ''
        self.svn_checkout = ''
        self.client = None
        self._svnserve_pid = 0
        self._max_svnserve_pid_tries = 12
        self._svnserve_port = os.environ.get('SVNSERVE_PORT')
        self._required_exes = ('svnadmin', 'svnserve', 'svn')
        MercurialTestBase.__init__(self, *args, **kwargs)

    def setUp(self):
        super(MercurialSubversionClientTests, self).setUp()
        self._hg_env = {'FOO': 'BAR'}

        for exe in self._required_exes:
            if not self.is_exe_in_path(exe):
                raise SkipTest('missing svn stuff!  giving up!')

        if not self._has_hgsubversion():
            raise SkipTest('unable to use `hgsubversion` extension!  '
                           'giving up!')

        if not self._tmpbase:
            self._tmpbase = self.create_tmp_dir()

        self._create_svn_repo()
        self._fire_up_svnserve()
        self._fill_in_svn_repo()

        try:
            self._get_testing_clone()
        except (OSError, IOError):
            msg = 'could not clone from svn repo!  skipping...'
            raise SkipTest(msg), None, sys.exc_info()[2]

        self._spin_up_client()
        self._stub_in_config_and_options()

    def _has_hgsubversion(self):
        output = self._hgcmd(['svn', '--help'],
                             ignore_errors=True,
                             extra_ignore_errors=(255))

        return not re.search("unknown command ['\"]svn['\"]", output, re.I)

    def tearDown(self):
        os.kill(self._svnserve_pid, 9)

    def _svn_add_file_commit(self, filename, data, msg):
        outfile = open(filename, 'w')
        outfile.write(data)
        outfile.close()
        execute(['svn', 'add', filename])
        execute(['svn', 'commit', '-m', msg])

    def _create_svn_repo(self):
        self.svn_repo = os.path.join(self._tmpbase, 'svnrepo')
        execute(['svnadmin', 'create', self.svn_repo])

    def _fire_up_svnserve(self):
        if not self._svnserve_port:
            self._svnserve_port = str(randint(30000, 40000))

        pid_file = os.path.join(self._tmpbase, 'svnserve.pid')
        execute([
            'svnserve', '--pid-file', pid_file, '-d', '--listen-port',
            self._svnserve_port, '-r', self._tmpbase
        ])

        for i in range(0, self._max_svnserve_pid_tries):
            try:
                self._svnserve_pid = int(open(pid_file).read().strip())
                return

            except (IOError, OSError):
                time.sleep(0.25)

        # This will re-raise the last exception, which will be either
        # IOError or OSError if the above fails and this branch is reached
        raise

    def _fill_in_svn_repo(self):
        self.svn_checkout = os.path.join(self._tmpbase, 'checkout.svn')
        execute([
            'svn', 'checkout',
            'file://%s' % self.svn_repo, self.svn_checkout
        ])
        os.chdir(self.svn_checkout)

        for subtree in ('trunk', 'branches', 'tags'):
            execute(['svn', 'mkdir', subtree])

        execute(['svn', 'commit', '-m', 'filling in T/b/t'])
        os.chdir(os.path.join(self.svn_checkout, 'trunk'))

        for i, data in enumerate([FOO, FOO1, FOO2]):
            self._svn_add_file_commit('foo.txt', data, 'foo commit %s' % i)

    def _get_testing_clone(self):
        self.clone_dir = os.path.join(self._tmpbase, 'checkout.hg')
        self._hgcmd([
            'clone',
            'svn://127.0.0.1:%s/svnrepo' % self._svnserve_port,
            self.clone_dir,
        ])

    def _spin_up_client(self):
        os.chdir(self.clone_dir)
        self.client = MercurialClient(options=self.options)

    def _stub_in_config_and_options(self):
        self.user_config = {}
        self.configs = []
        self.client.user_config = self.user_config
        self.client.configs = self.configs
        self.options.parent_branch = None

    def testGetRepositoryInfoSimple(self):
        """Test MercurialClient (+svn) get_repository_info, simple case"""
        ri = self.client.get_repository_info()

        self.assertEqual('svn', self.client._type)
        self.assertEqual('/trunk', ri.base_path)
        self.assertEqual('svn://127.0.0.1:%s/svnrepo' % self._svnserve_port,
                         ri.path)

    def testScanForServerSimple(self):
        """Test MercurialClient (+svn) scan_for_server, simple case"""
        ri = self.client.get_repository_info()
        server = self.client.scan_for_server(ri)

        self.assertTrue(server is None)

    def testScanForServerReviewboardrc(self):
        """Test MercurialClient (+svn) scan_for_server in .reviewboardrc"""
        rc_filename = os.path.join(self.clone_dir, '.reviewboardrc')
        rc = open(rc_filename, 'w')
        rc.write('REVIEWBOARD_URL = "%s"' % self.TESTSERVER)
        rc.close()
        self.client.user_config, configs = load_config_files(self.clone_dir)

        ri = self.client.get_repository_info()
        server = self.client.scan_for_server(ri)

        self.assertEqual(self.TESTSERVER, server)

    def testScanForServerProperty(self):
        """Test MercurialClient (+svn) scan_for_server in svn property"""
        os.chdir(self.svn_checkout)
        execute(['svn', 'update'])
        execute([
            'svn', 'propset', 'reviewboard:url', self.TESTSERVER,
            self.svn_checkout
        ])
        execute(['svn', 'commit', '-m', 'adding reviewboard:url property'])

        os.chdir(self.clone_dir)
        self._hgcmd(['pull'])
        self._hgcmd(['update', '-C'])

        ri = self.client.get_repository_info()

        self.assertEqual(self.TESTSERVER, self.client.scan_for_server(ri))

    def testDiffSimple(self):
        """Test MercurialClient (+svn) diff, simple case"""
        self.client.get_repository_info()

        self._hg_add_file_commit('foo.txt', FOO4, 'edit 4')

        self.assertEqual(EXPECTED_HG_SVN_DIFF_0, self.client.diff(None)[0])

    def testDiffSimpleMultiple(self):
        """Test MercurialClient (+svn) diff with multiple commits"""
        self.client.get_repository_info()

        self._hg_add_file_commit('foo.txt', FOO4, 'edit 4')
        self._hg_add_file_commit('foo.txt', FOO5, 'edit 5')
        self._hg_add_file_commit('foo.txt', FOO6, 'edit 6')

        self.assertEqual(EXPECTED_HG_SVN_DIFF_1, self.client.diff(None)[0])