Пример #1
0
def create_release_vcs(path, vcs_name=None):
    """Return a new release VCS that can release from this source path."""
    from rez.plugin_managers import plugin_manager
    vcs_types = get_release_vcs_types()
    if vcs_name:
        if vcs_name not in vcs_types:
            raise ReleaseVCSError("Unknown version control system: %r" % vcs_name)
        cls = plugin_manager.get_plugin_class('release_vcs', vcs_name)
        return cls(path)

    clss = []
    for vcs_name in vcs_types:
        cls = plugin_manager.get_plugin_class('release_vcs', vcs_name)
        if cls.is_valid_root(path):
            clss.append(cls)
    if len(clss) > 1:
        clss_str = ", ".join(x.name() for x in clss)
        raise ReleaseVCSError("Several version control systems are associated "
                              "with the path %s: %s. Use rez-release --vcs to "
                              "choose." % (path, clss_str))
    elif not clss:
        raise ReleaseVCSError("No version control system for package "
                              "releasing is associated with the path %s" % path)
    else:
        return clss[0](path)
Пример #2
0
def get_last_changed_revision(client, url):
    """
    util func, get last revision of url
    """
    try:
        svn_entries = client.info2(url,
                                   pysvn.Revision(pysvn.opt_revision_kind.head),
                                   recurse=False)
        if not svn_entries:
            raise ReleaseVCSError("svn.info2() returned no results on url %s" % url)
        return svn_entries[0][1].last_changed_rev
    except pysvn.ClientError, ce:
        raise ReleaseVCSError("svn.info2() raised ClientError: %s" % ce)
Пример #3
0
    def validate_repostate(self):
        b = self.git("rev-parse", "--is-bare-repository")
        if b == "true":
            raise ReleaseVCSError("Could not release: bare git repository")

        remote, remote_branch = self.get_tracking_branch()

        # check for upstream branch
        if remote is None and not self.settings.allow_no_upstream:
            raise ReleaseVCSError(
                "Release cancelled: there is no upstream branch (git cannot see "
                "a remote repo - you should probably FIX THIS FIRST!). To allow "
                "the release, set the config entry "
                "'plugins.release_vcs.git.allow_no_upstream' to true.")

        # check we are releasing from a valid branch
        releasable_branches = self.type_settings.releasable_branches
        if releasable_branches:
            releasable = False
            current_branch_name = self.get_local_branch()
            for releasable_branch in releasable_branches:
                if re.search(releasable_branch, current_branch_name):
                    releasable = True
                    break

            if not releasable:
                raise ReleaseVCSError(
                    "Could not release: current branch is %s, must match "
                    "one of: %s"
                    % (current_branch_name, ', '.join(releasable_branches)))

        # check for uncommitted changes
        try:
            self.git("diff-index", "--quiet", "HEAD")
        except ReleaseVCSError:
            msg = "Could not release: there are uncommitted changes:\n"
            statmsg = self.git("diff-index", "--stat", "HEAD")
            msg += '\n'.join(statmsg)
            raise ReleaseVCSError(msg)

        # check if we are behind/ahead of remote
        if remote:
            self.git("remote", "update")
            n = self.get_relative_to_remote()
            if n:
                s = "ahead of" if n > 0 else "behind"
                remote_uri = '/'.join((remote, remote_branch))
                raise ReleaseVCSError(
                    "Could not release: %d commits %s %s."
                    % (abs(n), s, remote_uri))
Пример #4
0
 def find_executable(cls, name):
     exe = which(name)
     if not exe:
         raise ReleaseVCSError(
             "Couldn't find executable '%s' for VCS '%s'" %
             (name, cls.name()))
     return exe
Пример #5
0
    def _cmd(self, *nargs):
        """Convenience function for executing a program such as 'git' etc."""
        cmd_str = ' '.join(map(quote, nargs))

        if self.package.config.debug("package_release"):
            print_debug("Running command: %s" % cmd_str)

        p = Popen(nargs,
                  stdout=subprocess.PIPE,
                  stderr=subprocess.PIPE,
                  cwd=self.pkg_root,
                  text=True)
        out, err = p.communicate()

        if p.returncode:
            print_debug("command stdout:")
            print_debug(out)
            print_debug("command stderr:")
            print_debug(err)
            raise ReleaseVCSError("command failed: %s\n%s" % (cmd_str, err))
        out = out.strip()
        if out:
            return [x.rstrip() for x in out.split('\n')]
        else:
            return []
