예제 #1
0
파일: vc.py 프로젝트: kaday/rose
    def checkout(self, id_):
        """Create a local copy of a suite with the given ID.

        Return the SuiteId of the suite on success.

        """
        if isinstance(id_, str):
            id_ = SuiteId(id_text=id_)
        if id_.revision is None:
            id_.revision = id_.REV_HEAD
        if id_.branch is None:
            id_.branch = id_.BRANCH_TRUNK
        local_copy = id_.to_local_copy()
        if os.path.exists(local_copy):
            id0 = SuiteId(location=local_copy)
            if id_.to_string_with_version() == id0.to_string_with_version():
                self.event_handler(LocalCopyCreateSkipEvent(id_))
                return id_
            elif self.force_mode:
                self.fs_util.delete(local_copy)
            else:
                raise FileExistError(local_copy)
        local_copy_dir = os.path.dirname(local_copy)
        if not os.path.isdir(local_copy_dir):
            self.fs_util.makedirs(os.path.dirname(local_copy))
        origin = "%s/%s@%s" % (id_.to_origin(), id_.branch, id_.revision)
        self.popen("svn", "checkout", "-q", origin, local_copy)
        self.event_handler(LocalCopyCreateEvent(id_))
        return id_
예제 #2
0
파일: vc.py 프로젝트: jimbolton/rose
    def delete(self, id, local_only=False):
        """Delete the local copy and the origin of a suite.
        
        It takes the suite ID as an argument.
        Return the SuiteId of the suite on success.

        """
        if isinstance(id, str):
            id = SuiteId(id_text=id)
        local_copy = id.to_local_copy()
        if os.path.exists(local_copy):
            if not self.force_mode:
                status = self.popen("svn", "status", local_copy)[0]
                if status:
                    raise LocalCopyStatusError(id, status)
            if os.getcwd() == local_copy:
                # TODO: Event?
                os.chdir(os.path.expanduser("~"))
            shutil.rmtree(local_copy)
            self.event_handler(FileDeleteEvent(local_copy))
        if not local_only:    
            self.popen("svn", "delete",
                       "-q", "-m", "%s: deleted." % str(id),
                       id.to_origin())
            self.event_handler(SuiteDeleteEvent(id))
        return id
예제 #3
0
파일: vc.py 프로젝트: benfitzpatrick/rose
    def delete(self, id_, local_only=False):
        """Delete the local copy and the origin of a suite.

        It takes the suite ID as an argument.
        Return the SuiteId of the suite on success.

        """
        if isinstance(id_, str):
            id_ = SuiteId(id_text=id_)
        local_copy = id_.to_local_copy()
        if os.path.exists(local_copy):
            if not self.force_mode:
                status = self.popen("svn", "status", local_copy)[0]
                if status:
                    raise LocalCopyStatusError(id_, status)
            if os.getcwd() == local_copy:
                self.fs_util.chdir(os.path.expanduser("~"))
            self.fs_util.delete(local_copy)
        if not local_only:
            self.popen(
                "svn", "delete", "-q",
                "-m", self.COMMIT_MESSAGE_DELETE % str(id_),
                id_.to_origin())
            self.event_handler(SuiteDeleteEvent(id_))
        return id_
예제 #4
0
파일: vc.py 프로젝트: scwhitehouse/rose
    def delete(self, id_, local_only=False):
        """Delete the local copy and the origin of a suite.

        It takes the suite ID as an argument.
        Return the SuiteId of the suite on success.

        """
        if isinstance(id_, str):
            id_ = SuiteId(id_text=id_)
        local_copy = id_.to_local_copy()
        if os.path.exists(local_copy):
            if not self.force_mode:
                status = self.popen("svn", "status", local_copy)[0]
                if status:
                    raise LocalCopyStatusError(id_, status)
            if os.getcwd() == local_copy:
                self.fs_util.chdir(os.path.expanduser("~"))
            self.fs_util.delete(local_copy)
        if not local_only:
            self.popen(
                "svn", "delete", "-q",
                "-m", self.COMMIT_MESSAGE_DELETE % str(id_),
                id_.to_origin())
            self.event_handler(SuiteDeleteEvent(id_))
        return id_
