示例#1
0
    def get_repository_info(self):
        """Return the repository info object."""
        if not check_install(['hg', '--help']):
            logging.debug('Unable to execute "hg --help": skipping Mercurial')
            return None

        self._init()

        if not self.hg_root:
            # hg aborted => no mercurial repository here.
            return None

        if self._type == 'svn':
            return self._calculate_hgsubversion_repository_info(self._svn_info)
        else:
            path = self.hg_root
            base_path = '/'

            if self._remote_path:
                path = self._remote_path[1]
                base_path = ''

            return RepositoryInfo(path=path,
                                  base_path=base_path,
                                  supports_parent_diffs=True)
示例#2
0
    def get_repository_info(self):
        if not check_install('p4 help'):
            return None

        data = execute(["p4", "info"], ignore_errors=True)

        m = re.search(r'^Server address: (.+)$', data, re.M)
        if not m:
            return None

        repository_path = m.group(1).strip()

        try:
            hostname, port = repository_path.split(":")
            info = socket.gethostbyaddr(hostname)

            # If aliases exist for hostname, create a list of alias:port
            # strings for repository_path.
            if info[1]:
                servers = [info[0]] + info[1]
                repository_path = ["%s:%s" % (server, port)
                                   for server in servers]
            else:
                repository_path = "%s:%s" % (info[0], port)
        except (socket.gaierror, socket.herror):
            pass

        m = re.search(r'^Server version: [^ ]*/([0-9]+)\.([0-9]+)/[0-9]+ .*$',
                      data, re.M)
        self.p4d_version = int(m.group(1)), int(m.group(2))

        return RepositoryInfo(path=repository_path, supports_changesets=True)
示例#3
0
    def get_repository_info(self):
        if not check_install(['cvs']):
            logging.debug('Unable to execute "cvs": skipping CVS')
            return None

        cvsroot_path = os.path.join('CVS', 'Root')

        if not os.path.exists(cvsroot_path):
            return None

        with open(cvsroot_path, 'r') as fp:
            repository_path = fp.read().strip()

        i = repository_path.find('@')
        if i != -1:
            repository_path = repository_path[i + 1:]

        i = repository_path.rfind(':')
        if i != -1:
            host = repository_path[:i]
            try:
                canon = socket.getfqdn(host)
                repository_path = repository_path.replace('%s:' % host,
                                                          '%s:' % canon)
            except socket.error as msg:
                logging.error('failed to get fqdn for %s, msg=%s',
                              host, msg)

        return RepositoryInfo(path=repository_path)
示例#4
0
    def get_repository_info(self):
        """Return repository information for the current working tree.

        Returns:
            rbtools.clients.RepositoryInfo:
            The repository info structure.
        """
        if not check_install([self._exe, '--help']):
            logging.debug('Unable to execute "hg --help": skipping Mercurial')
            return None

        self._init()

        if not self.hg_root:
            # hg aborted => no mercurial repository here.
            return None

        if self._type == 'svn':
            return self._calculate_hgsubversion_repository_info(self._svn_info)
        else:
            path = self.hg_root
            base_path = '/'

            if self._remote_path:
                path = self._remote_path[1]
                base_path = ''

            return RepositoryInfo(path=path,
                                  base_path=base_path,
                                  local_path=self.hg_root)
示例#5
0
    def _calculate_hgsubversion_repository_info(self, svn_info):
        """Return repository info for an hgsubversion checkout.

        Args:
            svn_info (unicode):
                The SVN info output.

        Returns:
            rbtools.clients.RepositoryInfo:
            The repository info structure, if available.
        """
        def _info(r):
            m = re.search(r, svn_info, re.M)

            if m:
                return urlsplit(m.group(1))
            else:
                return None

        self._type = 'svn'

        root = _info(r'^Repository Root: (.+)$')
        url = _info(r'^URL: (.+)$')

        if not (root and url):
            return None

        scheme, netloc, path, _, _ = root
        root = urlunparse(
            [scheme, root.netloc.split('@')[-1], path, '', '', ''])
        base_path = url.path[len(path):]

        return RepositoryInfo(path=root,
                              base_path=base_path,
                              local_path=self.hg_root)
