def create(self): """Create a new test environment. This sets up Trac, calls :meth:`create_repo` and sets up authentication. """ os.mkdir(self.dirname) # testing.log gets any unused output from subprocesses self.logfile = open(os.path.join(self.dirname, 'testing.log'), 'w') self.create_repo() config_file = os.path.join(self.dirname, 'config.ini') config = Configuration(config_file) config.set('repositories', '.dir', self.repo_path_for_initenv()) config.set('repositories', '.type', self.repotype) config.save() self._tracadmin('initenv', self.tracdir, self.dburi, '--config=%s' % config_file) if call([ sys.executable, os.path.join(self.trac_src, 'contrib', 'htpasswd.py'), "-c", "-b", self.htpasswd, "admin", "admin" ], close_fds=close_fds, cwd=self.command_cwd): raise Exception('Unable to setup admin password') self.adduser('user') self.adduser('joe') self.grant_perm('admin', 'TRAC_ADMIN') env = self.get_trac_environment() for component in self.get_enabled_components(): env.config.set('components', component, 'enabled') env.config.save() self.post_create(env)
def cli_command(self, project, args): """Manipulate the trac environment for a project Supported arguments: - create: creates an environment - sync: Synchronizes the configuration with Cydra's requirements - addrepo <type> <name> [tracname]: adds the repository to trac, identified by tracname - updatedefaults <file>: Adds trac's default options to config""" if len(args) < 1 or args[0] not in ['create', 'addrepo', 'sync', 'updatedefaults']: print self.cli_command.__doc__ return if args[0] == 'create': if self.has_env(project): print "Project already has a Trac environment!" return if self.create(project): print "Environment created" else: print "Creation failed!" elif args[0] == 'sync': self.sync(project) print project.name, "synced" elif args[0] == 'addrepo': if len(args) < 3: print self.cli_command.__doc__ return repository = project.get_repository(args[1], args[2]) if not repository: print "Unknown repository" return ret = False if len(args) == 4: ret = self.register_repository(repository, args[3]) else: ret = self.register_repository(repository) if ret: print "Successfully added repository" else: print "Adding repository failed!" elif args[0] == 'updatedefaults': if len(args) < 2: print self.cli_command.__doc__ return config = Configuration(args[1]) # load defaults config.set_defaults() config.save()
def create(self, options=[], default_data=True): """Create the basic directory structure of the environment, initialize the database and populate the configuration file with default values. If options contains ('inherit', 'file'), default values will not be loaded; they are expected to be provided by that file or other options. :raises TracError: if the base directory of `path` does not exist. :raises TracError: if `path` exists and is not empty. """ base_dir = os.path.dirname(self.path) if not os.path.exists(base_dir): raise TracError( _( "Base directory '%(env)s' does not exist. Please create it " "and retry.", env=base_dir)) if os.path.exists(self.path) and os.listdir(self.path): raise TracError(_("Directory exists and is not empty.")) # Create the directory structure if not os.path.exists(self.path): os.mkdir(self.path) os.mkdir(self.htdocs_dir) os.mkdir(self.log_dir) os.mkdir(self.plugins_dir) os.mkdir(self.templates_dir) # Create a few files create_file(os.path.join(self.path, 'VERSION'), _VERSION + '\n') create_file( os.path.join(self.path, 'README'), 'This directory contains a Trac environment.\n' 'Visit https://trac.edgewall.org/ for more information.\n') # Setup the default configuration os.mkdir(self.conf_dir) config = Configuration(self.config_file_path) for section, name, value in options: config.set(section, name, value) config.save() self.setup_config() if not any((section, option) == ('inherit', 'file') for section, option, value in options): self.config.set_defaults(self) self.config.save() # Create the sample configuration create_file(self.config_file_path + '.sample') self._update_sample_config() # Create the database dbm = DatabaseManager(self) dbm.init_db() if default_data: dbm.insert_default_data()
def set_home_config(self, values): syspath = self.conf.getEnvironmentSysPath("home") setconf = Configuration(syspath + '/conf/trac.ini') try: for (main, sub, value) in values: setconf.set(main, sub, value) setconf.save() except: return False return True
def set_home_config(self, values): syspath = self.conf.getEnvironmentSysPath("home") setconf = Configuration(syspath + '/conf/trac.ini') try: for (main, sub, value) in values: setconf.set(main, sub, value) setconf.save() except: return False return True
def test_set_and_save(self): configfile = open(self.filename, 'w') configfile.close() config = Configuration(self.filename) config.set('a', 'option', 'x') self.assertEquals('x', config.get('a', 'option')) config.save() configfile = open(self.filename, 'r') self.assertEquals(['[a]\n', 'option = x\n', '\n'], configfile.readlines()) configfile.close()
def _update_sample_config(self): filename = os.path.join(self.env.config_file_path + ".sample") if not os.path.isfile(filename): return config = Configuration(filename) for (section, name), option in Option.get_registry().iteritems(): config.set(section, name, option.dumps(option.default)) try: config.save() self.log.info( "Wrote sample configuration file with the new " "settings and their default values: %s", filename ) except IOError as e: self.log.warn("Couldn't write sample configuration file (%s)", e, exc_info=True)
def _update_sample_config(self): filename = os.path.join(self.config_file_path + '.sample') if not os.path.isfile(filename): return config = Configuration(filename) config.set_defaults() try: config.save() except EnvironmentError as e: self.log.warning("Couldn't write sample configuration file (%s)%s", e, exception_to_unicode(e, traceback=True)) else: self.log.info( "Wrote sample configuration file with the new " "settings and their default values: %s", filename)
def _update_sample_config(self): filename = os.path.join(self.env.path, 'conf', 'trac.ini.sample') if not os.path.isfile(filename): return config = Configuration(filename) for (section, name), option in Option.get_registry().iteritems(): config.set(section, name, option.dumps(option.default)) try: config.save() self.log.info("Wrote sample configuration file with the new " "settings and their default values: %s", filename) except IOError as e: self.log.warn("Couldn't write sample configuration file (%s)", e, exc_info=True)
def do(self): # Make backup of trac.ini before configuring it try: shutil.copy(self.conf_file, self.conf_file_back) except Exception: conf.log.exception("Could not create trac.ini backup") return False # Open trac.ini for configuration config = None try: config = Configuration(self.conf_file) except Exception: conf.log.exception("Error while reading config file!") return False # Enable correct plugin for repository try: vcs_plugin = self.__vcs_plugin() if vcs_plugin: config.set('components', vcs_plugin, 'enabled') config.set('trac', 'repository_type', self.vcs_type) except Exception: conf.log.exception("Could not set static settings for trac") return False try: config.set('project', 'descr', self.project.description) except Exception: conf.log.exception("Couldn't set description") return False # Remove attachment size (to enable global setting) try: config.remove("attachment", "max_size") except Exception: conf.log.exception("Could not remove attachment config property for a new project") # Save configuration try: config.save() except Exception: conf.log.exception("Failed to save configuration") return False self.success = True return True
def do(self): # Make backup of trac.ini before configuring it try: shutil.copy(self.conf_file, self.conf_file_back) except Exception: conf.log.exception("Could not create trac.ini backup") return False # Open trac.ini for configuration config = None try: config = Configuration(self.conf_file) except Exception: conf.log.exception("Error while reading config file!") return False # Enable correct plugin for repository try: vcs_plugin = self.__vcs_plugin() if vcs_plugin: config.set('components', vcs_plugin, 'enabled') config.set('trac', 'repository_type', self.vcs_type) except Exception: conf.log.exception("Could not set static settings for trac") return False try: config.set('project', 'descr', self.project.description) except Exception: conf.log.exception("Couldn't set description") return False # Remove attachment size (to enable global setting) try: config.remove("attachment", "max_size") except Exception: conf.log.exception("Could not remove attachment config property for a new project") # Save configuration try: config.save() except Exception: conf.log.exception("Failed to save configuration") return False self.success = True return True
def writeconfig(self, filepath, dicts=[]): """Writes or updates a config file. A list of dictionaries is used so that options for different aspects of the configuration can be kept separate while being able to update the same sections. Note that the result is order dependent where two dictionaries update the same option. """ config = Configuration(filepath) file_changed = False for data in dicts: for section, options in data.iteritems(): for key, value in options.iteritems(): if config.get(section, key, None) != value: # This should be expected to generate a false positive # when two dictionaries update the same option file_changed = True config.set(section, key, value) if file_changed: if os.path.exists(filepath): backupfile(filepath) config.save()
def writeconfig(self, filepath, dicts=[]): """Writes or updates a config file. A list of dictionaries is used so that options for different aspects of the configuration can be kept separate while being able to update the same sections. Note that the result is order dependent where two dictionaries update the same option. """ config = Configuration(filepath) file_changed = False for data in dicts: for section, options in data.iteritems(): for key, value in options.iteritems(): if config.get(section, key, None) != value: # This should be expected to generate a false positive # when two dictionaries update the same option file_changed = True config.set(section, key, value) if file_changed: if os.path.exists(filepath): backupfile(filepath) config.save()
def create(self, options=[]): """Create the basic directory structure of the environment, initialize the database and populate the configuration file with default values. If options contains ('inherit', 'file'), default values will not be loaded; they are expected to be provided by that file or other options. """ # Create the directory structure if not os.path.exists(self.path): os.mkdir(self.path) os.mkdir(self.get_log_dir()) os.mkdir(self.get_htdocs_dir()) os.mkdir(os.path.join(self.path, 'plugins')) # Create a few files create_file(os.path.join(self.path, 'VERSION'), _VERSION + '\n') create_file( os.path.join(self.path, 'README'), 'This directory contains a Trac environment.\n' 'Visit http://trac.edgewall.org/ for more information.\n') # Setup the default configuration os.mkdir(os.path.join(self.path, 'conf')) create_file(os.path.join(self.path, 'conf', 'trac.ini.sample')) config = Configuration(os.path.join(self.path, 'conf', 'trac.ini')) for section, name, value in options: config.set(section, name, value) config.save() self.setup_config() if not any((section, option) == ('inherit', 'file') for section, option, value in options): self.config.set_defaults(self) self.config.save() # Create the database DatabaseManager(self).init_db()
def create(self, options=[]): """Create the basic directory structure of the environment, initialize the database and populate the configuration file with default values. If options contains ('inherit', 'file'), default values will not be loaded; they are expected to be provided by that file or other options. """ # Create the directory structure if not os.path.exists(self.path): os.mkdir(self.path) os.mkdir(self.get_log_dir()) os.mkdir(self.get_htdocs_dir()) os.mkdir(os.path.join(self.path, 'plugins')) # Create a few files create_file(os.path.join(self.path, 'VERSION'), _VERSION + '\n') create_file(os.path.join(self.path, 'README'), 'This directory contains a Trac environment.\n' 'Visit http://trac.edgewall.org/ for more information.\n') # Setup the default configuration os.mkdir(os.path.join(self.path, 'conf')) create_file(self.config_file_path + '.sample') config = Configuration(self.config_file_path) for section, name, value in options: config.set(section, name, value) config.save() self.setup_config() if not any((section, option) == ('inherit', 'file') for section, option, value in options): self.config.set_defaults(self) self.config.save() # Create the database DatabaseManager(self).init_db()
def sync(self, project): """Sync the trac environment with cydra This sets the options returned by ``get_default_options`` and adds Trac's own defaults if necessary""" if not self.has_env(project): logger.warning('Project %s has no Trac Environment to sync', project.name) return tracini = os.path.join(self.get_env_path(project), 'conf', 'trac.ini') options = self.get_default_options(project) # if inherit is enabled, the default values are supposed to be in # the inherited file. Thus, we can truncate the config file to get a bare minimum if 'inherit_config' in self.component_config: options.append(('inherit', 'file', self.component_config['inherit_config'])) with open(tracini, 'w') as f: f.truncate() # re-create the configuration file config = Configuration(tracini) for section, name, value in options: config.set(section, name, value) config.save() # load defaults if not any((section, option) == ('inherit', 'file') for section, option, value in options): config.set_defaults() config.save() # check if repositories in cydra match repositories in trac env = Environment(self.get_env_path(project)) rm = RepositoryManager(env) trac_repos = rm.get_real_repositories() trac_repo_names = [r.reponame for r in trac_repos] for repotype, repos in project.data.get('plugins', {}).get('trac', {}).items(): for repo, tracname in (repos or {}).items(): if tracname not in trac_repo_names: logger.warning("Removing trac mapping from cydra for %s repo %s", repo, tracname) del repos[repo] if not repos: del project.data.get('plugins', {}).get('trac', {})[repotype] # Now do the reverse revmap = dict([(y, x) for (x, y) in self.typemap.items()]) for repo in trac_repos: logger.debug('Looking at trac repo %s', repo.reponame) try: baseparts = repo.get_base().split(':') # This is extremely naiive and possibly breaks some time repotype, path = baseparts[0], baseparts[-1] except: logger.error("Unable to parse: " + repo.get_base()) reponame = os.path.basename(path) if repotype == 'git': reponame = reponame[:-4] try: repository = project.get_repository(revmap[repotype], reponame) except: logger.error("Unable to locate %s %s (%s)", repotype, reponame, path) repository = None logger.debug('Cydra repo %r', repository) if repository: # set this mapping if not there already project.data.setdefault('plugins', {}).setdefault('trac', {}).setdefault(repository.type, {})[repository.name] = repo.reponame logger.info('Setting trac mapping for %s %s -> %s', repository.type, repository.name, repo.reponame) else: logger.error("Unable to load %s %s (%s)", revmap[repotype], reponame, path) project.save()
def _do_update(self, req): """Update component enablement.""" components = req.args.getlist('component') oenabled = req.args.getlist('enable') penabled = req.args.getlist('prjenable') changes = False changed = {} # Set global project configuration prjconf = Configuration(conf.global_conf_path) for component in components: c_state = self.get_project_component_state(component, self.config) c_activated = (component in oenabled) if self.is_plugin_changed(c_state, c_activated): self.config.set('components', component, c_activated and 'enabled' or 'disabled') self.log.info('%sabling component %s', c_activated and 'En' or 'Dis', component) changes = True if prjconf: cip_state = self.get_project_component_state( component, prjconf) cip_activated = (component in penabled) if self.is_plugin_changed(cip_state, cip_activated): self.log.info('%sabling project component %s', cip_activated and 'En' or 'Dis', component) changed[ component] = cip_activated and 'enabled' or 'disabled' changes = True if prjconf: scomponents = req.args.getlist('setting') static_items = req.args.getlist('static_setting') for scomponent in scomponents: values = self.get_project_component_value( scomponent, None, prjconf) saved_value = self.parse_value(0, values) saved_static = self.parse_value(1, values) current_value = req.args.get(scomponent + '.value').replace( '|', '') current_static = (scomponent in static_items) if saved_value != current_value or saved_static != current_static: if current_static: final_value = current_value else: final_value = current_value + '|no' prjconf.set('settings', scomponent, final_value) changes = True if changes: self.config.save() if prjconf: for key in changed.keys(): prjconf.set('components', key, changed[key]) prjconf.save()
def cli_command(self, project, args): """Manipulate the trac environment for a project Supported arguments: - create: creates an environment - sync: Synchronizes the configuration with Cydra's requirements - addrepo <type> <name> [tracname]: adds the repository to trac, identified by tracname - updatedefaults <file>: Adds trac's default options to config""" if len(args) < 1 or args[0] not in [ 'create', 'addrepo', 'sync', 'updatedefaults' ]: print self.cli_command.__doc__ return if args[0] == 'create': if self.has_env(project): print "Project already has a Trac environment!" return if self.create(project): print "Environment created" else: print "Creation failed!" elif args[0] == 'sync': self.sync(project) print project.name, "synced" elif args[0] == 'addrepo': if len(args) < 3: print self.cli_command.__doc__ return repository = project.get_repository(args[1], args[2]) if not repository: print "Unknown repository" return ret = False if len(args) == 4: ret = self.register_repository(repository, args[3]) else: ret = self.register_repository(repository) if ret: print "Successfully added repository" else: print "Adding repository failed!" elif args[0] == 'updatedefaults': if len(args) < 2: print self.cli_command.__doc__ return config = Configuration(args[1]) # load defaults config.set_defaults() config.save()
def sync(self, project): """Sync the trac environment with cydra This sets the options returned by ``get_default_options`` and adds Trac's own defaults if necessary""" if not self.has_env(project): logger.warning('Project %s has no Trac Environment to sync', project.name) return tracini = os.path.join(self.get_env_path(project), 'conf', 'trac.ini') options = self.get_default_options(project) # if inherit is enabled, the default values are supposed to be in # the inherited file. Thus, we can truncate the config file to get a bare minimum if 'inherit_config' in self.component_config: options.append( ('inherit', 'file', self.component_config['inherit_config'])) with open(tracini, 'w') as f: f.truncate() # re-create the configuration file config = Configuration(tracini) for section, name, value in options: config.set(section, name, value) config.save() # load defaults if not any((section, option) == ('inherit', 'file') for section, option, value in options): config.set_defaults() config.save() # check if repositories in cydra match repositories in trac env = Environment(self.get_env_path(project)) rm = RepositoryManager(env) trac_repos = rm.get_real_repositories() trac_repo_names = [r.reponame for r in trac_repos] for repotype, repos in project.data.get('plugins', {}).get('trac', {}).items(): for repo, tracname in (repos or {}).items(): if tracname not in trac_repo_names: logger.warning( "Removing trac mapping from cydra for %s repo %s", repo, tracname) del repos[repo] if not repos: del project.data.get('plugins', {}).get('trac', {})[repotype] # Now do the reverse revmap = dict([(y, x) for (x, y) in self.typemap.items()]) for repo in trac_repos: logger.debug('Looking at trac repo %s', repo.reponame) try: baseparts = repo.get_base().split( ':' ) # This is extremely naiive and possibly breaks some time repotype, path = baseparts[0], baseparts[-1] except: logger.error("Unable to parse: " + repo.get_base()) reponame = os.path.basename(path) if repotype == 'git': reponame = reponame[:-4] try: repository = project.get_repository(revmap[repotype], reponame) except: logger.error("Unable to locate %s %s (%s)", repotype, reponame, path) repository = None logger.debug('Cydra repo %r', repository) if repository: # set this mapping if not there already project.data.setdefault('plugins', {}).setdefault( 'trac', {}).setdefault(repository.type, {})[repository.name] = repo.reponame logger.info('Setting trac mapping for %s %s -> %s', repository.type, repository.name, repo.reponame) else: logger.error("Unable to load %s %s (%s)", revmap[repotype], reponame, path) project.save()
def _do_update(self, req): """Update component enablement.""" components = req.args.getlist('component') oenabled = req.args.getlist('enable') penabled = req.args.getlist('prjenable') changes = False changed = {} # Set global project configuration prjconf = Configuration(conf.global_conf_path) for component in components: c_state = self.get_project_component_state(component, self.config) c_activated = (component in oenabled) if self.is_plugin_changed(c_state, c_activated): self.config.set('components', component, c_activated and 'enabled' or 'disabled') self.log.info('%sabling component %s', c_activated and 'En' or 'Dis', component) changes = True if prjconf: cip_state = self.get_project_component_state(component, prjconf) cip_activated = (component in penabled) if self.is_plugin_changed(cip_state, cip_activated): self.log.info('%sabling project component %s', cip_activated and 'En' or 'Dis', component) changed[component] = cip_activated and 'enabled' or 'disabled' changes = True if prjconf: scomponents = req.args.getlist('setting') static_items = req.args.getlist('static_setting') for scomponent in scomponents: values = self.get_project_component_value(scomponent, None, prjconf) saved_value = self.parse_value(0, values) saved_static = self.parse_value(1, values) current_value = req.args.get(scomponent + '.value').replace('|', '') current_static = (scomponent in static_items) if saved_value != current_value or saved_static != current_static: if current_static: final_value = current_value else: final_value = current_value + '|no' prjconf.set('settings', scomponent, final_value) changes = True if changes: self.config.save() if prjconf: for key in changed.keys(): prjconf.set('components', key, changed[key]) prjconf.save()