예제 #5
0
파일: vc.py 프로젝트: csimag/rose
def create(argv):
    """CLI function: create and copy."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("checkout_mode", "info_file",
                              "meta_suite_mode", "non_interactive", "prefix")
    opts, args = opt_parser.parse_args(argv)
    verbosity = opts.verbosity - opts.quietness
    report = Reporter(verbosity)
    client = RosieVCClient(event_handler=report)
    SuiteId.svn.event_handler = client.event_handler # FIXME: ugly?
    from_id = None
    if args:
        from_id = SuiteId(id_text=args[0])
        if from_id.branch is None:
            from_id.branch = from_id.BRANCH_TRUNK
        if from_id.revision is None:
            from_id.revision = from_id.REV_HEAD
            from_id = SuiteId(id_text=from_id.to_string_with_version())
    if opts.info_file is None:
        try:
            info_config = client.generate_info_config(from_id, opts.prefix)
        except (RosePopenError) as e:
            report(e)
            sys.exit(1)
        info_file = tempfile.NamedTemporaryFile(delete=False)
        try:
            rose.config.dump(info_config, info_file)
            info_file.close()
            command_list = client.popen.get_cmd("editor", info_file.name)
            client.popen(*command_list, stdout=sys.stdout)
            info_config = rose.config.load(info_file.name)
        finally:
            os.unlink(info_file.name)
    elif opts.info_file == "-":
        info_config = rose.config.load(sys.stdin)
    else:
        info_config = rose.config.load(opts.info_file)
    if not opts.non_interactive:
        try:
            response = raw_input("Create? y/n (default n) ")
        except EOFError:
            sys.exit(1)
        if response != 'y':
            sys.exit(1)
    try:
        id = client.create(info_config, from_id, opts.prefix,
                           opts.meta_suite_mode)
    except (RosePopenError, SuiteInfoFieldError, SuiteIdOverflowError) as e:
        report(e)
        sys.exit(1)
    if opts.checkout_mode:
        try:
            client.checkout(id)
        except (FileExistError, RosePopenError) as e:
            report(e)
            sys.exit(1)
예제 #6
0
파일: vc.py 프로젝트: csimag/rose
    def create(self, info_config, from_id=None, prefix=None,
               meta_suite_mode=False):
        """Create a suite.

        info_config -- A rose.config.ConfigNode object, which will be used as
                       the content of the "rose-suite.info" file of the new
                       suite.
        from_id -- If defined, copy items from it.
        prefix -- If defined, create the suite in the suite repository named by
                  the prefix instead of the default one.
        meta_suite_mode -- If True, create the special metadata suite.
                           Ignored if from_id is not None.

        Return the SuiteId of the suite on success.

        """
        for key in ["owner", "project", "title"]:
            if not info_config.get([key], no_ignore=True):
                raise SuiteInfoFieldError(key)
        if from_id is not None:
            return self._copy(info_config, from_id)
        new_id = None
        while new_id is None:
            if meta_suite_mode:
                if prefix is None:
                    new_id = SuiteId(id_text="ROSIE")
                else:
                    idx = SuiteId.FORMAT_IDX % (prefix, "ROSIE")
                    new_id = SuiteId(id_text=idx)
            else:
                new_id = SuiteId.get_next(prefix)
            new_origin = new_id.to_origin() + "/" + new_id.BRANCH_TRUNK
            dir = self._get_work_dir()
            rose.config.dump(info_config, os.path.join(dir, "rose-suite.info"))
            open(os.path.join(dir, "rose-suite.conf"), "w").close()
            try:
                self.popen("svn", "import",
                           "-q",
                           "-m", "%s: new suite." % str(new_id),
                           dir,
                           new_origin)
                self.event_handler(SuiteCreateEvent(new_id))
            except RosePopenError as e:
                try:
                    self.popen("svn", "info", new_origin)
                    if not meta_suite_mode:
                        new_id = None
                except RosePopenError:
                    raise e
            finally:
                self._delete_work_dir()
        return new_id
예제 #7
0
파일: vc.py 프로젝트: jimbolton/rose
    def checkout(self, id):
        """Create a local copy of a suite with the given ID.

        Return the SuiteId of the suite on success.

        """
        if isinstance(id, str):
            id = SuiteId(id_text=id)
        if id.revision is None:
            id.revision = id.REV_HEAD
        if id.branch is None:
            id.branch = id.BRANCH_TRUNK
        local_copy = id.to_local_copy()
        if os.path.exists(local_copy):
            id0 = SuiteId(location=local_copy)
            if id.to_string_with_version() == id0.to_string_with_version():
                self.event_handler(LocalCopyCreateSkipEvent(id))
                return id
            elif self.force_mode:
                if os.path.isfile(local_copy):
                    unlink(local_copy)
                else:
                    shutil.rmtree(local_copy)
                self.event_handler(FileDeleteEvent(local_copy))
            else:
                raise FileExistError(local_copy)
        local_copy_dir = os.path.dirname(local_copy)
        if not os.path.isdir(local_copy_dir):
            os.makedirs(os.path.dirname(local_copy))
            self.event_handler(FileCreateEvent(local_copy_dir))
        origin = id.to_origin() + "/" + id.branch + "@" + id.revision
        self.popen("svn", "checkout", "-q", origin, local_copy)
        self.event_handler(LocalCopyCreateEvent(id))
        return id
예제 #8
0
파일: vc.py 프로젝트: benfitzpatrick/rose
    def checkout(self, id_):
        """Create a local copy of a suite with the given ID.

        Return the SuiteId of the suite on success.

        """
        if isinstance(id_, str):
            id_ = SuiteId(id_text=id_)
        if id_.revision is None:
            id_.revision = id_.REV_HEAD
        if id_.branch is None:
            id_.branch = id_.BRANCH_TRUNK
        local_copy = id_.to_local_copy()
        if os.path.exists(local_copy):
            id0 = SuiteId(location=local_copy)
            if id_.to_string_with_version() == id0.to_string_with_version():
                self.event_handler(LocalCopyCreateSkipEvent(id_))
                return id_
            elif self.force_mode:
                self.fs_util.delete(local_copy)
            else:
                raise FileExistError(local_copy)
        local_copy_dir = os.path.dirname(local_copy)
        if not os.path.isdir(local_copy_dir):
            self.fs_util.makedirs(os.path.dirname(local_copy))
        origin = "%s/%s@%s" % (id_.to_origin(), id_.branch, id_.revision)
        self.popen("svn", "checkout", "-q", origin, local_copy)
        self.event_handler(LocalCopyCreateEvent(id_))
        return id_
예제 #9
0
 def update(self):
     """Get info and communicate any change."""
     local_suites = SuiteId.get_checked_out_suite_ids()
     if local_suites == self.local_suites:
         return
     self.local_suites = local_suites
     self.queue.put(local_suites)
예제 #10
0
파일: status.py 프로젝트: hjoliver/rose
 def update(self):
     """Get info and communicate any change."""
     local_suites = SuiteId.get_checked_out_suite_ids()
     if local_suites == self.local_suites:
         return
     self.local_suites = local_suites
     self.queue.put(local_suites)
예제 #11
0
파일: ws.py 프로젝트: matthewrmshin/rose
 def _render(self, all_revs=0, data=None, filters=None, s=None):
     """Render return data with a template."""
     if data:
         for item in data:
             suite_id = SuiteId.from_idx_branch_revision(
                 item["idx"], item["branch"], item["revision"])
             item["href"] = suite_id.to_web()
             item["date"] = str(get_timepoint_from_seconds_since_unix_epoch(
                 item["date"]))
     tmpl = self.props["template_env"].get_template("prefix-index.html")
     self.write(tmpl.render(
         title=self.props["title"],
         host=self.props["host_name"],
         rose_version=self.props["rose_version"],
         script="/static",
         service_root=self.service_root,
         prefix=self.prefix,
         prefix_source_url=self.source_url,
         known_keys=self.dao.get_known_keys(),
         query_operators=self.dao.get_query_operators(),
         all_revs=all_revs,
         filters=filters,
         s=s,
         data=data)
     )
예제 #12
0
파일: ws_client.py 프로젝트: lexual/rose
    def query_local_copies(self, user=None):
        """Returns details of the local suites.

        As if they had been obtained using a search or query.

        """
        suite_ids = []
        for suite_id in SuiteId.get_checked_out_suite_ids(user=user):
            if suite_id.prefix in self.prefixes:
                suite_ids.append(suite_id)
        if not suite_ids:
            return []

        # Simple query
        results = []
        queued_suite_ids = list(suite_ids)
        while queued_suite_ids:  # Batch up queries
            q_list = []
            for _ in range(self.MAX_LOCAL_QUERIES):
                if not queued_suite_ids:
                    break
                suite_id = queued_suite_ids.pop()
                q_list.append("or ( idx eq %s" % suite_id.idx)
                q_list.append("and branch eq %s )" % suite_id.branch)
            for data, _ in self.query(q_list):
                results.extend(data)
        result_idx_branches = []
        for result in results:
            result_idx_branches.append((result[u"idx"], result[u"branch"]))

        # A branch may have been deleted - query with all_revs=1.
        # We only want to use all_revs on demand as it's slow.
        queued_suite_ids = []
        for suite_id in suite_ids:
            if (suite_id.idx, suite_id.branch) not in result_idx_branches:
                queued_suite_ids.append(suite_id)
        if not queued_suite_ids:
            return results
        while queued_suite_ids:  # Batch up queries
            q_list = []
            for _ in range(self.MAX_LOCAL_QUERIES):
                if not queued_suite_ids:
                    break
                suite_id = queued_suite_ids.pop()
                q_list.append("or ( idx eq %s" % suite_id.idx)
                q_list.append("and branch eq %s )" % suite_id.branch)
            more_results = []
            for data, _ in self.query(q_list, all_revs=1):
                more_results.extend(data)
            new_results = {}
            for result in more_results:
                idx_branch = (result[u"idx"], result[u"branch"])
                if (idx_branch not in new_results or
                        result[u"revision"] >
                        new_results[idx_branch][u"revision"]):
                    new_results.update({idx_branch: result})
            for _, result in sorted(new_results.items()):
                results.append(result)
        return results
예제 #13
0
    def query_local_copies(self, user=None):
        """Returns details of the local suites.

        As if they had been obtained using a search or query.

        """
        suite_ids = []
        for suite_id in SuiteId.get_checked_out_suite_ids(user=user):
            if suite_id.prefix in self.prefixes:
                suite_ids.append(suite_id)
        if not suite_ids:
            return []

        # Simple query
        results = []
        queued_suite_ids = list(suite_ids)
        while queued_suite_ids:  # Batch up queries
            q_list = []
            for _ in range(self.MAX_LOCAL_QUERIES):
                if not queued_suite_ids:
                    break
                suite_id = queued_suite_ids.pop()
                q_list.append("or ( idx eq %s" % suite_id.idx)
                q_list.append("and branch eq %s )" % suite_id.branch)
            for data, _ in self.query(q_list):
                results.extend(data)
        result_idx_branches = []
        for result in results:
            result_idx_branches.append((result[u"idx"], result[u"branch"]))

        # A branch may have been deleted - query with all_revs=1.
        # We only want to use all_revs on demand as it's slow.
        queued_suite_ids = []
        for suite_id in suite_ids:
            if (suite_id.idx, suite_id.branch) not in result_idx_branches:
                queued_suite_ids.append(suite_id)
        if not queued_suite_ids:
            return results
        while queued_suite_ids:  # Batch up queries
            q_list = []
            for _ in range(self.MAX_LOCAL_QUERIES):
                if not queued_suite_ids:
                    break
                suite_id = queued_suite_ids.pop()
                q_list.append("or ( idx eq %s" % suite_id.idx)
                q_list.append("and branch eq %s )" % suite_id.branch)
            more_results = []
            for data, _ in self.query(q_list, all_revs=1):
                more_results.extend(data)
            new_results = {}
            for result in more_results:
                idx_branch = (result[u"idx"], result[u"branch"])
                if (idx_branch not in new_results or result[u"revision"] >
                        new_results[idx_branch][u"revision"]):
                    new_results.update({idx_branch: result})
            for _, result in sorted(new_results.items()):
                results.append(result)
        return results
예제 #14
0
파일: ws_client.py 프로젝트: jimbolton/rose
 def __init__(self, root=None, prefix=None):
     if root is None:
         config = rose.config.default_node()
         node = config.get(["rosie-ws-client", "ws-root-default"])
         root = node.value
     self.root = root
     if prefix is None:
         prefix = SuiteId.get_prefix_default()
     self.prefix = prefix
예제 #15
0
파일: vc.py 프로젝트: benfitzpatrick/rose
 def _copy1(self, info_config, from_id):
     """Copy a suite from the same repository."""
     from_id_url = "%s/%s@%s" % (from_id.to_origin(), from_id.branch,
                                 from_id.revision)
     self.popen("svn", "info", from_id_url)  # Die if from_id not exists
     prefix = from_id.prefix
     temp_local_copy = os.path.join(self._get_work_dir(), "work")
     new_id = None
     # N.B. This is probably the simplest logic to maintain,
     #      but not the most efficient for runtime. Does it matter?
     while new_id is None:
         if os.path.exists(temp_local_copy):
             shutil.rmtree(temp_local_copy)
         self.popen("svn", "checkout", "-q", "--depth", "empty",
                    SuiteId.get_prefix_location(prefix), temp_local_copy)
         new_id = SuiteId.get_next(prefix)
         for i in range(len(new_id.sid)):
             dir_ = os.path.join(
                 temp_local_copy, os.sep.join(new_id.sid[0:i + 1]))
             self.popen("svn", "update", "-q", "--depth", "empty", dir_)
             if not os.path.isdir(dir_):
                 os.mkdir(dir_)
                 self.popen("svn", "add", "-q", dir_)
         dir_ = os.path.join(temp_local_copy, os.sep.join(new_id.sid))
         self.popen(
             "svn", "cp", "-q", from_id_url, os.path.join(dir_, "trunk"))
         rose.config.dump(
             info_config, os.path.join(dir_, "trunk", "rose-suite.info"))
         message = self.COMMIT_MESSAGE_COPY % (
             new_id, from_id.to_string_with_version())
         try:
             self.popen(
                 "svn", "commit", "-q", "-m", message, temp_local_copy)
             self.event_handler(SuiteCreateEvent(new_id))
             self.event_handler(SuiteCopyEvent(new_id, from_id))
         except RosePopenError as exc:
             try:
                 self.popen("svn", "info", new_id.to_origin())
                 new_id = None
             except RosePopenError:
                 raise exc
         finally:
             self._delete_work_dir()
     return new_id
예제 #16
0
파일: vc.py 프로젝트: kaday/rose
 def _copy1(self, info_config, from_id):
     """Copy a suite from the same repository."""
     from_id_url = "%s/%s@%s" % (from_id.to_origin(), from_id.branch,
                                 from_id.revision)
     self.popen("svn", "info", from_id_url)  # Die if from_id not exists
     prefix = from_id.prefix
     temp_local_copy = os.path.join(self._get_work_dir(), "work")
     new_id = None
     # N.B. This is probably the simplest logic to maintain,
     #      but not the most efficient for runtime. Does it matter?
     while new_id is None:
         if os.path.exists(temp_local_copy):
             shutil.rmtree(temp_local_copy)
         self.popen("svn", "checkout", "-q", "--depth", "empty",
                    SuiteId.get_prefix_location(prefix), temp_local_copy)
         new_id = SuiteId.get_next(prefix)
         for i in range(len(new_id.sid)):
             dir_ = os.path.join(temp_local_copy,
                                 os.sep.join(new_id.sid[0:i + 1]))
             self.popen("svn", "update", "-q", "--depth", "empty", dir_)
             if not os.path.isdir(dir_):
                 os.mkdir(dir_)
                 self.popen("svn", "add", "-q", dir_)
         dir_ = os.path.join(temp_local_copy, os.sep.join(new_id.sid))
         self.popen("svn", "cp", "-q", from_id_url,
                    os.path.join(dir_, "trunk"))
         rose.config.dump(info_config,
                          os.path.join(dir_, "trunk", "rose-suite.info"))
         message = self.COMMIT_MESSAGE_COPY % (
             new_id, from_id.to_string_with_version())
         try:
             self.popen("svn", "commit", "-q", "-m", message,
                        temp_local_copy)
             self.event_handler(SuiteCreateEvent(new_id))
             self.event_handler(SuiteCopyEvent(new_id, from_id))
         except RosePopenError as exc:
             try:
                 self.popen("svn", "info", new_id.to_origin())
                 new_id = None
             except RosePopenError:
                 raise exc
         finally:
             self._delete_work_dir()
     return new_id
예제 #17
0
 def __init__(self, prefix=None):
     if prefix is None:
         prefix = SuiteId.get_prefix_default()
     self.prefix = prefix
     conf = ResourceLocator.default().get_conf()
     root = conf.get_value(["rosie-id", "prefix-ws." + self.prefix])
     if root is None:
         raise UnknownRootError(self.prefix)
     if not root.endswith("/"):
         root += "/"
     self.root = root
예제 #18
0
파일: util.py 프로젝트: csimag/rose
 def add_prefix_choices(self):
     """Add the prefix choices."""
     self.prefixes = SuiteId.get_prefix_locations().keys()
     self.prefixes.sort()
     self.prefixes.reverse()
     for prefix in self.prefixes:
         search = '<menu action="Source">'
         repl = search + '<menuitem action="_{0}_"/>'.format(prefix)
         self.ui_config_string = self.ui_config_string.replace(
                                         search, repl, 1)
         self.radio_action_details.append(
                           ("_{0}_".format(prefix), None, prefix))
예제 #19
0
 def add_prefix_choices(self):
     """Add the prefix choices."""
     self.prefixes = self.ws_client.auth_managers.keys()
     self.prefixes.sort()
     self.prefixes.reverse()
     for prefix in self.prefixes:
         source = '<menu action="Source">'
         repl = source + '<menuitem action="_{0}_"/>'.format(prefix)
         self.ui_config_string = self.ui_config_string.replace(
             source, repl, 1)
         label_str = prefix + " - " + SuiteId.get_prefix_location(prefix)
         self.prefixes_action_details.append(
             ("_{0}_".format(prefix), None, label_str.replace("_", "__")))
예제 #20
0
def list_local_suites(argv):
    """CLI command to list all the locally checked out suites"""
    opt_parser = RoseOptionParser().add_my_options(
        "no_headers", "prefixes", "print_format", "reverse", "sort", "user")
    opts = opt_parser.parse_args(argv)[0]
    report = Reporter(opts.verbosity - opts.quietness)

    if opts.user:
        alternative_roses_dir = SuiteId.get_local_copy_root(opts.user)
        report(UserSpecificRoses(alternative_roses_dir), prefix=None)

    ws_client = RosieWSClient(prefixes=opts.prefixes, event_handler=report)
    _display_maps(opts, ws_client, ws_client.query_local_copies(opts.user))
예제 #21
0
파일: util.py 프로젝트: dpmatthews/rose
 def add_prefix_choices(self):
     """Add the prefix choices."""
     self.prefixes = self.ws_client.auth_managers.keys()
     self.prefixes.sort()
     self.prefixes.reverse()
     for prefix in self.prefixes:
         source = '<menu action="Source">'
         repl = source + '<menuitem action="_{0}_"/>'.format(prefix)
         self.ui_config_string = self.ui_config_string.replace(
             source, repl, 1)
         label_str = prefix + " - " + SuiteId.get_prefix_location(prefix)
         self.prefixes_action_details.append((
             "_{0}_".format(prefix), None, label_str.replace("_", "__")))
예제 #22
0
def list_local_suites(argv):
    """CLI command to list all the locally checked out suites"""
    opt_parser = RoseOptionParser().add_my_options("no_headers", "prefixes",
                                                   "print_format", "reverse",
                                                   "sort", "user")
    opts = opt_parser.parse_args(argv)[0]
    report = Reporter(opts.verbosity - opts.quietness)

    if opts.user:
        alternative_roses_dir = SuiteId.get_local_copy_root(opts.user)
        report(UserSpecificRoses(alternative_roses_dir), prefix=None)

    ws_client = RosieWSClient(prefixes=opts.prefixes, event_handler=report)
    _display_maps(opts, ws_client, ws_client.query_local_copies(opts.user))
예제 #23
0
파일: ws_client.py 프로젝트: jimbolton/rose
def get_local_suites(prefix=None):
    """Returns a dict of prefixes and id tuples for locally-present suites."""
    local_copies = []
    local_copy_root = SuiteId.get_local_copy_root()
    if not os.path.isdir(local_copy_root):
        return local_copies
    for path in os.listdir(local_copy_root):
        location = os.path.join(local_copy_root, path)
        try:
            id = SuiteId(location=location)
        except SuiteIdError as e:
            continue
        if prefix is None or id.prefix == prefix:
            local_copies.append(id)
    return local_copies
예제 #24
0
파일: ws.py 프로젝트: craigmaclachlan/rose
 def _render(self, all_revs=0, data=None, filters=None, s=None):
     """Render return data with a template."""
     if data:
         for item in data:
             suite_id = SuiteId.from_idx_branch_revision(
                 item["idx"], item["branch"], item["revision"])
             item["href"] = suite_id.to_web()
     template = self.template_env.get_template("prefix-index.html")
     return template.render(web_prefix=cherrypy.request.script_name,
                            prefix=self.prefix,
                            prefix_source_url=self.source_url,
                            known_keys=self.dao.get_known_keys(),
                            query_operators=self.dao.get_query_operators(),
                            all_revs=all_revs,
                            filters=filters,
                            s=s,
                            data=data)
예제 #25
0
파일: ws.py 프로젝트: jmancell/rose
 def _render(self, all_revs=False, data=None, filters=None, s=None):
     if data:
         for item in data:
             suite_id = SuiteId.from_idx_branch_revision(
                 item["idx"], item["branch"], item["revision"])
             item["href"] = suite_id.to_web()
     template = self.template_env.get_template("prefix-index.html")
     return template.render(
                     web_prefix=cherrypy.request.script_name,
                     prefix=self.prefix,
                     prefix_source_url=self.source_url,
                     known_keys=self.dao.get_known_keys(),
                     query_operators=self.dao.get_query_operators(),
                     all_revs=all_revs,
                     filters=filters,
                     s=s,
                     data=data)
예제 #26
0
    def query_local_copies(self, user=None):
        """Returns details of the local suites.

        As if they had been obtained using a search or query.

        """
        suite_ids = []
        for suite_id in SuiteId.get_checked_out_suite_ids(user=user):
            if suite_id.prefix in self.prefixes:
                suite_ids.append(suite_id)
        if not suite_ids:
            return []

        q_list = []
        for suite_id in suite_ids:
            q_list.append("or ( idx eq %s" % suite_id.idx)
            q_list.append("and branch eq %s )" % suite_id.branch)
        results = []
        for data, _ in self.query(q_list):
            results.extend(data)
        result_idx_branches = []
        for result in results:
            result_idx_branches.append((result[u"idx"], result[u"branch"]))
        q_list = []
        for suite_id in suite_ids:
            if (suite_id.idx, suite_id.branch) in result_idx_branches:
                continue
                # A branch may have been deleted - we need all_revs=1.
                # We only want to use all_revs on demand as it's slow.
            q_list.append("or ( idx eq %s" % suite_id.idx)
            q_list.append("and branch eq %s )" % suite_id.branch)
        if q_list:
            more_results = []
            for data, _ in self.query(q_list, all_revs=1):
                more_results.extend(data)
            new_results = {}
            for result in more_results:
                idx_branch = (result[u"idx"], result[u"branch"])
                if (idx_branch not in new_results or
                        result[u"revision"] >
                        new_results[idx_branch][u"revision"]):
                    new_results.update({idx_branch: result})
            for _, result in sorted(new_results.items()):
                results.append(result)
        return results
예제 #27
0
 def _update_local_status_row(self, model, path, r_iter, data):
     """Update the status for a row of the treeview"""
     index_map, local_suites = data[0:2]
     idx = model.get_value(r_iter, index_map["idx"])
     branch = model.get_value(r_iter, index_map["branch"])
     revision = int(model.get_value(r_iter, index_map["revision"]))
     suite_id = SuiteId.from_idx_branch_revision(idx, branch, revision)
     status = suite_id.get_status()
     model.set_value(r_iter, index_map["local"], status)
     suite_id_text = suite_id.to_string_with_version()
     results = ""
     for line in self._result_info[idx, branch, revision].splitlines():
         if line == suite_id_text or ":" in line or not line:
             results += line + "\n"
         else:
             results += STATUS_TIP[status] + "\n"
     self._result_info[idx, branch, revision] = results
     return False
예제 #28
0
    def create(self, info_config, from_id=None, prefix=None,
               meta_suite_mode=False):
        """Create a suite.

        info_config -- A rose.config.ConfigNode object, which will be used as
                       the content of the "rose-suite.info" file of the new
                       suite.
        from_id -- If defined, copy items from it.
        prefix -- If defined, create the suite in the suite repository named by
                  the prefix instead of the default one.
        meta_suite_mode -- If True, create the special metadata suite.
                           Ignored if from_id is not None.

        Return the SuiteId of the suite on success.

        """
        for key in ["owner", "project", "title"]:
            if not info_config.get([key], no_ignore=True):
                raise SuiteInfoFieldError(key)
        if from_id is not None:
            return self._copy(info_config, from_id)
        new_id = None
        while new_id is None:
            if meta_suite_mode:
                if prefix is None:
                    new_id = SuiteId(id_text="ROSIE")
                else:
                    idx = SuiteId.FORMAT_IDX % (prefix, "ROSIE")
                    new_id = SuiteId(id_text=idx)
            else:
                new_id = SuiteId.get_next(prefix)
            new_origin = new_id.to_origin() + "/" + new_id.BRANCH_TRUNK
            dir = self._get_work_dir()
            rose.config.dump(info_config, os.path.join(dir, "rose-suite.info"))
            open(os.path.join(dir, "rose-suite.conf"), "w").close()
            try:
                self.popen("svn", "import",
                           "-q",
                           "-m", "%s: new suite." % str(new_id),
                           dir,
                           new_origin)
                self.event_handler(SuiteCreateEvent(new_id))
            except RosePopenError as e:
                try:
                    self.popen("svn", "info", new_origin)
                    if not meta_suite_mode:
                        new_id = None
                except RosePopenError:
                    raise e
            finally:
                self._delete_work_dir()
        return new_id
예제 #29
0
파일: result.py 프로젝트: ScottWales/rose
 def _update_local_status_row(self, model, path, r_iter, data):
     """Update the status for a row of the treeview"""
     index_map, local_suites = data[0:2]
     idx = model.get_value(r_iter, index_map["idx"])
     branch = model.get_value(r_iter, index_map["branch"])
     revision = int(model.get_value(r_iter, index_map["revision"]))
     suite_id = SuiteId.from_idx_branch_revision(idx, branch, revision)
     status = suite_id.get_status()
     model.set_value(r_iter, index_map["local"], status)
     suite_id_text = suite_id.to_string_with_version()
     results = ""
     for line in self._result_info[idx, branch, revision].splitlines():
         if line == suite_id_text or ":" in line or not line:
             results += line + "\n"
         else:
             results += STATUS_TIP[status] + "\n"
     self._result_info[idx, branch, revision] = results
     return False
예제 #30
0
def delete(argv):
    """CLI function: delete."""
    opt_parser = RoseOptionParser().add_my_options("force_mode",
                                                   "non_interactive",
                                                   "local_only")
    opts, args = opt_parser.parse_args(argv)
    report = Reporter(opts.verbosity - opts.quietness)
    client = RosieVCClient(event_handler=report, force_mode=opts.force_mode)
    SuiteId.svn.event_handler = client.event_handler # FIXME
    if not args:
        args.append(SuiteId(location=os.getcwd()))
    interactive_mode = not opts.non_interactive
    prompt = ("%s: delete local+repository copies? " +
              "y/n/a (default n, a=yes-to-all) ")
    if opts.local_only:
        prompt = "%s: delete local copy? y/n/a (default n, a=yes-to-all) "
    rc = 0
    for arg in args:
        if interactive_mode:
            try:
                response = raw_input(prompt % arg)
            except EOFError:
                rc = 1
                continue
            if response == 'a':
                interactive_mode = False
            elif response != 'y':
                rc = 1
                continue
        if opts.debug_mode:
            client.delete(arg, opts.local_only)
        else:
            try:
                client.delete(arg, opts.local_only)
            except (LocalCopyStatusError, RosePopenError,
                    SuiteIdPrefixError) as e:
                client.event_handler(e)
                rc = 1
                if not opts.force_mode:
                    sys.exit(1)
    if rc:
        sys.exit(rc)
예제 #31
0
파일: vc.py 프로젝트: kaday/rose
def delete(argv):
    """CLI function: delete."""
    opt_parser = RoseOptionParser().add_my_options("force_mode",
                                                   "non_interactive",
                                                   "local_only")
    opts, args = opt_parser.parse_args(argv)
    report = Reporter(opts.verbosity - opts.quietness)
    client = RosieVCClient(event_handler=report, force_mode=opts.force_mode)
    SuiteId.svn.event_handler = client.event_handler
    if not args:
        args.append(SuiteId(location=os.getcwd()))
    interactive_mode = not opts.non_interactive
    prompt = PROMPT_DELETE
    if opts.local_only:
        prompt = PROMPT_DELETE_LOCAL
    ret_code = 0
    for arg in args:
        if interactive_mode:
            try:
                response = raw_input(prompt % arg)
            except EOFError:
                ret_code = 1
                continue
            if response == YES_TO_ALL:
                interactive_mode = False
            elif response != YES:
                ret_code = 1
                continue
        if opts.debug_mode:
            client.delete(arg, opts.local_only)
        else:
            try:
                client.delete(arg, opts.local_only)
            except (LocalCopyStatusError, RosePopenError,
                    SuiteIdPrefixError) as exc:
                client.event_handler(exc)
                ret_code = 1
                if not opts.force_mode:
                    sys.exit(1)
    if ret_code:
        sys.exit(ret_code)
예제 #32
0
파일: ws_client.py 프로젝트: hjoliver/rose
 def __init__(self, prefix=None, popen=None, prompt_func=None):
     if prefix is None:
         prefix = SuiteId.get_prefix_default()
     self.prefix = prefix
     self.auth_manager = RosieWSClientAuthManager(self.prefix, popen=popen, prompt_func=prompt_func)
     self.root = self.auth_manager.root
     self.requests_kwargs = {}
     res_loc = ResourceLocator.default()
     https_ssl_verify_mode_str = (
         res_loc.default().get_conf().get_value(["rosie-id", "prefix-https-ssl-verify." + prefix])
     )
     if https_ssl_verify_mode_str:
         https_ssl_verify_mode = ast.literal_eval(https_ssl_verify_mode_str)
         self.requests_kwargs["verify"] = bool(https_ssl_verify_mode)
     https_ssl_cert_str = res_loc.default().get_conf().get_value(["rosie-id", "prefix-https-ssl-cert." + prefix])
     if https_ssl_cert_str:
         https_ssl_cert = shlex.split(https_ssl_cert_str)
         if len(https_ssl_cert) == 1:
             self.requests_kwargs["cert"] = https_ssl_cert[0]
         else:
             self.requests_kwargs["cert"] = tuple(https_ssl_cert[0:2])
예제 #33
0
def get_local_suites(prefix=None, skip_status=False, user=None):
    """Returns a dict of prefixes and id tuples for locally-present suites."""
    local_copies = []

    if user:
        local_copy_root = os.path.expanduser(user) + "/roses"
    else:
        local_copy_root = SuiteId.get_local_copy_root()

    if not os.path.isdir(local_copy_root):
        return local_copies
    for path in os.listdir(local_copy_root):
        location = os.path.join(local_copy_root, path)
        try:
            id_ = SuiteId(location=location, skip_status=skip_status)
        except SuiteIdError as e:
            continue
        if prefix is None or id_.prefix == prefix:
            if str(id_) == path:
                local_copies.append(id_)
    return local_copies
예제 #34
0
 def _render(self, all_revs=0, data=None, filters=None, s=None):
     """Render return data with a template."""
     if data:
         for item in data:
             suite_id = SuiteId.from_idx_branch_revision(
                 item["idx"], item["branch"], item["revision"])
             item["href"] = suite_id.to_web()
             item["date"] = str(
                 get_timepoint_from_seconds_since_unix_epoch(item["date"]))
     tmpl = self.props["template_env"].get_template("prefix-index.html")
     return tmpl.render(title=self.props["title"],
                        host=self.props["host_name"],
                        rose_version=self.props["rose_version"],
                        script=cherrypy.request.script_name,
                        prefix=self.prefix,
                        prefix_source_url=self.source_url,
                        known_keys=self.dao.get_known_keys(),
                        query_operators=self.dao.get_query_operators(),
                        all_revs=all_revs,
                        filters=filters,
                        s=s,
                        data=data)
예제 #35
0
파일: vc.py 프로젝트: benfitzpatrick/rose
    def generate_info_config(self, from_id=None, prefix=None, project=None):
        """Generate a rose.config.ConfigNode for a rose-suite.info.

        This is suitable for passing into the create method of this
        class.
        If from_id is defined, copy items from it.
        Return the rose.config.ConfigNode instance.

        """
        from_project = None
        from_title = None
        if from_id is not None:
            from_info_url = "%s/%s/rose-suite.info@%s" % (from_id.to_origin(),
                                                          from_id.branch,
                                                          from_id.revision)
            out_data = self.popen("svn", "cat", from_info_url)[0]
            from_config = rose.config.load(StringIO(out_data.decode()))

        res_loc = ResourceLocator.default()
        older_config = None
        info_config = rose.config.ConfigNode()

        # Determine project if given as a command-line option on create
        if from_id is None and project is not None:
            info_config.set(["project"], project)

        # Set the compulsory fields and use the project and metadata if
        #  available.
        meta_config = load_meta_config(
            info_config, config_type=rose.INFO_CONFIG_NAME)
        if from_id is None and project is not None:
            for node_keys, node in meta_config.walk(no_ignore=True):
                if isinstance(node.value, dict):
                    continue
                sect, key = node_keys
                value = node.value
                sect = sect.translate(None, "=")
                if key == "compulsory" and value == "true":
                    info_config.set([sect], "")
            info_config.set(["project"], project)
        else:
            if from_project is None:
                info_config.set(["project"], "")
            if from_title is None:
                info_config.set(["title"], "")

        # Determine prefix
        if prefix is None:
            if from_id is None:
                prefix = SuiteId.get_prefix_default()
            else:
                prefix = from_id.prefix

        # Determine owner:
        # 1. From user configuration [rosie-id]prefix-username
        # 2. From username of a matching group in [groups] in
        #    ~/.subversion/servers
        # 3. Current user ID
        owner = res_loc.get_conf().get_value(
            ["rosie-id", "prefix-username." + prefix])
        if not owner and self.subversion_servers_conf:
            servers_conf = rose.config.load(self.subversion_servers_conf)
            groups_node = servers_conf.get(["groups"])
            if groups_node is not None:
                prefix_loc = SuiteId.get_prefix_location(prefix)
                prefix_host = urlparse(prefix_loc).hostname
                for key, node in groups_node.value.items():
                    if fnmatch(prefix_host, node.value):
                        owner = servers_conf.get_value([key, "username"])
                        break
        if not owner:
            owner = pwd.getpwuid(os.getuid())[0]
        info_config.set(["owner"], owner)

        # Copy description
        try:
            from_id.to_string_with_version()
            info_config.set(
                ["description"],
                "Copy of %s" % (from_id.to_string_with_version()))
        except AttributeError:
            pass

        # Copy fields provided by the user
        try:
            from_config.walk(no_ignore=False)
            for node_keys, node in from_config.walk(no_ignore=False):
                if isinstance(node.value, dict):
                    continue
                sect, key = node_keys
                value = node.value
                if (key in ["description", "owner", "access-list"] or
                        (key == "project" and from_project is not None)):
                    pass
                else:
                    info_config.set([key], value)
        except UnboundLocalError:
            pass

        # Determine access list
        access_list_str = res_loc.get_conf().get_value(
            ["rosie-vc", "access-list-default"])
        if access_list_str:
            info_config.set(["access-list"], access_list_str)
        if from_id is None and project is not None:
            for node_keys, node in meta_config.walk(no_ignore=True):
                if isinstance(node.value, dict):
                    continue
                sect, key = node_keys
                value = node.value
                sect = sect.translate(None, "=")
                if key == "value-hints" or key == "values":
                    reminder = ("please remove all commented hints/lines " +
                                "in the main/top section before saving.")
                    info_config.set([sect],
                                    rose.variable.array_split(value)[0],
                                    comments=[value, reminder])
        if older_config is not None:
            for node_keys, node in older_config.walk(no_ignore=True):
                if isinstance(node.value, dict):
                    continue
                sect, key = node_keys
                value = node.value
                info_config.set([key], value)

        return info_config
예제 #36
0
def _display_maps(opts, ws_client, dict_rows, url=None):
    """Display returned suite details."""
    report = ws_client.event_handler

    try:
        terminal_cols = int(ws_client.popen("stty", "size")[0].split()[1])
    except (IndexError, RosePopenError, ValueError):
        terminal_cols = None

    if terminal_cols == 0:
        terminal_cols = None

    if opts.quietness and not opts.print_format:
        opts.print_format = PRINT_FORMAT_QUIET
    elif not opts.print_format:
        opts.print_format = PRINT_FORMAT_DEFAULT

    all_keys = ws_client.get_known_keys()

    for dict_row in dict_rows:
        suite_id = SuiteId.from_idx_branch_revision(dict_row["idx"],
                                                    dict_row["branch"],
                                                    dict_row["revision"])
        dict_row["suite"] = suite_id.to_string_with_version()
        if "%local" in opts.print_format:
            dict_row["local"] = suite_id.get_status(getattr(
                opts, "user", None))
    all_keys += ["suite"]
    if "%local" in opts.print_format:
        all_keys += ["local"]

    more_keys = []
    for key in REC_COL_IN_FORMAT.findall(opts.print_format):
        if key not in all_keys:
            more_keys.append(key)
    all_keys += more_keys

    if opts.sort is None or opts.sort not in all_keys:
        opts.sort = "revision"
    dict_rows.sort(lambda x, y: cmp(x[opts.sort], y[opts.sort]))
    if opts.reverse:
        dict_rows.reverse()

    keylist = []
    for key in all_keys:
        if "%" + key in opts.print_format:
            keylist.append(key)

    if not opts.no_headers:
        dummy_row = {}
        for key in all_keys:
            dummy_row[key] = key
        dict_rows.insert(0, dummy_row)

    dict_rows = _align(dict_rows, keylist)

    for dict_row in dict_rows:
        out = opts.print_format
        for key, value in dict_row.items():
            if "%" + key in out:
                out = unicode(out).replace(u"%" + unicode(key), unicode(value),
                                           1)
        out = unicode(out.replace("%%", "%").expandtabs().rstrip())

        report(SuiteEvent(out.expandtabs() + "\n"),
               prefix="",
               clip=terminal_cols)
        report(SuiteInfo(dict_row), prefix="")
    if url is not None:
        report(URLEvent(url + "\n"), prefix="")
예제 #37
0
파일: vc.py 프로젝트: benfitzpatrick/rose
    def create(self, info_config, from_id=None, prefix=None,
               meta_suite_mode=False):
        """Create a suite.

        info_config -- A rose.config.ConfigNode object, which will be used as
                       the content of the "rose-suite.info" file of the new
                       suite.
        from_id -- If defined, copy items from it.
        prefix -- If defined, create the suite in the suite repository named by
                  the prefix instead of the default one.
        meta_suite_mode -- If True, create the special metadata suite.
                           Ignored if from_id is not None.

        Return the SuiteId of the suite on success.

        """
        if from_id is not None and (not prefix or from_id.prefix == prefix):
            return self._copy1(info_config, from_id)
        dir_ = self._get_work_dir()
        try:
            # Create a temporary suite in the file system
            if from_id:
                from_id_url = "%s/%s@%s" % (
                    from_id.to_origin(), from_id.branch, from_id.revision)
                self.popen("svn", "export", "-q", "--force", from_id_url, dir_)
            else:
                open(os.path.join(dir_, "rose-suite.conf"), "w").close()
            rose.config.dump(
                info_config, os.path.join(dir_, "rose-suite.info"))

            # Attempt to import the temporary suite to the repository
            new_id = None
            while new_id is None:
                if meta_suite_mode:
                    if prefix is None:
                        new_id = SuiteId(id_text="ROSIE")
                    else:
                        idx = SuiteId.FORMAT_IDX % (prefix, "ROSIE")
                        new_id = SuiteId(id_text=idx)
                else:
                    new_id = SuiteId.get_next(prefix)
                new_origin = new_id.to_origin() + "/" + new_id.BRANCH_TRUNK
                try:
                    if from_id:
                        message = self.COMMIT_MESSAGE_COPY % (
                            new_id, from_id.to_string_with_version())
                    else:
                        message = self.COMMIT_MESSAGE_CREATE % str(new_id)
                    self.popen(
                        "svn", "import", "-q", "-m", message, dir_, new_origin)
                    self.event_handler(SuiteCreateEvent(new_id))
                    if from_id:
                        self.event_handler(SuiteCopyEvent(new_id, from_id))
                except RosePopenError as exc:
                    try:
                        self.popen("svn", "info", new_origin)
                        if not meta_suite_mode:
                            new_id = None
                    except RosePopenError:
                        raise exc
            return new_id
        finally:
            self._delete_work_dir()
예제 #38
0
def create(argv):
    """CLI function: create and copy."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("checkout_mode", "info_file",
                              "meta_suite_mode", "non_interactive", "prefix")
    opts, args = opt_parser.parse_args(argv)
    verbosity = opts.verbosity - opts.quietness
    report = Reporter(verbosity)
    client = RosieVCClient(event_handler=report)
    SuiteId.svn.event_handler = client.event_handler # FIXME: ugly?
    from_id = None
    if args:
        from_id = SuiteId(id_text=args[0])
        if from_id.branch is None:
            from_id.branch = from_id.BRANCH_TRUNK
        if from_id.revision is None:
            from_id.revision = from_id.REV_HEAD
            from_id = SuiteId(id_text=from_id.to_string_with_version())
    if opts.info_file is None:
        try:
            info_config = client.generate_info_config(from_id, opts.prefix)
        except (RosePopenError) as e:
            report(e)
            sys.exit(1)
        info_file = tempfile.NamedTemporaryFile(delete=False)
        try:
            rose.config.dump(info_config, info_file)
            info_file.write(CREATE_INFO_CONFIG_COMMENT)
            info_file.close()
            command_list = client.popen.get_cmd("editor", info_file.name)
            client.popen(*command_list, stdout=sys.stdout)
            info_config = rose.config.load(info_file.name)
        finally:
            os.unlink(info_file.name)
    elif opts.info_file == "-":
        info_config = rose.config.load(sys.stdin)
    else:
        info_config = rose.config.load(opts.info_file)
    if not opts.non_interactive:
        if from_id:
            question = "Copy \"%s\"?" % from_id.to_string_with_version()
        else:
            prefix = opts.prefix
            if not prefix:
                prefix = SuiteId.get_prefix_default()
            question = "Create suite at \"%s\"?" % prefix
        try:
            response = raw_input(question + " y/n (default n) ")
        except EOFError:
            sys.exit(1)
        if response != 'y':
            sys.exit(1)
    try:
        id = client.create(info_config, from_id, opts.prefix,
                           opts.meta_suite_mode)
    except (RosePopenError, SuiteInfoFieldError, SuiteIdOverflowError) as e:
        report(e)
        sys.exit(1)
    if opts.checkout_mode:
        try:
            client.checkout(id)
        except (FileExistError, RosePopenError) as e:
            report(e)
            sys.exit(1)