示例#6
0
    def get_repository_info(self):
        """Determine and return the repository info.

        Returns:
            rbtools.clients.RepositoryInfo:
            The repository info object. If the current working directory does
            not correspond to a TFS checkout, this returns ``None``.
        """
        if self.tf is None:
            logging.debug('Unable to execute "tf help": skipping TFS')
            return None

        workfold = self._run_tf(['workfold', os.getcwd()])

        m = re.search('^Collection: (.*)$', workfold, re.MULTILINE)
        if not m:
            logging.debug('Could not find the collection from "tf workfold"')
            return None

        # Now that we know it's TFS, make sure we have GNU diff installed,
        # and error out if we don't.
        check_gnu_diff()

        path = unquote(m.group(1))

        return RepositoryInfo(path)
示例#7
0
    def get_repository_info(self):
        """
        Find out information about the current Bazaar branch (if any) and
        return it.
        """
        if not check_install(['bzr', 'help']):
            logging.debug('Unable to execute "bzr help": skipping Bazaar')
            return None

        bzr_info = execute(["bzr", "info"], ignore_errors=True)

        if "ERROR: Not a branch:" in bzr_info:
            # This is not a branch:
            repository_info = None
        else:
            # This is a branch, let's get its attributes:
            branch_match = re.search(self.BRANCH_REGEX, bzr_info, re.MULTILINE)

            path = branch_match.group("branch_path")
            if path == ".":
                path = os.getcwd()

            repository_info = RepositoryInfo(
                path=path,
                base_path="/",  # Diffs are always relative to the root.
                supports_parent_diffs=True)

        return repository_info
示例#8
0
    def get_repository_info(self):
        """Return repository information for the current working tree.

        Returns:
            rbtools.clients.RepositoryInfo:
            The repository info structure.
        """
        if not check_install(['bzr', 'help']):
            logging.debug('Unable to execute "bzr help": skipping Bazaar')
            return None

        bzr_info = execute(['bzr', 'info'], ignore_errors=True)

        if 'ERROR: Not a branch:' in bzr_info:
            # This is not a branch:
            repository_info = None
        else:
            # This is a branch, let's get its attributes:
            branch_match = re.search(self.BRANCH_REGEX, bzr_info, re.MULTILINE)

            path = branch_match.group('branch_path')
            if path == '.':
                path = os.getcwd()

            repository_info = RepositoryInfo(
                path=path,
                base_path='/',  # Diffs are always relative to the root.
                local_path=path,
                supports_parent_diffs=True)

        return repository_info
示例#9
0
    def get_repository_info(self):
        if not check_install(['cm', 'version']):
            logging.debug('Unable to execute "cm version": skipping Plastic')
            return None

        # Get the workspace directory, so we can strip it from the diff output
        self.workspacedir = execute(["cm", "gwp", ".", "--format={1}"],
                                    split_lines=False,
                                    ignore_errors=True).strip()

        logging.debug("Workspace is %s" % self.workspacedir)

        # Get the repository that the current directory is from
        split = execute(["cm", "ls", self.workspacedir, "--format={8}"],
                        split_lines=True,
                        ignore_errors=True)

        # remove blank lines
        split = [x for x in split if x]

        m = re.search(r'^rep:(.+)$', split[0], re.M)

        if not m:
            return None

        path = m.group(1)

        return RepositoryInfo(path,
                              supports_changesets=True,
                              supports_parent_diffs=False)
示例#10
0
    def get_repository_info(self):
        if not check_install('cm version'):
            return None

        # Get the repository that the current directory is from.  If there
        # is more than one repository mounted in the current directory,
        # bail out for now (in future, should probably enter a review
        # request per each repository.)
        split = execute(["cm", "ls", "--format={8}"],
                        split_lines=True,
                        ignore_errors=True)
        m = re.search(r'^rep:(.+)$', split[0], re.M)

        if not m:
            return None

        # Make sure the repository list contains only one unique entry
        if len(split) != split.count(split[0]):
            # Not unique!
            die('Directory contains more than one mounted repository')

        path = m.group(1)

        # Get the workspace directory, so we can strip it from the diff output
        self.workspacedir = execute(["cm", "gwp", ".", "--format={1}"],
                                    split_lines=False,
                                    ignore_errors=True).strip()

        logging.debug("Workspace is %s" % self.workspacedir)

        return RepositoryInfo(path,
                              supports_changesets=True,
                              supports_parent_diffs=False)
