Example #1
0
    def setup_checkout(cls, checkout_dir):
        """Populate a Subversion checkout.

        This will create a checkout of the sample Subversion repository stored
        in the :file:`testdata` directory.

        Args:
            checkout_dir (unicode):
                The top-level directory in which the checkout will be placed.

        Returns:
            The main checkout directory, or ``None`` if :command:`svn` isn't
            in the path.
        """
        if not is_exe_in_path('svn'):
            return None

        cls.svn_dir = os.path.join(cls.testdata_dir, 'svn-repo')
        cls.svn_repo_url = 'file://%s' % cls.svn_dir
        cls.clone_dir = os.path.join(checkout_dir, 'svn-repo')

        os.mkdir(checkout_dir, 0o700)
        os.chdir(checkout_dir)
        cls._run_svn(['co', cls.svn_repo_url, cls.clone_dir])

        return cls.clone_dir
Example #2
0
    def setUp(self):
        if not is_exe_in_path('svn'):
            raise SkipTest('svn not found in path')

        super(SVNClientTests, self).setUp()

        self.options.svn_show_copies_as_adds = None
        self.client = SVNClient(options=self.options)
Example #3
0
def command_exists(cmd_name):
    """Determine if the given command exists.

    This function checks for the existence of an RBTools command entry point
    with the given name and an executable named rbt-"cmd_name" on the path.
    Aliases are not considered.
    """
    return find_entry_point_for_command(cmd_name) or is_exe_in_path("rbt-%s" % cmd_name)
Example #4
0
def command_exists(cmd_name):
    """Determine if the given command exists.

    This function checks for the existence of an RBTools command entry point
    with the given name and an executable named rbt-"cmd_name" on the path.
    Aliases are not considered.
    """
    return (find_entry_point_for_command(cmd_name)
            or is_exe_in_path('rbt-%s' % cmd_name))
Example #5
0
    def setUp(self):
        if not is_exe_in_path('bzr'):
            raise SkipTest('bzr not found in path')

        super(BazaarClientTests, self).setUp()

        self.set_user_home(os.path.join(self.testdata_dir, 'homedir'))

        self.options.parent_branch = None
        self.client = BazaarClient(options=self.options)
Example #6
0
def process_mercurial_hook(stdin, log):
    CHG = 'chg'
    if is_exe_in_path(CHG):
        global HG
        os.environ['CHGHG'] = HG
        HG = CHG

    h = MercurialHook(log)
    node = os.environ.get('HG_NODE')
    return h.push_to_reviewboard(node)
Example #7
0
    def setUp(self):
        super(SVNClientTests, self).setUp()

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

        self.svn_dir = os.path.join(self.testdata_dir, 'svn-repo')
        self.clone_dir = self.chdir_tmp()
        self.svn_repo_url = 'file://' + self.svn_dir
        self._run_svn(['co', self.svn_repo_url, 'svn-repo'])
        os.chdir(os.path.join(self.clone_dir, 'svn-repo'))

        self.client = SVNClient(options=self.options)
        self.options.svn_show_copies_as_adds = None
Example #8
0
    def setUp(self):
        super(SVNClientTests, self).setUp()

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

        self.svn_dir = os.path.join(self.testdata_dir, 'svn-repo')
        self.clone_dir = self.chdir_tmp()
        self.svn_repo_url = 'file://' + self.svn_dir
        self._run_svn(['co', self.svn_repo_url, 'svn-repo'])
        os.chdir(os.path.join(self.clone_dir, 'svn-repo'))

        self.client = SVNClient(options=self.options)
        self.options.svn_show_copies_as_adds = None