예제 #39
0
파일: vc.py 프로젝트: bjlittle/rose
def create(argv):
    """CLI function: create and copy."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("checkout_mode", "info_file",
                              "meta_suite_mode", "non_interactive", "prefix",
                              "project")
    opts, args = opt_parser.parse_args(argv)
    verbosity = opts.verbosity - opts.quietness
    report = Reporter(verbosity)
    client = RosieVCClient(event_handler=report)
    SuiteId.svn.event_handler = client.event_handler # FIXME: ugly?
    from_id = None
    if args:
        from_id = SuiteId(id_text=args[0])
        if from_id.branch is None:
            from_id.branch = from_id.BRANCH_TRUNK
        if from_id.revision is None:
            from_id.revision = from_id.REV_HEAD
            from_id = SuiteId(id_text=from_id.to_string_with_version())
    info_config_new = None
    interactive_mode = not opts.non_interactive
    if opts.info_file is None:
        try:
            info_config = client.generate_info_config(from_id, opts.prefix,
                                                      opts.project)
        except (RosePopenError) as e:
            report(e)
            sys.exit(1)
        info_file = tempfile.NamedTemporaryFile()
        if args:
            meta_config = load_meta_config(info_config, directory=None,
                                           config_type=rose.INFO_CONFIG_NAME,
                                           error_handler=None,
                                           ignore_meta_error=False)
            for node_keys, node in meta_config.walk(no_ignore=True):
                if isinstance(node.value, dict):
                    continue
                sect, key = node_keys
                value = node.value
                sect = sect.translate(None, "=")
                if key == "copy-mode" and value == "clear":
                    info_config.set([sect], "")
                if key == "copy-mode" and value == "never":
                    info_config.unset([sect])
        rose.config.dump(info_config, info_file)
        info_file.write(CREATE_INFO_CONFIG_COMMENT)
        info_file.seek(0)
        command_list = client.popen.get_cmd("editor", info_file.name)
        client.popen(*command_list, stdout=sys.stdout)
        info_config = rose.config.load(info_file)
        try:
            info_config_new, error_reported = client.check_fields(info_config,
                                                              interactive_mode,
                                                              from_id,
                                                              opts.prefix)
        except (RosePopenError, SuiteInfoFieldError,
                SuiteIdOverflowError) as e:
            report(e)
            sys.exit(1)
        while error_reported is True:
            info_file = tempfile.NamedTemporaryFile()
            info_config = info_config_new
            if (info_config.get(["project"]).value is not None and
               opts.project is None):
                project = info_config.get(["project"]).value
                info_config = client.generate_info_config(from_id, opts.prefix,
                                                          project,
                                                          info_config)
            rose.config.dump(info_config, info_file)
            info_file.write(CREATE_INFO_CONFIG_COMMENT)
            info_file.seek(0)
            command_list = client.popen.get_cmd("editor", info_file.name)
            client.popen(*command_list, stdout=sys.stdout)
            info_config = rose.config.load(info_file)
            try:
                info_config_new, error_reported = client.check_fields(
                                                              info_config,
                                                              interactive_mode,
                                                              from_id,
                                                              opts.prefix)
            except (RosePopenError, SuiteInfoFieldError,
                    SuiteIdOverflowError) as e:
                report(e)
                sys.exit(1)
    elif opts.info_file == "-":
        info_config = rose.config.load(sys.stdin)
        try:
            info_config_new, error_reported = client.check_fields(info_config,
                                                          interactive_mode,
                                                          from_id,
                                                          opts.info_file,
                                                          opts.prefix)
        except (RosePopenError, SuiteInfoFieldError,
                SuiteIdOverflowError) as e:
            report(e)
            sys.exit(1)
    else:
        info_config = rose.config.load(opts.info_file)
        try:
            info_config_new, error_reported = client.check_fields(info_config,
                                                          interactive_mode,
                                                          from_id,
                                                          opts.info_file,
                                                          opts.prefix)
        except (RosePopenError, SuiteInfoFieldError,
                SuiteIdOverflowError) as e:
            report(e)
            sys.exit(1)
    if interactive_mode:
        if from_id:
            question = "Copy \"%s\"?" % from_id.to_string_with_version()
        else:
            prefix = opts.prefix
            if not prefix:
                prefix = SuiteId.get_prefix_default()
            question = "Create suite at \"%s\"?" % prefix
        try:
            response = raw_input(question + " y/n (default n) ")
        except EOFError:
            sys.exit(1)
        if response != 'y':
            sys.exit(1)
    try:
        id = client.create(info_config, from_id, opts.prefix,
                           opts.meta_suite_mode)
    except (RosePopenError, SuiteInfoFieldError, SuiteIdOverflowError) as e:
        report(e)
        sys.exit(1)
    if opts.checkout_mode:
        try:
            client.checkout(id)
        except (FileExistError, RosePopenError) as e:
            report(e)
            sys.exit(1)
예제 #40
0
파일: vc.py 프로젝트: kaday/rose
    def create(self,
               info_config,
               from_id=None,
               prefix=None,
               meta_suite_mode=False):
        """Create a suite.

        info_config -- A rose.config.ConfigNode object, which will be used as
                       the content of the "rose-suite.info" file of the new
                       suite.
        from_id -- If defined, copy items from it.
        prefix -- If defined, create the suite in the suite repository named by
                  the prefix instead of the default one.
        meta_suite_mode -- If True, create the special metadata suite.
                           Ignored if from_id is not None.

        Return the SuiteId of the suite on success.

        """
        if from_id is not None and (not prefix or from_id.prefix == prefix):
            return self._copy1(info_config, from_id)

        dir_ = self._get_work_dir()
        try:
            # Create a temporary suite in the file system
            if from_id:
                from_id_url = "%s/%s@%s" % (from_id.to_origin(),
                                            from_id.branch, from_id.revision)
                self.popen("svn", "export", "-q", "--force", from_id_url, dir_)
            else:
                open(os.path.join(dir_, "rose-suite.conf"), "w").close()
            rose.config.dump(info_config, os.path.join(dir_,
                                                       "rose-suite.info"))

            # Attempt to import the temporary suite to the repository
            new_id = None
            while new_id is None:
                if meta_suite_mode:
                    if prefix is None:
                        new_id = SuiteId(id_text="ROSIE")
                    else:
                        idx = SuiteId.FORMAT_IDX % (prefix, "ROSIE")
                        new_id = SuiteId(id_text=idx)
                else:
                    new_id = SuiteId.get_next(prefix)
                new_origin = new_id.to_origin() + "/" + new_id.BRANCH_TRUNK
                try:
                    if from_id:
                        message = self.COMMIT_MESSAGE_COPY % (
                            new_id, from_id.to_string_with_version())
                    else:
                        message = self.COMMIT_MESSAGE_CREATE % str(new_id)
                    self.popen("svn", "import", "-q", "-m", message, dir_,
                               new_origin)
                    self.event_handler(SuiteCreateEvent(new_id))
                    if from_id:
                        self.event_handler(SuiteCopyEvent(new_id, from_id))
                except RosePopenError as exc:
                    try:
                        self.popen("svn", "info", new_origin)
                        if not meta_suite_mode:
                            new_id = None
                    except RosePopenError:
                        raise exc
            return new_id
        finally:
            self._delete_work_dir()
예제 #41
0
파일: vc.py 프로젝트: jimbolton/rose
    def create(self, info_config, from_id=None, prefix=None):
        """Create a suite.

        info_config should be a rose.config.ConfigNode object,
        which will be used as the content of the "rose-suite.info" file of the
        new suite.
        If from_id is defined, copy items from it.
        If prefix is defined, create the suite in the suite repository named by
        the prefix instead of the default one.
        Return the SuiteId of the suite on success.

        """
        for key in ["owner", "project", "title"]:
            if not info_config.get([key], no_ignore=True):
                raise SuiteInfoFieldError(key)
        if from_id is not None:
            prefix = from_id.prefix
        new_id = None
        while new_id is None:
            new_id = SuiteId.get_next(prefix)
            new_origin = new_id.to_origin() + "/" + new_id.BRANCH_TRUNK
            dir = self._get_work_dir()
            rose.config.dump(info_config, os.path.join(dir, "rose-suite.info"))
            open(os.path.join(dir, "rose-suite.conf"), "w").close()
            try:
                self.popen("svn", "import",
                          "-q",
                          "-m", "%s: new suite." % str(new_id),
                          dir,
                          new_origin)
                self.event_handler(SuiteCreateEvent(new_id))
                self._delete_work_dir()
            except RosePopenError as e:
                try:
                    self.popen("svn", "info", new_origin)
                    new_id = None
                except RosePopenError:
                    raise e
        if from_id is None:
            return new_id
        from_origin_base = "%s/%s" % (from_id.to_origin(), from_id.branch)
        from_origin = "%s@%s" % (from_origin_base, from_id.revision)
        copy_command_list = ["copy", "-q"]
        for from_item in self.popen("svn", "ls", from_origin)[0].split():
            if from_item not in ["rose-suite.conf", "rose-suite.info"]:
                item = "%s/%s@%s" % (from_origin_base, from_item, from_id.revision)
                copy_command_list.append(item)
        copy_command_list.append(".")
        log = "%s: copy items from %s" % (str(new_id),
                                          from_id.to_string_with_version())
        temp_local_copy = os.path.join(self._get_work_dir(), "work")
        try:
            self.popen("svn", "checkout", new_origin, temp_local_copy)
            cwd = os.getcwd()
            os.chdir(temp_local_copy)
            self.popen("svn", *copy_command_list)
            from_conf = "%s/%s@%s" % (from_origin_base,
                                      "rose-suite.conf",
                                      from_id.revision)
            f = open("rose-suite.conf", "w")
            f.write(self.popen("svn", "cat", from_conf)[0])
            f.close()
            self.popen("svn", "commit", "-m", log)
            self.event_handler(SuiteCopyEvent(new_id, from_id))
        finally:
            os.chdir(cwd)
            self._delete_work_dir()
        return new_id
예제 #42
0
파일: vc.py 프로젝트: kaday/rose
    def generate_info_config(self, from_id=None, prefix=None, project=None):
        """Generate a rose.config.ConfigNode for a rose-suite.info.

        This is suitable for passing into the create method of this
        class.
        If from_id is defined, copy items from it.
        Return the rose.config.ConfigNode instance.

        """
        from_project = None
        from_title = None
        if from_id is not None:
            from_info_url = "%s/%s/rose-suite.info@%s" % (
                from_id.to_origin(), from_id.branch, from_id.revision)
            out_data = self.popen("svn", "cat", from_info_url)[0]
            from_config = rose.config.load(StringIO(out_data))

        res_loc = ResourceLocator.default()
        older_config = None
        info_config = rose.config.ConfigNode()

        # Determine project if given as a command-line option on create
        if from_id is None and project is not None:
            info_config.set(["project"], project)

        # Set the compulsory fields and use the project and metadata if
        #  available.
        meta_config = load_meta_config(info_config,
                                       config_type=rose.INFO_CONFIG_NAME)
        if from_id is None and project is not None:
            for node_keys, node in meta_config.walk(no_ignore=True):
                if isinstance(node.value, dict):
                    continue
                sect, key = node_keys
                value = node.value
                sect = sect.translate(None, "=")
                if key == "compulsory" and value == "true":
                    info_config.set([sect], "")
            info_config.set(["project"], project)
        else:
            if from_project is None:
                info_config.set(["project"], "")
            if from_title is None:
                info_config.set(["title"], "")

        # Determine prefix
        if prefix is None:
            if from_id is None:
                prefix = SuiteId.get_prefix_default()
            else:
                prefix = from_id.prefix

        # Determine owner:
        # 1. From user configuration [rosie-id]prefix-username
        # 2. From username of a matching group in [groups] in
        #    ~/.subversion/servers
        # 3. Current user ID
        owner = res_loc.get_conf().get_value(
            ["rosie-id", "prefix-username." + prefix])
        if not owner and self.subversion_servers_conf:
            servers_conf = rose.config.load(self.subversion_servers_conf)
            groups_node = servers_conf.get(["groups"])
            if groups_node is not None:
                prefix_loc = SuiteId.get_prefix_location(prefix)
                prefix_host = urlparse(prefix_loc).hostname
                for key, node in groups_node.value.items():
                    if fnmatch(prefix_host, node.value):
                        owner = servers_conf.get_value([key, "username"])
                        break
        if not owner:
            owner = pwd.getpwuid(os.getuid())[0]
        info_config.set(["owner"], owner)

        # Copy description
        try:
            from_id.to_string_with_version()
            info_config.set(["description"],
                            "Copy of %s" % (from_id.to_string_with_version()))
        except AttributeError:
            pass

        # Copy fields provided by the user
        try:
            from_config.walk(no_ignore=False)
            for node_keys, node in from_config.walk(no_ignore=False):
                if isinstance(node.value, dict):
                    continue
                sect, key = node_keys
                value = node.value
                if (key in ["description", "owner", "access-list"]
                        or (key == "project" and from_project is not None)):
                    pass
                else:
                    info_config.set([key], value)
        except UnboundLocalError:
            pass

        # Determine access list
        access_list_str = res_loc.get_conf().get_value(
            ["rosie-vc", "access-list-default"])
        if access_list_str:
            info_config.set(["access-list"], access_list_str)
        if from_id is None and project is not None:
            for node_keys, node in meta_config.walk(no_ignore=True):
                if isinstance(node.value, dict):
                    continue
                sect, key = node_keys
                value = node.value
                sect = sect.translate(None, "=")
                if key == "value-hints" or key == "values":
                    reminder = ("please remove all commented hints/lines " +
                                "in the main/top section before saving.")
                    info_config.set([sect],
                                    rose.variable.array_split(value)[0],
                                    comments=[value, reminder])
        if older_config is not None:
            for node_keys, node in older_config.walk(no_ignore=True):
                if isinstance(node.value, dict):
                    continue
                sect, key = node_keys
                value = node.value
                info_config.set([key], value)

        return info_config
예제 #43
0
파일: vc.py 프로젝트: benfitzpatrick/rose
def create(argv):
    """CLI function: create and copy."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options(
        "checkout_mode", "info_file", "meta_suite_mode", "non_interactive",
        "prefix", "project")
    opts, args = opt_parser.parse_args(argv)
    verbosity = opts.verbosity - opts.quietness
    client = RosieVCClient(event_handler=Reporter(verbosity))
    SuiteId.svn.event_handler = client.event_handler
    from_id = None
    if args:
        from_id = SuiteId(id_text=args[0])
        if from_id.branch is None:
            from_id.branch = from_id.BRANCH_TRUNK
        if from_id.revision is None:
            from_id.revision = from_id.REV_HEAD
            from_id = SuiteId(id_text=from_id.to_string_with_version())
    interactive_mode = not opts.non_interactive
    if opts.info_file is None:
        info_config = client.generate_info_config(
            from_id, opts.prefix, opts.project)
        if from_id is not None:
            meta_config = load_meta_config(
                info_config,
                directory=None,
                config_type=rose.INFO_CONFIG_NAME,
                error_handler=None,
                ignore_meta_error=False)
            for node_keys, node in meta_config.walk(no_ignore=True):
                if isinstance(node.value, dict):
                    continue
                sect, key = node_keys
                value = node.value
                sect = sect.replace("=", "")
                if key == "copy-mode" and value == "clear":
                    info_config.set([sect], "")
                if key == "copy-mode" and value == "never":
                    info_config.unset([sect])

        info_config = _edit_info_config(opts, client, info_config)
    else:
        file_ = opts.info_file
        if opts.info_file == "-":
            file_ = sys.stdin
        info_config = rose.config.load(file_)
    info_config = _validate_info_config(opts, client, info_config)
    if interactive_mode:
        prefix = opts.prefix
        if from_id:
            if not prefix:
                prefix = from_id.prefix
            question = PROMPT_COPY % (from_id.to_string_with_version(), prefix)
        else:
            if not prefix:
                prefix = SuiteId.get_prefix_default()
            question = PROMPT_CREATE % prefix
        try:
            response = input(question)
        except EOFError:
            sys.exit(1)
        if response != YES:
            sys.exit(1)
    try:
        id_ = client.create(
            info_config, from_id, opts.prefix, opts.meta_suite_mode)
    except (RosePopenError, SuiteIdOverflowError) as exc:
        client.event_handler(exc)
        sys.exit(1)
    if opts.checkout_mode:
        try:
            client.checkout(id_)
        except (FileExistError, RosePopenError) as exc:
            client.event_handler(exc)
            sys.exit(1)