示例#11
0
    def get_repository_info(self):
        if not check_install('hg --help'):
            return None

        self._load_hgrc()

        if not self.hg_root:
            # hg aborted => no mercurial repository here.
            return None

        svn_info = execute(["hg", "svn", "info"], ignore_errors=True)

        if (not svn_info.startswith('abort:')
                and not svn_info.startswith("hg: unknown command")
                and not svn_info.lower().startswith('not a child of')):
            return self._calculate_hgsubversion_repository_info(svn_info)

        self._type = 'hg'

        path = self.hg_root
        base_path = '/'

        if self.hgrc:
            self._calculate_remote_path()

            if self._remote_path:
                path = self._remote_path[1]
                base_path = ''

        return RepositoryInfo(path=path,
                              base_path=base_path,
                              supports_parent_diffs=True)
示例#12
0
    def _calculate_hgsubversion_repository_info(self, svn_info):
        def _info(r):
            m = re.search(r, svn_info, re.M)

            if m:
                return urlsplit(m.group(1))
            else:
                return None

        self._type = 'svn'

        root = _info(r'^Repository Root: (.+)$')
        url = _info(r'^URL: (.+)$')

        if not (root and url):
            return None

        scheme, netloc, path, _, _ = root
        root = urlunparse(
            [scheme, root.netloc.split("@")[-1], path, "", "", ""])
        base_path = url.path[len(path):]

        return RepositoryInfo(path=root,
                              base_path=base_path,
                              supports_parent_diffs=True)
示例#13
0
    def __init__(self, path, base_path, vobstag):
        """Initialize the repsitory info.

        Args:
            path (unicode):
                The path of the repository.

            base_path (unicode):
                The relative path between the repository root and the working
                directory.

            vobstag (unicode):
                The vobstag for the repository.
        """
        RepositoryInfo.__init__(self, path, base_path,
                                supports_parent_diffs=False)
        self.vobstag = vobstag
示例#14
0
    def get_repository_info(self):
        if not self.p4.is_supported():
            return None

        p4_info = self.p4.info()

        repository_path = p4_info.get('Server address', None)

        if repository_path is None:
            return None

        try:
            parts = repository_path.split(':')
            hostname = None

            if len(parts) == 3 and parts[0] == 'ssl':
                hostname = parts[1]
                port = parts[2]
            elif len(parts) == 2:
                hostname, port = parts

            if not hostname:
                die('Path %s is not a valid Perforce P4PORT' % repository_path)

            info = socket.gethostbyaddr(hostname)

            # If aliases exist for hostname, create a list of alias:port
            # strings for repository_path.
            if info[1]:
                servers = [info[0]] + info[1]
                repository_path = [
                    "%s:%s" % (server, port) for server in servers
                ]
            else:
                repository_path = "%s:%s" % (info[0], port)
        except (socket.gaierror, socket.herror):
            pass

        server_version = p4_info.get('Server version', None)

        if not server_version:
            return None

        m = re.search(r'[^ ]*/([0-9]+)\.([0-9]+)/[0-9]+ .*$', server_version,
                      re.M)
        if m:
            self.p4d_version = int(m.group(1)), int(m.group(2))
        else:
            # Gracefully bail if we don't get a match
            return None

        # Now that we know it's Perforce, make sure we have GNU diff
        # installed, and error out if we don't.
        check_gnu_diff()

        return RepositoryInfo(path=repository_path, supports_changesets=True)
示例#15
0
    def get_repository_info(self):
        """Return repository information for the current working tree.

        Returns:
            rbtools.clients.RepositoryInfo:
            The repository info structure.
        """
        local_path = self.get_local_path()

        if local_path:
            return RepositoryInfo(path=local_path, local_path=local_path)

        return None