Example #9
0
    def setup_checkout(cls, checkout_dir):
        """Populate two Bazaar clones.

        This will create a clone of the sample Bazaar repository stored in
        the :file:`testdata` directory, and a child clone of that first
        clone.

        Args:
            checkout_dir (unicode):
                The top-level directory in which clones will be placed.

        Returns:
            The main clone directory, or ``None`` if :command:`bzr` isn't
            in the path.
        """
        if not is_exe_in_path('bzr'):
            return None

        original_branch = os.path.join(checkout_dir, 'orig')
        child_branch = os.path.join(checkout_dir, 'child')

        os.mkdir(checkout_dir, 0o700)
        os.mkdir(original_branch, 0o700)
        os.mkdir(child_branch, 0o700)

        try:
            cls._run_bzr(['init', '.'], cwd=original_branch)
            cls._bzr_add_file_commit(filename='foo.txt',
                                     data=FOO,
                                     msg='initial commit',
                                     cwd=original_branch)

            cls._run_bzr([
                'branch', '--use-existing-dir', original_branch, child_branch
            ],
                         cwd=original_branch)
        except Exception as e:
            raise unittest.SkipTest('Unable to set up bzr checkout: %s' %
                                    six.text_type(e))

        cls.original_branch = original_branch
        cls.child_branch = child_branch

        return original_branch
Example #10
0
    def setUp(self):
        # This should come before the call to super to prevent
        # unbalanced calls to setUp/tearDown
        if not is_exe_in_path('bzr'):
            raise SkipTest('bzr not found in path')
        super(BazaarClientTests, self).setUp()

        self.original_branch = self.chdir_tmp()
        self.child_branch = self.create_tmp_dir()

        self._run_bzr(['init', '.'])
        self._bzr_add_file_commit('foo.txt', FOO, 'initial commit')
        self._run_bzr([
            'branch', '--use-existing-dir', self.original_branch,
            self.child_branch
        ])

        self.client = BazaarClient(options=self.options)
        self.options.parent_branch = None
Example #11
0
    def setUp(self):
        super(BazaarClientTests, self).setUp()

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

        self.set_user_home(os.path.join(self.testdata_dir, 'homedir'))

        self.orig_dir = os.getcwd()

        self.original_branch = self.chdir_tmp()
        self._run_bzr(["init", "."])
        self._bzr_add_file_commit("foo.txt", FOO, "initial commit")

        self.child_branch = mktemp()
        self._run_bzr(["branch", self.original_branch, self.child_branch])
        self.client = BazaarClient(options=self.options)
        os.chdir(self.orig_dir)

        self.options.parent_branch = None
Example #12
0
    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
Example #13
0
    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
Example #14
0
    def setUp(self):
        super(BazaarClientTests, self).setUp()

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

        self.set_user_home(
            os.path.join(self.testdata_dir, 'homedir'))

        self.orig_dir = os.getcwd()

        self.original_branch = self.chdir_tmp()
        self._run_bzr(["init", "."])
        self._bzr_add_file_commit("foo.txt", FOO, "initial commit")

        self.child_branch = mktemp()
        self._run_bzr(["branch", self.original_branch, self.child_branch])
        self.client = BazaarClient(options=self.options)
        os.chdir(self.orig_dir)

        self.options.parent_branch = None
Example #15
0
    def setUp(self):
        if not is_exe_in_path('bzr'):
            raise SkipTest('bzr not found in path')

        super(BazaarClientTests, self).setUp()

        self.set_user_home(
            os.path.join(self.testdata_dir, 'homedir'))

        self.original_branch = make_tempdir()
        self._run_bzr(['init', '.'], cwd=self.original_branch)
        self._bzr_add_file_commit('foo.txt', FOO, 'initial commit',
                                  cwd=self.original_branch)

        self.child_branch = make_tempdir()
        self._run_bzr(['branch', '--use-existing-dir', self.original_branch,
                       self.child_branch],
                      cwd=self.original_branch)
        self.client = BazaarClient(options=self.options)

        self.options.parent_branch = None
Example #16
0
    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()
Example #17
0
    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()
Example #18
0
    def setUp(self):
        if not is_exe_in_path('bzr'):
            raise SkipTest('bzr not found in path')

        super(BazaarClientTests, self).setUp()

        self.set_user_home(os.path.join(self.testdata_dir, 'homedir'))

        self.original_branch = make_tempdir()
        self._run_bzr(['init', '.'], cwd=self.original_branch)
        self._bzr_add_file_commit('foo.txt',
                                  FOO,
                                  'initial commit',
                                  cwd=self.original_branch)

        self.child_branch = make_tempdir()
        self._run_bzr([
            'branch', '--use-existing-dir', self.original_branch,
            self.child_branch
        ],
                      cwd=self.original_branch)
        self.client = BazaarClient(options=self.options)

        self.options.parent_branch = None