예제 #44
0
    def generate_info_config(self, from_id=None, prefix=None):
        """Generate a rose.config.ConfigNode for a rose-suite.info.

        This is suitable for passing into the create method of this
        class.
        If from_id is defined, copy items from it.
        Return the rose.config.ConfigNode instance.

        """
        from_project = None
        from_title = None
        if from_id is not None:
            from_info_url = "%s/%s/rose-suite.info@%s" % (from_id.to_origin(),
                                                          from_id.branch,
                                                          from_id.revision)
            out_data = self.popen("svn", "cat", from_info_url)[0]
            from_config = rose.config.load(StringIO(out_data))
            if from_config.get(["project"]) is not None:
                from_project = from_config.get(["project"]).value
            if from_config.get(["title"]) is not None:
                from_title = from_config.get(["title"]).value

        res_loc = ResourceLocator.default()
        info_config = rose.config.ConfigNode()

        # Determine prefix
        if from_id is not None:
            prefix = from_id.prefix
        elif prefix is None:
            prefix = SuiteId.get_prefix_default()

        # Determine owner:
        # 1. From user configuration [rosie-id]prefix-username
        # 2. From username of a matching group in [groups] in
        #    ~/.subversion/servers
        # 3. Current user ID
        owner = res_loc.get_conf().get_value(
                        ["rosie-id", "prefix-username." + prefix])
        if not owner and self.subversion_servers_conf:
            servers_conf = rose.config.load(self.subversion_servers_conf)
            groups_node = servers_conf.get(["groups"])
            if groups_node is not None:
                group = None
                prefix_loc = SuiteId.get_prefix_location(prefix)
                prefix_host = urlparse(prefix_loc).hostname
                for key, node in groups_node.value.items():
                    if fnmatch(prefix_host, node.value):
                        owner = servers_conf.get_value([key, "username"])
                        break
        if not owner:
            owner = pwd.getpwuid(os.getuid())[0]
        info_config.set(["owner"], owner)

        # Determine project and title
        if from_project:
            info_config.set(["project"], from_project)
        else:
            info_config.set(["project"], "")
        if from_title:
            info_config.set(["title"], "Copy of %s: %s" % 
                            (from_id.to_string_with_version(), from_title))
        else:
            info_config.set(["title"], "")

        # Determine access list
        access_list_str = res_loc.get_conf().get_value(
            ["rosie-vc", "access-list-default"])
        if access_list_str:
            info_config.set(["access-list"], access_list_str)
        return info_config