示例#16
0
    def setUp(self):
        # Save the old http_get and http_post
        postreview.options = OptionsStub()

        self.saved_http_get = ReviewBoardServer.http_get
        self.saved_http_post = ReviewBoardServer.http_post

        self.server = ReviewBoardServer('http://localhost:8080/',
                                        RepositoryInfo(), None)
        ReviewBoardServer.http_get = self._http_method
        ReviewBoardServer.http_post = self._http_method

        self.server.deprecated_api = self.deprecated_api
        self.http_response = {}
示例#17
0
    def get_repository_info(self):
        """Return repository information for the current working tree.

        Returns:
            rbtools.clients.RepositoryInfo:
            The repository info structure.
        """
        if not check_install(['cvs']):
            logging.debug('Unable to execute "cvs": skipping CVS')
            return None

        repository_path = self.get_local_path()

        return RepositoryInfo(path=repository_path,
                              local_path=repository_path)
示例#18
0
    def get_repository_info(self):
        """Determine and return the repository info.

        Returns:
            rbtools.clients.RepositoryInfo:
            The repository info object. If the current working directory does
            not correspond to a TFS checkout, this returns ``None``.
        """
        rc, path, errors = self._run_helper(['get-collection'],
                                            ignore_errors=True)

        if rc == 0:
            return RepositoryInfo(path.strip())
        else:
            return None
示例#19
0
    def get_repository_info(self):
        """Return repository information for the current working tree.

        Returns:
            rbtools.clients.RepositoryInfo:
            The repository info structure.
        """
        path = self.get_local_path()

        if not path:
            return None

        return RepositoryInfo(
            path=path,
            base_path='/',  # Diffs are always relative to the root.
            local_path=path)
示例#20
0
    def get_repository_info(self):
        """Return repository information for the current working tree.

        Returns:
            rbtools.clients.RepositoryInfo:
            The repository info structure.
        """
        path = self.get_local_path()

        if path:
            # Now that we know it's TFS, make sure we have GNU diff installed, and
            # error out if we don't.
            check_gnu_diff()

            return RepositoryInfo(path=path, local_path=path)

        return None
示例#21
0
class CVSClient(SCMClient):
    """
    A wrapper around the cvs tool that fetches repository
    information and generates compatible diffs.
    """
    name = 'CVS'

    supports_diff_exclude_patterns = True

    INDEX_FILE_RE = re.compile('^Index: (.+)\n$')

    REVISION_WORKING_COPY = '--rbtools-working-copy'

    def __init__(self, **kwargs):
        super(CVSClient, self).__init__(**kwargs)

    def get_repository_info(self):
        if not check_install(['cvs']):
            logging.debug('Unable to execute "cvs": skipping CVS')
            return None

        cvsroot_path = os.path.join("CVS", "Root")

        if not os.path.exists(cvsroot_path):
            return None

        fp = open(cvsroot_path, "r")
        repository_path = fp.read().strip()
        fp.close()

        i = repository_path.find("@")
        if i != -1:
            repository_path = repository_path[i + 1:]

        i = repository_path.rfind(":")
        if i != -1:
            host = repository_path[:i]
            try:
                canon = socket.getfqdn(host)
                repository_path = repository_path.replace('%s:' % host,
                                                          '%s:' % canon)
            except socket.error, msg:
                logging.error("failed to get fqdn for %s, msg=%s"
                              % (host, msg))

        return RepositoryInfo(path=repository_path)
示例#22
0
    def test_prompt_rb_repository_repos_found(self):
        """Testing setup-repo reads and processes existing repos"""
        setup = self._create_setup_repo_command()
        setup.default_transport_cls = TestTransport('testmockurl')
        mock_api_root = setup.default_transport_cls.get_root()

        self.spy_on(get_input, call_fake=lambda *args, **kwargs: '1')
        self.spy_on(confirm_select)
        self.spy_on(setup._display_rb_repositories)

        output = setup.prompt_rb_repository(
            tool_name='Git',
            repository_info=RepositoryInfo(path='testpath'),
            api_root=mock_api_root,
        )

        self.assertTrue(setup._display_rb_repositories.called)
        self.assertIsInstance(output, ItemResource)