Пример #6
0
def create_release_vcs(path, vcs_name=None):
    """Return a new release VCS that can release from this source path."""
    from rez.plugin_managers import plugin_manager
    vcs_types = get_release_vcs_types()
    if vcs_name:
        if vcs_name not in vcs_types:
            raise ReleaseVCSError("Unknown version control system: %r" %
                                  vcs_name)
        cls = plugin_manager.get_plugin_class('release_vcs', vcs_name)
        return cls(path)

    classes_by_level = {}
    for vcs_name in vcs_types:
        cls = plugin_manager.get_plugin_class('release_vcs', vcs_name)
        result = cls.find_vcs_root(path)
        if not result:
            continue
        vcs_path, levels_up = result
        classes_by_level.setdefault(levels_up, []).append((cls, vcs_path))

    if not classes_by_level:
        raise ReleaseVCSError("No version control system for package "
                              "releasing is associated with the path %s" %
                              path)

    # it's ok to have multiple results, as long as there is only one at the
    # "closest" directory up from this dir - ie, if we start at:
    #    /blah/foo/pkg_root
    # and these dirs exist:
    #    /blah/.hg
    #    /blah/foo/.git
    # ...then this is ok, because /blah/foo/.git is "closer" to the original
    # dir, and will be picked. However, if these two directories exist:
    #    /blah/foo/.git
    #    /blah/foo/.hg
    # ...then we error, because we can't decide which to use

    lowest_level = sorted(classes_by_level)[0]
    clss = classes_by_level[lowest_level]
    if len(clss) > 1:
        clss_str = ", ".join(x[0].name() for x in clss)
        raise ReleaseVCSError("Several version control systems are associated "
                              "with the path %s: %s. Use rez-release --vcs to "
                              "choose." % (path, clss_str))
    else:
        cls, vcs_root = clss[0]
        return cls(pkg_root=path, vcs_root=vcs_root)
Пример #7
0
 def _url(op):
     origin = doc["tracking_branch"].split('/')[0]
     lines = self.git("remote", "-v")
     lines = [x for x in lines if origin in x.split()]
     lines = [x for x in lines if ("(%s)" % op) in x.split()]
     try:
         return lines[0].split()[1]
     except:
         raise ReleaseVCSError("failed to parse %s url from:\n%s" %
                               (op, '\n'.join(lines)))
Пример #8
0
    def validate_repostate(self):
        status_list = self.svnc.status(self.pkg_root, get_all=False, update=True)
        status_list_known = []

        for status in status_list:
            if status.entry:
                status_list_known.append(status)

        if status_list_known:
            raise ReleaseVCSError(
                "'%s' is not in a state to release - you may need to svn-checkin "
                "and/or svn-update: %s" % (self.pkg_root, str(status_list_known)))
Пример #9
0
    def get_tag_url(self, tag_name=None):
        # find the base path, ie where 'trunk', 'branches', 'tags' should be
        pos_tr = self.this_url.find("/trunk")
        pos_br = self.this_url.find("/branches")
        pos = max(pos_tr, pos_br)
        if (pos == -1):
            raise ReleaseVCSError("%s is not in a branch or trunk" % self.pkg_root)
        base_url = self.this_url[:pos]
        tag_url = base_url + "/tags"

        if tag_name:
            tag_url += '/' + tag_name
        return tag_url
Пример #10
0
    def __init__(self, pkg_root, vcs_root=None):
        if vcs_root is None:
            result = self.find_vcs_root(pkg_root)
            if not result:
                raise ReleaseVCSError("Could not find %s repository for the "
                                      "path %s" % (self.name(), pkg_root))
            vcs_root = result[0]
        else:
            assert (self.is_valid_root(vcs_root))

        self.vcs_root = vcs_root
        self.pkg_root = pkg_root
        self.package = get_developer_package(pkg_root)
        self.type_settings = self.package.config.plugins.release_vcs
        self.settings = self.type_settings.get(self.name())
Пример #11
0
 def get_relative_to_remote(self):
     """Return the number of commits we are relative to the remote. Negative
     is behind, positive in front, zero means we are matched to remote.
     """
     s = self.git("status", "--short", "-b")[0]
     r = re.compile("\[([^\]]+)\]")
     toks = r.findall(s)
     if toks:
         try:
             s2 = toks[-1]
             adj, n = s2.split()
             assert (adj in ("ahead", "behind"))
             n = int(n)
             return -n if adj == "behind" else n
         except Exception as e:
             raise ReleaseVCSError(
                 ("Problem parsing first line of result of 'git status "
                  "--short -b' (%s):\n%s") % (s, str(e)))
     else:
         return 0
Пример #12
0
 def _check(modified, path):
     if modified:
         modified = [line.split()[-1] for line in modified]
         raise ReleaseVCSError(
             "%s is not in a state to release - please commit outstanding "
             "changes: %s" % (path, ', '.join(modified)))