예제 #45
0
파일: vc.py 프로젝트: csimag/rose
    def generate_info_config(self, from_id=None, prefix=None):
        """Generate a rose.config.ConfigNode for a rose-suite.info.

        This is suitable for passing into the create method of this
        class.
        If from_id is defined, copy items from it.
        Return the rose.config.ConfigNode instance.

        """
        from_project = None
        from_title = None
        if from_id is not None:
            from_info_url = "%s/%s/rose-suite.info@%s" % (from_id.to_origin(),
                                                          from_id.branch,
                                                          from_id.revision)
            out_data = self.popen("svn", "cat", from_info_url)[0]
            from_config = rose.config.load(StringIO(out_data))
            if from_config.get(["project"]) is not None:
                from_project = from_config.get(["project"]).value
            if from_config.get(["title"]) is not None:
                from_title = from_config.get(["title"]).value

        res_loc = ResourceLocator.default()
        info_config = rose.config.load(
                res_loc.locate("rosie-create/rose-suite.info"))
        if from_id is not None:
            prefix = from_id.prefix
        elif prefix is None:
            prefix = SuiteId.get_prefix_default()

        # Determine owner:
        # 1. From user configuration [rosie-id]prefix-username
        # 2. From username of a matching group in [groups] in
        #    ~/.subversion/servers
        # 3. Current user ID
        owner = res_loc.get_conf().get_value(
                        ["rosie-id", "prefix-username." + prefix])
        if not owner and self.subversion_servers_conf:
            servers_conf = rose.config.load(self.subversion_servers_conf)
            groups_node = servers_conf.get(["groups"])
            if groups_node is not None:
                group = None
                prefix_loc = SuiteId.get_prefix_location(prefix)
                prefix_host = urlparse(prefix_loc).hostname
                for key, node in groups_node.value.items():
                    if fnmatch(prefix_host, node.value):
                        owner = servers_conf.get_value([key, "username"])
                        break
        if not owner:
            owner = pwd.getpwuid(os.getuid())[0]
        info_config.set(["owner"], owner)

        if from_project:
            info_config.set(["project"], from_project)
        else:
            info_config.set(["project"], "")
        if from_title:
            info_config.set(["title"], "Copy of %s: %s" % 
                            (from_id.to_string_with_version(), from_title))
        else:
            info_config.set(["title"], "")
        return info_config