示例#23
0
    def test_prompt_rb_repository_no_repos_found(self):
        """Testing setup-repo does not show repo prompt if no repo exists"""
        setup = self._create_setup_repo_command()
        setup.default_transport_cls = TestTransport(
            'testmockurl',
            list_payload=TestWithPayloads.list_payload_no_repos,
        )
        mock_api_root = setup.default_transport_cls.get_root()

        self.spy_on(setup._display_rb_repositories)

        output = setup.prompt_rb_repository(
            tool_name='Git',
            repository_info=RepositoryInfo(path='testpath'),
            api_root=mock_api_root)

        self.assertFalse(setup._display_rb_repositories.called)
        self.assertIsNone(output)
示例#24
0
    def _calculate_hgsubversion_repository_info(self, svn_info):
        self._type = 'svn'
        m = re.search(r'^Repository Root: (.+)$', svn_info, re.M)

        if not m:
            return None

        path = m.group(1)
        m2 = re.match(r'^(svn\+ssh|http|https|svn)://([-a-zA-Z0-9.]*@)(.*)$',
                        path)
        if m2:
            path = '%s://%s' % (m2.group(1), m2.group(3))

        m = re.search(r'^URL: (.+)$', svn_info, re.M)

        if not m:
            return None

        base_path = m.group(1)[len(path):] or "/"
        return RepositoryInfo(path=path, base_path=base_path,
                              supports_parent_diffs=True)
示例#25
0
class CVSClient(SCMClient):
    """
    A wrapper around the cvs tool that fetches repository
    information and generates compatible diffs.
    """
    name = 'CVS'

    def __init__(self, **kwargs):
        super(CVSClient, self).__init__(**kwargs)

    def get_repository_info(self):
        if not check_install("cvs"):
            return None

        cvsroot_path = os.path.join("CVS", "Root")

        if not os.path.exists(cvsroot_path):
            return None

        fp = open(cvsroot_path, "r")
        repository_path = fp.read().strip()
        fp.close()

        i = repository_path.find("@")
        if i != -1:
            repository_path = repository_path[i + 1:]

        i = repository_path.rfind(":")
        if i != -1:
            host = repository_path[:i]
            try:
                canon = socket.getfqdn(host)
                repository_path = repository_path.replace('%s:' % host,
                                                          '%s:' % canon)
            except socket.error, msg:
                logging.error("failed to get fqdn for %s, msg=%s"
                              % (host, msg))

        return RepositoryInfo(path=repository_path)
示例#26
0
    def get_repository_info(self):
        if not check_install(['hg', '--help']):
            return None

        self._init()

        if not self.hg_root:
            # hg aborted => no mercurial repository here.
            return None

        if self._type == 'svn':
            return self._calculate_hgsubversion_repository_info(self._svn_info)
        else:
            path = self.hg_root
            base_path = '/'

            if self._remote_path:
                path = self._remote_path[1]
                base_path = ''

            return RepositoryInfo(path=path,
                                  base_path=base_path,
                                  supports_parent_diffs=True)
示例#27
0
    def get_repository_info(self):
        """Return repository information for the current working tree.

        Returns:
            rbtools.clients.RepositoryInfo:
            The repository info structure.
        """
        if not check_install(['cm', 'version']):
            logging.debug('Unable to execute "cm version": skipping Plastic')
            return None

        # Get the workspace directory, so we can strip it from the diff output
        self.workspacedir = execute(['cm', 'gwp', '.', '--format={1}'],
                                    split_lines=False,
                                    ignore_errors=True).strip()

        logging.debug('Workspace is %s', self.workspacedir)

        # Get the repository that the current directory is from
        split = execute(['cm', 'ls', self.workspacedir, '--format={8}'],
                        split_lines=True,
                        ignore_errors=True)

        # remove blank lines
        split = [x for x in split if x]

        m = re.search(r'^rep:(.+)$', split[0], re.M)

        if not m:
            return None

        path = m.group(1)

        return RepositoryInfo(path=path,
                              local_path=path,
                              supports_changesets=True,
                              supports_parent_diffs=False)