Example #19
0
    def setUpClass(cls):
        super(MercurialSubversionClientTests, cls).setUpClass()

        for exe in ('svnadmin', 'svnserve', 'svn'):
            if not is_exe_in_path(exe):
                raise SkipTest('%s is not available on the system. Skipping.' %
                               exe)

        cls._has_hgsubversion = None

        # 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.
        cls._svnserve_pid = None
        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
Example #20
0
    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
Example #21
0
class ClearCaseClientTests(kgb.SpyAgency, SCMClientTests):
    """Unit tests for ClearCaseClient."""

    @unittest.skipIf(not is_exe_in_path('cleartool'),
                     'cleartool not found in path')
    def setUp(self):
        super(ClearCaseClientTests, self).setUp()

        self.set_user_home(
            os.path.join(self.testdata_dir, 'homedir'))
        self.client = ClearCaseClient(options=self.options)

    def test_get_local_path_outside_view(self):
        """Testing ClearCaseClient.get_local_path outside of view"""
        self.spy_on(execute, op=kgb.SpyOpMatchInOrder([
            {
                'args': (['cleartool', 'pwv', '-short'],),
                'op': kgb.SpyOpReturn('** NONE **'),
            },
        ]))

        self.assertEqual(self.client.get_local_path(), None)

    def test_get_local_path_inside_view(self):
        """Testing ClearCaseClient.get_local_path inside view"""
        self.spy_on(execute, op=kgb.SpyOpMatchInOrder([
            {
                'args': (['cleartool', 'pwv', '-short'],),
                'op': kgb.SpyOpReturn('test-view'),
            },
            {
                'args': (['cleartool', 'pwv', '-root'],),
                'op': kgb.SpyOpReturn('/test/view'),
            },
            {
                'args': (['cleartool', 'describe', '-short', 'vob:.'],),
                'op': kgb.SpyOpReturn('vob'),
            },
        ]))

        self.assertEqual(self.client.get_local_path(), '/test/view/vob')

    def test_get_repository_info_snapshot(self):
        """Testing ClearCaseClient.get_repository_info with snapshot view"""
        self.spy_on(check_gnu_diff, call_original=False)
        self.spy_on(execute, op=kgb.SpyOpMatchInOrder([
            {
                'args': (['cleartool', 'pwv', '-short'],),
                'op': kgb.SpyOpReturn('test-view'),
            },
            {
                'args': (['cleartool', 'pwv', '-root'],),
                'op': kgb.SpyOpReturn('/test/view'),
            },
            {
                'args': (['cleartool', 'describe', '-short', 'vob:.'],),
                'op': kgb.SpyOpReturn('vob'),
            },
            {
                'args': (['cleartool', 'lsview', '-full', '-properties',
                          '-cview'],),
                'op': kgb.SpyOpReturn(_SNAPSHOT_VIEW_INFO),
            },
        ]))

        repository_info = self.client.get_repository_info()
        self.assertEqual(repository_info.path, '/test/view/vob')
        self.assertEqual(repository_info.vobtag, 'vob')
        self.assertEqual(repository_info.vob_tags, {'vob'})

        # Initial state that gets populated later by update_from_remote
        self.assertEqual(repository_info.uuid_to_tags, {})
        self.assertEqual(repository_info.is_legacy, True)

        self.assertEqual(self.client.viewtype, 'snapshot')
        self.assertEqual(self.client.is_ucm, False)

    def test_get_repository_info_dynamic(self):
        """Testing ClearCaseClient.get_repository_info with dynamic view and
        base ClearCase
        """
        self.spy_on(check_gnu_diff, call_original=False)
        self.spy_on(execute, op=kgb.SpyOpMatchInOrder([
            {
                'args': (['cleartool', 'pwv', '-short'],),
                'op': kgb.SpyOpReturn('test-view'),
            },
            {
                'args': (['cleartool', 'pwv', '-root'],),
                'op': kgb.SpyOpReturn('/test/view'),
            },
            {
                'args': (['cleartool', 'describe', '-short', 'vob:.'],),
                'op': kgb.SpyOpReturn('vob'),
            },
            {
                'args': (['cleartool', 'lsview', '-full', '-properties',
                          '-cview'],),
                'op': kgb.SpyOpReturn(_DYNAMIC_VIEW_INFO),
            },
        ]))

        repository_info = self.client.get_repository_info()
        self.assertEqual(repository_info.path, '/test/view/vob')
        self.assertEqual(repository_info.vobtag, 'vob')
        self.assertEqual(repository_info.vob_tags, {'vob'})

        # Initial state that gets populated later by update_from_remote
        self.assertEqual(repository_info.uuid_to_tags, {})
        self.assertEqual(repository_info.is_legacy, True)

        self.assertEqual(self.client.viewtype, 'dynamic')
        self.assertEqual(self.client.is_ucm, False)

    def test_get_repository_info_dynamic_UCM(self):
        """Testing ClearCaseClient.get_repository_info with dynamic view and UCM
        """
        self.spy_on(check_gnu_diff, call_original=False)
        self.spy_on(execute, op=kgb.SpyOpMatchInOrder([
            {
                'args': (['cleartool', 'pwv', '-short'],),
                'op': kgb.SpyOpReturn('test-view'),
            },
            {
                'args': (['cleartool', 'pwv', '-root'],),
                'op': kgb.SpyOpReturn('/test/view'),
            },
            {
                'args': (['cleartool', 'describe', '-short', 'vob:.'],),
                'op': kgb.SpyOpReturn('vob'),
            },
            {
                'args': (['cleartool', 'lsview', '-full', '-properties',
                          '-cview'],),
                'op': kgb.SpyOpReturn(_UCM_VIEW_INFO),
            },
        ]))

        repository_info = self.client.get_repository_info()
        self.assertEqual(repository_info.path, '/test/view/vob')
        self.assertEqual(repository_info.vobtag, 'vob')
        self.assertEqual(repository_info.vob_tags, {'vob'})

        # Initial state that gets populated later by update_from_remote
        self.assertEqual(repository_info.uuid_to_tags, {})
        self.assertEqual(repository_info.is_legacy, True)

        self.assertEqual(self.client.viewtype, 'dynamic')
        self.assertEqual(self.client.is_ucm, True)

    def test_get_repository_info_automatic(self):
        """Testing ClearCaseClient.get_repository_info with automatic view"""
        self.spy_on(check_gnu_diff, call_original=False)
        self.spy_on(execute, op=kgb.SpyOpMatchInOrder([
            {
                'args': (['cleartool', 'pwv', '-short'],),
                'op': kgb.SpyOpReturn('test-view'),
            },
            {
                'args': (['cleartool', 'pwv', '-root'],),
                'op': kgb.SpyOpReturn('/test/view'),
            },
            {
                'args': (['cleartool', 'describe', '-short', 'vob:.'],),
                'op': kgb.SpyOpReturn('vob'),
            },
            {
                'args': (['cleartool', 'lsview', '-full', '-properties',
                          '-cview'],),
                'op': kgb.SpyOpReturn(_AUTOMATIC_VIEW_INFO),
            },
        ]))

        try:
            self.client.get_repository_info()
        except SCMError as e:
            self.assertEqual(six.text_type(e),
                             'Webviews and automatic views are not currently '
                             'supported. RBTools commands can only be used in '
                             'dynamic or snapshot views.')
        else:
            self.fail('get_repository_info did not raise SCMError')

    def test_get_repository_info_webview(self):
        """Testing ClearCaseClient.get_repository_info with webview"""
        self.spy_on(check_gnu_diff, call_original=False)
        self.spy_on(execute, op=kgb.SpyOpMatchInOrder([
            {
                'args': (['cleartool', 'pwv', '-short'],),
                'op': kgb.SpyOpReturn('test-view'),
            },
            {
                'args': (['cleartool', 'pwv', '-root'],),
                'op': kgb.SpyOpReturn('/test/view'),
            },
            {
                'args': (['cleartool', 'describe', '-short', 'vob:.'],),
                'op': kgb.SpyOpReturn('vob'),
            },
            {
                'args': (['cleartool', 'lsview', '-full', '-properties',
                          '-cview'],),
                'op': kgb.SpyOpReturn(_WEBVIEW_VIEW_INFO),
            },
        ]))

        try:
            self.client.get_repository_info()
        except SCMError as e:
            self.assertEqual(six.text_type(e),
                             'Webviews and automatic views are not currently '
                             'supported. RBTools commands can only be used in '
                             'dynamic or snapshot views.')
        else:
            self.fail('get_repository_info did not raise SCMError')

    def test_repository_info_update_from_remote_clearcase(self):
        """Testing ClearCaseRepositoryInfo.update_from_remote with ClearCase
        remote
        """
        self.spy_on(execute, op=kgb.SpyOpMatchInOrder([
            {
                'args': (['cleartool', 'lsregion'],),
                'op': kgb.SpyOpReturn(['region']),
            },
            {
                'args': (['cleartool', 'lsvob', '-s', '-family',
                          '9ac6856f.c9af11eb.9851.52:54:00:7f:63:a5',
                          '-region', 'region'],),
                'op': kgb.SpyOpReturn('vob1'),
            },
            {
                'args': (['cleartool', 'lsvob', '-s', '-family',
                          'b520a815.c9af11eb.986f.52:54:00:7f:63:a5',
                          '-region', 'region'],),
                'op': kgb.SpyOpReturn('vob2'),
            },
        ]))

        repository_info = ClearCaseRepositoryInfo('/view/test/vob', 'vob')
        repository_info.update_from_remote({}, {
            'repopath': '/view/server-view',
            'uuids': [
                '9ac6856f.c9af11eb.9851.52:54:00:7f:63:a5',
                'b520a815.c9af11eb.986f.52:54:00:7f:63:a5',
            ],
        })

        self.assertEqual(repository_info.uuid_to_tags, {
            '9ac6856f.c9af11eb.9851.52:54:00:7f:63:a5': ['vob1'],
            'b520a815.c9af11eb.986f.52:54:00:7f:63:a5': ['vob2'],
        })
        self.assertEqual(repository_info.is_legacy, False)

    def test_repository_info_update_from_remote_versionvault(self):
        """Testing ClearCaseRepositoryInfo.update_from_remote with
        VersionVault remote
        """
        self.spy_on(execute, op=kgb.SpyOpMatchInOrder([
            {
                'args': (['cleartool', 'lsregion'],),
                'op': kgb.SpyOpReturn(['region']),
            },
            {
                'args': (['cleartool', 'lsvob', '-s', '-family',
                          '9ac6856f.c9af11eb.9851.52:54:00:7f:63:a5',
                          '-region', 'region'],),
                'op': kgb.SpyOpReturn('vob'),
            },
        ]))

        repository_info = ClearCaseRepositoryInfo('/view/test/vob', 'vob')
        repository_info.update_from_remote({}, {
            'repopath': '/view/server-view',
            'uuid': '9ac6856f.c9af11eb.9851.52:54:00:7f:63:a5',
        })

        self.assertEqual(repository_info.uuid_to_tags, {
            '9ac6856f.c9af11eb.9851.52:54:00:7f:63:a5': ['vob'],
        })
        self.assertEqual(repository_info.is_legacy, True)

    def test_get_vobtag_success(self):
        """Testing ClearCaseClient._get_vobtag inside view"""
        self.spy_on(execute, op=kgb.SpyOpMatchInOrder([
            {
                'args': (['cleartool', 'describe', '-short', 'vob:.'],),
                'op': kgb.SpyOpReturn('/vob\n'),
            },
        ]))

        self.assertEqual(self.client._get_vobtag(), '/vob')

    def test_get_vobtag_error(self):
        """Testing ClearCaseClient._get_vobtag outside view"""
        self.spy_on(execute, op=kgb.SpyOpMatchInOrder([
            {
                'args': (['cleartool', 'describe', '-short', 'vob:.'],),
                'op': kgb.SpyOpReturn(
                    'cleartool: Error: Unable to determine VOB for '
                    'pathname ".".\n'
                ),
            },
        ]))

        with self.assertRaises(SCMError):
            self.client._get_vobtag()

    def test_parse_revision_spec(self):
        """Testing ClearCaseClient.parse_revision_spec"""
        cases = [
            (
                [],
                '--rbtools-checkedout-base',
                '--rbtools-checkedout-changeset',
            ),
            (
                ['activity:bugfix123'],
                '--rbtools-activity-base',
                'bugfix123',
            ),
            (
                ['baseline:test@/vob'],
                '--rbtools-baseline-base',
                ['test@/vob'],
            ),
            (
                ['brtype:bugfix123'],
                '--rbtools-branch-base',
                'bugfix123',
            ),
            (
                ['lbtype:bugfix123'],
                '--rbtools-label-base',
                ['bugfix123'],
            ),
            (
                ['stream:bugfix123@/vob'],
                '--rbtools-stream-base',
                'bugfix123@/vob',
            ),
            (
                ['baseline:dev@/vob', 'baseline:bugfix123@/vob'],
                '--rbtools-baseline-base',
                ['dev@/vob', 'bugfix123@/vob'],
            ),
            (
                ['lbtype:dev', 'lbtype:bugfix123'],
                '--rbtools-label-base',
                ['dev', 'bugfix123'],
            ),
            (
                [
                    'vob1/file@@/main/0:vob1/file@@/main/4',
                    'vob2/file2@@/dev/3:vob2/file2@@/main/9',
                ],
                '--rbtools-files',
                [
                    ['vob1/file@@/main/0', 'vob1/file@@/main/4'],
                    ['vob2/file2@@/dev/3', 'vob2/file2@@/main/9'],
                ],
            ),
        ]

        # Fake a dynamic view, which is required for revision specs with two
        # revisions.
        self.client.viewtype = 'dynamic'

        for spec, base, tip in cases:
            self.assertEqual(
                self.client.parse_revision_spec(spec),
                {'base': base, 'tip': tip})

    def test_checkedout_changeset(self):
        """Testing ClearCaseClient._get_checkedout_changeset"""
        self.spy_on(execute, op=kgb.SpyOpMatchInOrder([
            {
                'args': (['cleartool', 'lsregion'],),
                'op': kgb.SpyOpReturn(['region']),
            },
            {
                'args': (['cleartool', 'lsvob', '-s', '-family',
                          '9ac6856f.c9af11eb.9851.52:54:00:7f:63:a5',
                          '-region', 'region'],),
                'op': kgb.SpyOpReturn('vob'),
            },
            {
                'args': (['cleartool', 'lscheckout', '-avobs', '-cview',
                          '-me', '-fmt', r'%En\t%PVn\t%Vn\n'],),
                'op': kgb.SpyOpReturn(
                    'test2.py\t/main/1\t/main/CHECKEDOUT\n'
                    'test.pdf\t/main/0\t/main/CHECKEDOUT\n'
                    'test.py\t/main/1\t/main/CHECKEDOUT\n'
                ),
            },
        ]))

        repository_info = ClearCaseRepositoryInfo('/view/test/vob', 'vob')
        repository_info.update_from_remote({}, {
            'repopath': '/view/server-view',
            'uuid': '9ac6856f.c9af11eb.9851.52:54:00:7f:63:a5',
        })

        changeset = self.client._get_checkedout_changeset(repository_info)

        self.assertEqual(changeset, [
            ('test2.py@@/main/1', 'test2.py'),
            ('test.pdf@@/main/0', 'test.pdf'),
            ('test.py@@/main/1', 'test.py'),
        ])

    def test_activity_changeset(self):
        """Testing ClearCaseClient._get_activity_changeset"""
        self.spy_on(execute, op=kgb.SpyOpMatchInOrder([
            {
                'args': (['cleartool', 'lsregion'],),
                'op': kgb.SpyOpReturn(['region']),
            },
            {
                'args': (['cleartool', 'lsvob', '-s', '-family',
                          '9ac6856f.c9af11eb.9851.52:54:00:7f:63:a5',
                          '-region', 'region'],),
                'op': kgb.SpyOpReturn('/vobs/els'),
            },
            {
                'args': (['cleartool', 'lsactivity', '-fmt', '%[versions]Qp',
                          'activity-name'],),
                'op': kgb.SpyOpReturn(
                    '"/view/x/vobs/els/.@@/main/int/CHECKEDOUT.78" '
                    '"/view/x/vobs/els/test.pdf@@/main/int/CHECKEDOUT.77" '
                    '"/view/x/vobs/els/new.py@@/main/int/CHECKEDOUT.71" '
                    '"/view/x/vobs/els/test.py@@/main/int/CHECKEDOUT.64" '
                    '"/view/x/vobs/els/.@@/main/int/2" '
                    '"/view/x/vobs/els/test.py@@/main/int/3" '
                    '"/view/x/vobs/els/test.py@@/main/int/2"'
                ),
            },
            {
                'args': (['cleartool', 'desc', '-fmt',
                          '%[version_predecessor]p',
                          '/view/x/vobs/els/.@@/main/int/2'],),
                'op': kgb.SpyOpReturn('/main/int/1'),
            },
            {
                'args': (['cleartool', 'desc', '-fmt',
                          '%[version_predecessor]p',
                          '/view/x/vobs/els/test.py@@/main/int/2'],),
                'op': kgb.SpyOpReturn('/main/int/1'),
            },
        ]))

        repository_info = ClearCaseRepositoryInfo('/view/test/vob', 'vob')
        repository_info.update_from_remote({}, {
            'repopath': '/view/server-view',
            'uuid': '9ac6856f.c9af11eb.9851.52:54:00:7f:63:a5',
        })

        changeset = self.client._get_activity_changeset('activity-name',
                                                        repository_info)

        self.assertEqual(changeset, [
            ('/view/x/vobs/els/.@@/main/int/1',
             '/view/x/vobs/els/.'),
            ('/view/x/vobs/els/test.pdf@@/main/int/0',
             '/view/x/vobs/els/test.pdf'),
            ('/view/x/vobs/els/new.py@@/main/int/0',
             '/view/x/vobs/els/new.py'),
            ('/view/x/vobs/els/test.py@@/main/int/1',
             '/view/x/vobs/els/test.py'),
        ])

    def test_diff_directory(self):
        """Testing ClearCaseClient._diff_directory"""
        self.spy_on(execute, op=kgb.SpyOpMatchInOrder([
            {
                'args': (['cleartool', 'diff', '-ser',
                          '.@@/main/1', '.@@/main/CHECKEDOUT'],),
                'op': kgb.SpyOpReturn([
                    '********************************',
                    '<<< directory 1: .@@/main/test-project_integration/2',
                    '>>> directory 2:',
                    '.@@/main/test-project_integration/CHECKEDOUT',
                    '********************************',
                    '-----[ renamed to ]-----',
                    '< test2.py  --06-29T17:26 david',
                    '---',
                    '> renamed-file.py  --06-29T17:26 david',
                    '-----[ deleted ]-----',
                    '< test3.py  --07-28T00:30 david',
                    '-----[ added ]-----',
                    '> test4.py  --07-28T18:27 david',
                ]),
            },
            {
                'args': (['cleartool', 'desc', '-fmt', '%On',
                          '.@@/main/1/test2.py'],),
                'op': kgb.SpyOpReturn('test2.py-fake-oid'),
            },
            {
                'args': (['cleartool', 'desc', '-fmt', '%On',
                          '.@@/main/CHECKEDOUT/renamed-file.py'],),
                'op': kgb.SpyOpReturn('renamed-file.py-fake-oid'),
            },
            {
                'args': (['cleartool', 'desc', '-fmt', '%On',
                          '.@@/main/1/test3.py'],),
                'op': kgb.SpyOpReturn('test3.py-fake-oid'),
            },
            {
                'args': (['cleartool', 'desc', '-fmt', '%On',
                          '.@@/main/CHECKEDOUT/test4.py'],),
                'op': kgb.SpyOpReturn('test4.py-fake-oid'),
            },
        ]))

        self.assertEqual(
            self.client._diff_directory('.@@/main/1', '.@@/main/CHECKEDOUT'),
            {
                'added': {('.@@/main/CHECKEDOUT/test4.py',
                           'test4.py-fake-oid')},
                'deleted': {('.@@/main/1/test3.py', 'test3.py-fake-oid')},
                'renamed': {('.@@/main/1/test2.py', 'test2.py-fake-oid',
                             '.@@/main/CHECKEDOUT/renamed-file.py',
                             'renamed-file.py-fake-oid')},
            })