예제 #46
0
def _display_maps(opts, ws_client, dict_rows, url=None):
    """Display returned suite details."""
    report = ws_client.event_handler

    try:
        terminal_cols = int(ws_client.popen("stty", "size")[0].split()[1])
    except (IndexError, RosePopenError, ValueError):
        terminal_cols = None

    if terminal_cols == 0:
        terminal_cols = None

    if opts.quietness and not opts.print_format:
        opts.print_format = PRINT_FORMAT_QUIET
    elif not opts.print_format:
        opts.print_format = PRINT_FORMAT_DEFAULT

    all_keys = ws_client.get_known_keys()

    for dict_row in dict_rows:
        suite_id = SuiteId.from_idx_branch_revision(
            dict_row["idx"],
            dict_row["branch"],
            dict_row["revision"])
        dict_row["suite"] = suite_id.to_string_with_version()
        if "%local" in opts.print_format:
            dict_row["local"] = suite_id.get_status(
                getattr(opts, "user", None))
    all_keys += ["suite"]
    if "%local" in opts.print_format:
        all_keys += ["local"]

    more_keys = []
    for key in REC_COL_IN_FORMAT.findall(opts.print_format):
        if key not in all_keys:
            more_keys.append(key)
    all_keys += more_keys

    if opts.sort is None or opts.sort not in all_keys:
        opts.sort = "revision"
    dict_rows.sort(lambda x, y: cmp(x[opts.sort], y[opts.sort]))
    if opts.reverse:
        dict_rows.reverse()

    keylist = []
    for key in all_keys:
        if "%" + key in opts.print_format:
            keylist.append(key)

    if not opts.no_headers:
        dummy_row = {}
        for key in all_keys:
            dummy_row[key] = key
        dict_rows.insert(0, dummy_row)

    dict_rows = _align(dict_rows, keylist)

    for dict_row in dict_rows:
        out = opts.print_format
        for key, value in dict_row.items():
            if "%" + key in out:
                out = out.replace("%" + key, str(value), 1)
        out = out.replace("%%", "%").expandtabs().rstrip()

        report(SuiteEvent(out.expandtabs() + "\n"), prefix="",
               clip=terminal_cols)
        report(SuiteInfo(dict_row), prefix="")
    if url is not None:
        report(URLEvent(url + "\n"), prefix="")