示例#28
0
 def __init__(self, path, base_path, vobstag, supports_parent_diffs=False):
     RepositoryInfo.__init__(self, path, base_path,
                             supports_parent_diffs=supports_parent_diffs)
     self.vobstag = vobstag
示例#29
0
    def get_repository_info(self):
        if not check_install('git --help'):
            # CreateProcess (launched via subprocess, used by check_install)
            # does not automatically append .cmd for things it finds in PATH.
            # If we're on Windows, and this works, save it for further use.
            if (sys.platform.startswith('win')
                    and check_install('git.cmd --help')):
                self.git = 'git.cmd'
            else:
                return None

        git_dir = execute([self.git, "rev-parse", "--git-dir"],
                          ignore_errors=True).rstrip("\n")

        if git_dir.startswith("fatal:") or not os.path.isdir(git_dir):
            return None
        self.bare = execute([self.git, "config",
                             "core.bare"]).strip() == 'true'

        # post-review in directories other than the top level of
        # of a work-tree would result in broken diffs on the server
        if not self.bare:
            git_top = execute([self.git, "rev-parse", "--show-toplevel"],
                              ignore_errors=True).rstrip("\n")

            # Top level might not work on old git version se we use git dir
            # to find it.
            if git_top.startswith("fatal:") or not os.path.isdir(git_dir):
                git_top = git_dir

            os.chdir(os.path.abspath(git_top))

        self.head_ref = execute([self.git, 'symbolic-ref', '-q', 'HEAD'],
                                ignore_errors=True).strip()

        # We know we have something we can work with. Let's find out
        # what it is. We'll try SVN first, but only if there's a .git/svn
        # directory. Otherwise, it may attempt to create one and scan
        # revisions, which can be slow. Also skip SVN detection if the git
        # repository was specified on command line.
        git_svn_dir = os.path.join(git_dir, 'svn')

        if (not getattr(self.options, 'repository_url', None)
                and os.path.isdir(git_svn_dir)
                and len(os.listdir(git_svn_dir)) > 0):
            data = execute([self.git, "svn", "info"], ignore_errors=True)

            m = re.search(r'^Repository Root: (.+)$', data, re.M)

            if m:
                path = m.group(1)
                m = re.search(r'^URL: (.+)$', data, re.M)

                if m:
                    base_path = m.group(1)[len(path):] or "/"
                    m = re.search(r'^Repository UUID: (.+)$', data, re.M)

                    if m:
                        uuid = m.group(1)
                        self.type = "svn"

                        # Get SVN tracking branch
                        if getattr(self.options, 'parent_branch', None):
                            self.upstream_branch = self.options.parent_branch
                        else:
                            data = execute([self.git, "svn", "rebase", "-n"],
                                           ignore_errors=True)
                            m = re.search(r'^Remote Branch:\s*(.+)$', data,
                                          re.M)

                            if m:
                                self.upstream_branch = m.group(1)
                            else:
                                sys.stderr.write('Failed to determine SVN '
                                                 'tracking branch. Defaulting'
                                                 'to "master"\n')
                                self.upstream_branch = 'master'

                        return SVNRepositoryInfo(path=path,
                                                 base_path=base_path,
                                                 uuid=uuid,
                                                 supports_parent_diffs=True)
            else:
                # Versions of git-svn before 1.5.4 don't (appear to) support
                # 'git svn info'.  If we fail because of an older git install,
                # here, figure out what version of git is installed and give
                # the user a hint about what to do next.
                version = execute([self.git, "svn", "--version"],
                                  ignore_errors=True)
                version_parts = re.search('version (\d+)\.(\d+)\.(\d+)',
                                          version)
                svn_remote = execute(
                    [self.git, "config", "--get", "svn-remote.svn.url"],
                    ignore_errors=True)

                if (version_parts and svn_remote and not self.is_valid_version(
                    (int(version_parts.group(1)), int(version_parts.group(2)),
                     int(version_parts.group(3))), (1, 5, 4))):
                    die("Your installation of git-svn must be upgraded to "
                        "version 1.5.4 or later")

        # Okay, maybe Perforce (git-p4).
        git_p4_ref = os.path.join(git_dir, 'refs', 'remotes', 'p4', 'master')
        data = execute([self.git, 'config', '--get', 'git-p4.port'],
                       ignore_errors=True)
        m = re.search(r'(.+)', data)
        if m and os.path.exists(git_p4_ref):
            port = m.group(1)
            self.type = 'perforce'
            self.upstream_branch = 'remotes/p4/master'
            return RepositoryInfo(path=port,
                                  base_path='',
                                  supports_parent_diffs=True)

        # Nope, it's git then.
        # Check for a tracking branch and determine merge-base
        self.upstream_branch = ''
        if self.head_ref:
            short_head = self._strip_heads_prefix(self.head_ref)
            merge = execute(
                [self.git, 'config', '--get',
                 'branch.%s.merge' % short_head],
                ignore_errors=True).strip()
            remote = execute(
                [self.git, 'config', '--get',
                 'branch.%s.remote' % short_head],
                ignore_errors=True).strip()

            merge = self._strip_heads_prefix(merge)

            if remote and remote != '.' and merge:
                self.upstream_branch = '%s/%s' % (remote, merge)

        url = None
        if getattr(self.options, 'repository_url', None):
            url = self.options.repository_url
            self.upstream_branch = self.get_origin(self.upstream_branch,
                                                   True)[0]
        else:
            self.upstream_branch, origin_url = \
                self.get_origin(self.upstream_branch, True)

            if not origin_url or origin_url.startswith("fatal:"):
                self.upstream_branch, origin_url = self.get_origin()

            url = origin_url.rstrip('/')

            # Central bare repositories don't have origin URLs.
            # We return git_dir instead and hope for the best.
            if not url:
                url = os.path.abspath(git_dir)

                # There is no remote, so skip this part of upstream_branch.
                self.upstream_branch = self.upstream_branch.split('/')[-1]

        if url:
            self.type = "git"
            return RepositoryInfo(path=url,
                                  base_path='',
                                  supports_parent_diffs=True)

        return None