예제 #47
0
파일: vc.py 프로젝트: kaday/rose
def create(argv):
    """CLI function: create and copy."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("checkout_mode", "info_file", "meta_suite_mode",
                              "non_interactive", "prefix", "project")
    opts, args = opt_parser.parse_args(argv)
    verbosity = opts.verbosity - opts.quietness
    client = RosieVCClient(event_handler=Reporter(verbosity))
    SuiteId.svn.event_handler = client.event_handler
    from_id = None
    if args:
        from_id = SuiteId(id_text=args[0])
        if from_id.branch is None:
            from_id.branch = from_id.BRANCH_TRUNK
        if from_id.revision is None:
            from_id.revision = from_id.REV_HEAD
            from_id = SuiteId(id_text=from_id.to_string_with_version())
    interactive_mode = not opts.non_interactive
    if opts.info_file is None:
        info_config = client.generate_info_config(from_id, opts.prefix,
                                                  opts.project)
        if from_id is not None:
            meta_config = load_meta_config(info_config,
                                           directory=None,
                                           config_type=rose.INFO_CONFIG_NAME,
                                           error_handler=None,
                                           ignore_meta_error=False)
            for node_keys, node in meta_config.walk(no_ignore=True):
                if isinstance(node.value, dict):
                    continue
                sect, key = node_keys
                value = node.value
                sect = sect.translate(None, "=")
                if key == "copy-mode" and value == "clear":
                    info_config.set([sect], "")
                if key == "copy-mode" and value == "never":
                    info_config.unset([sect])
        info_config = _edit_info_config(opts, client, info_config)
    else:
        file_ = opts.info_file
        if opts.info_file == "-":
            file_ = sys.stdin
        info_config = rose.config.load(file_)
    info_config = _validate_info_config(opts, client, info_config)
    if interactive_mode:
        prefix = opts.prefix
        if from_id:
            if not prefix:
                prefix = from_id.prefix
            question = PROMPT_COPY % (from_id.to_string_with_version(), prefix)
        else:
            if not prefix:
                prefix = SuiteId.get_prefix_default()
            question = PROMPT_CREATE % prefix
        try:
            response = raw_input(question)
        except EOFError:
            sys.exit(1)
        if response != YES:
            sys.exit(1)
    try:
        id_ = client.create(info_config, from_id, opts.prefix,
                            opts.meta_suite_mode)
    except (RosePopenError, SuiteIdOverflowError) as exc:
        client.event_handler(exc)
        sys.exit(1)
    if opts.checkout_mode:
        try:
            client.checkout(id_)
        except (FileExistError, RosePopenError) as exc:
            client.event_handler(exc)
            sys.exit(1)