示例#30
0
    def get_repository_info(self):
        """Get repository information for the current Git working tree.

        Returns:
            rbtools.clients.RepositoryInfo:
            The repository info structure.
        """
        # Temporarily reset the toplevel. This is necessary for making things
        # work correctly in unit tests where we may be moving the cwd around a
        # lot.
        self._git_toplevel = None

        if not check_install(['git', '--help']):
            # CreateProcess (launched via subprocess, used by check_install)
            # does not automatically append .cmd for things it finds in PATH.
            # If we're on Windows, and this works, save it for further use.
            if (sys.platform.startswith('win') and
                check_install(['git.cmd', '--help'])):
                self.git = 'git.cmd'
            else:
                logging.debug('Unable to execute "git --help" or "git.cmd '
                              '--help": skipping Git')
                return None

        git_dir = self._execute([self.git, 'rev-parse', '--git-dir'],
                                ignore_errors=True).rstrip('\n')

        if git_dir.startswith('fatal:') or not os.path.isdir(git_dir):
            return None

        # Sometimes core.bare is not set, and generates an error, so ignore
        # errors. Valid values are 'true' or '1'.
        bare = execute([self.git, 'config', 'core.bare'],
                       ignore_errors=True).strip()
        self.bare = bare in ('true', '1')

        # Running in directories other than the top level of
        # of a work-tree would result in broken diffs on the server
        if not self.bare:
            git_top = execute([self.git, 'rev-parse', '--show-toplevel'],
                              ignore_errors=True).rstrip('\n')

            # Top level might not work on old git version se we use git dir
            # to find it.
            if (git_top.startswith(('fatal:', 'cygdrive')) or
                not os.path.isdir(git_dir)):
                git_top = git_dir

            self._git_toplevel = os.path.abspath(git_top)

        self._head_ref = self._execute(
            [self.git, 'symbolic-ref', '-q', 'HEAD'],
            ignore_errors=True).strip()

        # We know we have something we can work with. Let's find out
        # what it is. We'll try SVN first, but only if there's a .git/svn
        # directory. Otherwise, it may attempt to create one and scan
        # revisions, which can be slow. Also skip SVN detection if the git
        # repository was specified on command line.
        git_svn_dir = os.path.join(git_dir, 'svn')

        if (not getattr(self.options, 'repository_url', None) and
            os.path.isdir(git_svn_dir) and
            len(os.listdir(git_svn_dir)) > 0):
            data = self._execute([self.git, 'svn', 'info'], ignore_errors=True)

            m = re.search(r'^Repository Root: (.+)$', data, re.M)

            if m:
                path = m.group(1)
                m = re.search(r'^URL: (.+)$', data, re.M)

                if m:
                    base_path = m.group(1)[len(path):] or '/'
                    m = re.search(r'^Repository UUID: (.+)$', data, re.M)

                    if m:
                        uuid = m.group(1)
                        self._type = self.TYPE_GIT_SVN

                        m = re.search(r'Working Copy Root Path: (.+)$', data,
                                      re.M)

                        if m:
                            local_path = m.group(1)
                        else:
                            local_path = self._git_toplevel

                        return SVNRepositoryInfo(path=path,
                                                 base_path=base_path,
                                                 local_path=local_path,
                                                 uuid=uuid,
                                                 supports_parent_diffs=True)
            else:
                # Versions of git-svn before 1.5.4 don't (appear to) support
                # 'git svn info'.  If we fail because of an older git install,
                # here, figure out what version of git is installed and give
                # the user a hint about what to do next.
                version = self._execute([self.git, 'svn', '--version'],
                                        ignore_errors=True)
                version_parts = re.search('version (\d+)\.(\d+)\.(\d+)',
                                          version)
                svn_remote = self._execute(
                    [self.git, 'config', '--get', 'svn-remote.svn.url'],
                    ignore_errors=True)

                if (version_parts and svn_remote and
                    not is_valid_version((int(version_parts.group(1)),
                                          int(version_parts.group(2)),
                                          int(version_parts.group(3))),
                                         (1, 5, 4))):
                    raise SCMError('Your installation of git-svn must be '
                                   'upgraded to version 1.5.4 or later.')

        # Okay, maybe Perforce (git-p4).
        git_p4_ref = os.path.join(git_dir, 'refs', 'remotes', 'p4', 'master')
        if os.path.exists(git_p4_ref):
            data = self._execute([self.git, 'config', '--get', 'git-p4.port'],
                                 ignore_errors=True)
            m = re.search(r'(.+)', data)
            if m:
                port = m.group(1)
            else:
                port = os.getenv('P4PORT')

            if port:
                self._type = self.TYPE_GIT_P4
                return RepositoryInfo(path=port,
                                      base_path='',
                                      local_path=self._git_toplevel,
                                      supports_parent_diffs=True)

        # Nope, it's git then.
        # Check for a tracking branch and determine merge-base
        self._type = self.TYPE_GIT
        url = None

        if getattr(self.options, 'repository_url', None):
            url = self.options.repository_url
        else:
            upstream_branch = self._get_parent_branch()
            url = self._get_origin(upstream_branch).rstrip('/')

            if url.startswith('fatal:'):
                raise SCMError('Could not determine remote URL for upstream '
                               'branch %s' % upstream_branch)

            # Central bare repositories don't have origin URLs.
            # We return git_dir instead and hope for the best.
            if not url:
                url = os.path.abspath(git_dir)

        if url:
            return RepositoryInfo(path=url,
                                  base_path='',
                                  local_path=self._git_toplevel,
                                  supports_parent_diffs=True)
        return None
示例#31
0
文件: svn.py 项目: halvorlu/rbtools
 def __init__(self, path, base_path, uuid, supports_parent_diffs=False):
     RepositoryInfo.__init__(self, path, base_path,
                             supports_parent_diffs=supports_parent_diffs)
     self.uuid = uuid