def update(self, argv): """ Updates any plugins installed through a URL. This basically runs ``git pull`` within any directory inside the :file:`.jig/plugis` directory. It's a very simple method of updating plugins that have already been installed. """ path = argv.path with self.out() as out: # Make sure that this directory has been initialized for Jig get_jigconfig(path) results = update_plugins(path) if not results: out.append('No plugins to update.') return out.append('Updating plugins') out.append('') for pm, output in results.items(): names = set([i.name for i in pm.plugins]) bundles = set([i.bundle for i in pm.plugins]) out.append('Plugin {0} in bundle {1}'.format( ', '.join(names), ', '.join(bundles))) out.extend(indent(output.splitlines()))
def remove(self, argv): """ Remove a plugin. This method is smart enough to work with only the plugin name if it happens to be unique. If there is more than one plugin with the same name but in a different bundle it will exit with an error. """ path = argv.path name = argv.name bundle = argv.bundle with self.out() as out: config = get_jigconfig(path) pm = PluginManager(config) plugins = plugins_by_name(pm) # Find the bundle if it's not specified if name in plugins and not bundle: if len(plugins[name]) > 1: # There are more than one plugin by this name raise CommandError( 'More than one plugin has the name of ' '{0}. Use the list command to see installed ' 'plugins.'.format(name)) bundle = plugins[name][0].bundle pm.remove(bundle, name) set_jigconfig(path, pm.config) out.append('Removed plugin {0}'.format(name))
def test_add_plugin(self): """ Adds a valid plugin. """ plugin_dir = create_plugin(self.plugindir, template='python', bundle='a', name='a') # We are going to test whether it defaults --gitrepo to cwd self.run_command('add {0}'.format(plugin_dir)) config = get_jigconfig(self.gitrepodir) # The config now contains our section self.assertTrue(config.has_section('plugin:a:a')) self.assertResults( u''' Added plugin a in bundle a to the repository. Run the plugins in the current repository with this command: $ jig runnow Jig works off of your staged files in the Git repository index. You place things in the index with `git add`. You will need to stage some files before you can run Jig.''', self.output)
def set(self, argv): """ Change a single setting for an installed plugin. """ path = argv.path key = argv.key key_parts = key.split('.', 3) config_value = argv.value with self.out(): if len(key_parts) != 3: # The key is not correct raise ConfigKeyInvalid( '{0} is an invalid config key.'.format(key)) bundle, plugin, config_key = key_parts config = get_jigconfig(path) pm = PluginManager(config) if not self._has_plugin(pm, bundle, plugin): raise CommandError('Could not locate plugin {0}.'.format( plugin)) section_name = 'plugin:{0}:{1}'.format( bundle, plugin) # Finally change the setting pm.config.set(section_name, config_key, config_value) set_jigconfig(path, pm.config)
def list(self, argv): """ List the installed plugins. """ path = argv.path with self.out() as out: config = get_jigconfig(path) pm = PluginManager(config) bundles = plugins_by_bundle(pm) if not bundles: out.append(u'No plugins installed.') out.extend(NO_PLUGINS_INSTALLED) return out.append(u'Installed plugins\n') out.append(u'{h1:<25} {h2}'.format( h1=u'Plugin name', h2=u'Bundle name')) sort_bundles = sorted(bundles.items(), key=lambda b: b[0]) for name, plugins in sort_bundles: sort_plugins = sorted(plugins, key=lambda p: p.name) for plugin in sort_plugins: out.append(u'{plugin:.<25} {name}'.format( name=name, plugin=plugin.name)) out.extend(USE_RUNNOW)
def list(self, argv): """ List the current settings for all plugins. """ path = argv.path with self.out() as out: config = get_jigconfig(path) pm = PluginManager(config) if not pm.plugins: out.append(u'No plugins installed.') out.extend(NO_PLUGINS_INSTALLED) return for meta in self._settings(pm): out.append( u'{bundle}.{plugin}.{config_key}={config_value}'.format( bundle=meta.plugin.bundle, plugin=meta.plugin.name, config_key=meta.key, config_value=meta.value ) ) if not out: out.append(u'Installed plugins have no settings.') out.extend(CHANGE_PLUGIN_SETTINGS)
def test_add_plugin(self): """ Adds a valid plugin. """ plugin_dir = create_plugin( self.plugindir, template='python', bundle='a', name='a') # We are going to test whether it defaults --gitrepo to cwd self.run_command('add {0}'.format(plugin_dir)) config = get_jigconfig(self.gitrepodir) # The config now contains our section self.assertTrue(config.has_section('plugin:a:a')) self.assertResults( u''' Added plugin a in bundle a to the repository. Run the plugins in the current repository with this command: $ jig runnow Jig works off of your staged files in the Git repository index. You place things in the index with `git add`. You will need to stage some files before you can run Jig.''', self.output)
def set(self, argv): """ Change a single setting for an installed plugin. """ path = argv.path key = argv.key key_parts = key.split('.', 3) config_value = argv.value with self.out(): if len(key_parts) != 3: # The key is not correct raise ConfigKeyInvalid( '{0} is an invalid config key.'.format(key)) bundle, plugin, config_key = key_parts config = get_jigconfig(path) pm = PluginManager(config) if not self._has_plugin(pm, bundle, plugin): raise CommandError( 'Could not locate plugin {0}.'.format(plugin)) section_name = 'plugin:{0}:{1}'.format(bundle, plugin) # Finally change the setting pm.config.set(section_name, config_key, config_value) set_jigconfig(path, pm.config)
def list(self, argv): """ List the current settings for all plugins. """ path = argv.path with self.out() as out: config = get_jigconfig(path) pm = PluginManager(config) if not pm.plugins: out.append(u'No plugins installed.') out.extend(NO_PLUGINS_INSTALLED) return for meta in self._settings(pm): out.append( u'{bundle}.{plugin}.{config_key}={config_value}'.format( bundle=meta.plugin.bundle, plugin=meta.plugin.name, config_key=meta.key, config_value=meta.value)) if not out: out.append(u'Installed plugins have no settings.') out.extend(CHANGE_PLUGIN_SETTINGS)
def process(self, argv): path = argv.path plugins_file = argv.pluginsfile with self.out() as out: try: plugin_list = read_plugin_list(plugins_file) except IOError as e: # Grab the human-readable part of the IOError and raise that raise PluginError(e[1]) for plugin in plugin_list: config = get_jigconfig(path) pm = PluginManager(config) try: added = add_plugin(pm, plugin, path) except Exception as e: out.append('From {0}:\n - {1}'.format(plugin, e)) continue set_jigconfig(path, pm.config) out.append('From {0}:'.format(plugin)) for p in added: out.append(' - Added plugin {0} in bundle {1}'.format( p.name, p.bundle)) out.extend(USE_RUNNOW)
def test_config_set(self): """ Setting can be changed. """ self._add_plugin( create_plugin(self.plugindir, template='python', bundle='test01', name='plugin01', settings={ 'a': '1', 'b': '2', 'c': '3' })) self.run_command('set -r {0} test01.plugin01.a 111'.format( self.gitrepodir)) # Setting was changed, no output to the console self.assertEqual('', self.output) # The setting was changed config = get_jigconfig(self.gitrepodir) self.assertEqual('111', config.get('plugin:test01:plugin01', 'a'))
def _add_plugin(self, plugin_dir): """ Adds a plugin to the jig initialized Git repository. """ config = get_jigconfig(self.gitrepodir) pm = PluginManager(config) pm.add(plugin_dir) set_jigconfig(self.gitrepodir, pm.config)
def _set(self, gitrepodir, bundle_name, plugin_name, key, value): """ Change a setting for a plugin and save the Jig config. """ config = get_jigconfig(self.gitrepodir) pm = PluginManager(config) pm.config.set("plugin:{0}:{1}".format(bundle_name, plugin_name), key, value) set_jigconfig(self.gitrepodir, pm.config)
def test_get_config(self): """ Get a config. """ initializer(self.gitrepodir) plugins = get_jigconfig(self.gitrepodir) self.assertTrue(isinstance(plugins, ConfigParser)) self.assertTrue(isfile(join(self.gitrepodir, '.jig', 'plugins.cfg')))
def test_no_last_checked(self): """ If the repo has never been checked for an update. """ config = get_jigconfig(self.gitrepodir) config.remove_section('jig') set_jigconfig(self.gitrepodir, config) last_check = last_checked_for_updates(self.gitrepodir) self.assertEqual(0, last_check)
def test_bad_last_checked(self): """ If the repo has a bad last checked value. """ config = get_jigconfig(self.gitrepodir) config.set('jig', 'last_checked_for_updates', 'bad') set_jigconfig(self.gitrepodir, config) last_check = last_checked_for_updates(self.gitrepodir) self.assertEqual(0, last_check)
def _set(self, gitrepodir, bundle_name, plugin_name, key, value): """ Change a setting for a plugin and save the Jig config. """ config = get_jigconfig(self.gitrepodir) pm = PluginManager(config) pm.config.set('plugin:{0}:{1}'.format(bundle_name, plugin_name), key, value) set_jigconfig(self.gitrepodir, pm.config)
def _clear_settings(self, gitrepodir): """ Remove all plugin specific settings. """ config = get_jigconfig(self.gitrepodir) pm = PluginManager(config) for section in pm.config.sections(): if not section.startswith("plugin"): continue for option, value in pm.config.items(section): if option == "path": continue pm.config.remove_option(section, option) set_jigconfig(self.gitrepodir, pm.config)
def _clear_settings(self, gitrepodir): """ Remove all plugin specific settings. """ config = get_jigconfig(self.gitrepodir) pm = PluginManager(config) for section in pm.config.sections(): if not section.startswith('plugin'): continue for option, value in pm.config.items(section): if option == 'path': continue pm.config.remove_option(section, option) set_jigconfig(self.gitrepodir, pm.config)
def test_remove_plugin(self): """ Removes an installed plugin. """ plugin_dir = create_plugin(self.plugindir, template='python', bundle='bundle', name='name') self.run_command('add -r {0} {1}'.format(self.gitrepodir, plugin_dir)) # Remove with the --gitrepo defaulting to cwd again self.run_command('remove name bundle') config = get_jigconfig(self.gitrepodir) # It should be removed from our config now self.assertFalse(config.has_section('plugin:bundle:name')) self.assertEqual(u'Removed plugin name\n', self.output)
def test_remove_plugin(self): """ Removes an installed plugin. """ plugin_dir = create_plugin( self.plugindir, template='python', bundle='bundle', name='name') self.run_command('add -r {0} {1}'.format(self.gitrepodir, plugin_dir)) # Remove with the --gitrepo defaulting to cwd again self.run_command('remove name bundle') config = get_jigconfig(self.gitrepodir) # It should be removed from our config now self.assertFalse(config.has_section('plugin:bundle:name')) self.assertEqual( u'Removed plugin name\n', self.output)
def add(self, argv): """ Add a plugin. """ path = argv.path plugin = argv.plugin with self.out() as out: config = get_jigconfig(path) pm = PluginManager(config) added = add_plugin(pm, plugin, path) set_jigconfig(path, pm.config) for p in added: out.append( 'Added plugin {0} in bundle {1} to the ' 'repository.'.format(p.name, p.bundle)) out.extend(USE_RUNNOW)
def test_config_set(self): """ Setting can be changed. """ self._add_plugin( create_plugin( self.plugindir, template="python", bundle="test01", name="plugin01", settings={"a": "1", "b": "2", "c": "3"}, ) ) self.run_command("set -r {0} test01.plugin01.a 111".format(self.gitrepodir)) # Setting was changed, no output to the console self.assertEqual("", self.output) # The setting was changed config = get_jigconfig(self.gitrepodir) self.assertEqual("111", config.get("plugin:test01:plugin01", "a"))
def about(self, argv): """ Provide about/help on each plugin setting. """ path = argv.path def wrap(payload): indent = ' ' tw = TextWrapper(width=70, initial_indent=indent, subsequent_indent=indent) return u'\n'.join(tw.wrap(payload)) with self.out() as out: config = get_jigconfig(path) pm = PluginManager(config) if not pm.plugins: out.append(u'No plugins installed.') out.extend(NO_PLUGINS_INSTALLED) return for meta in self._settings(pm): out.append(u'{bundle}.{plugin}.{config_key}'.format( bundle=meta.plugin.bundle, plugin=meta.plugin.name, config_key=meta.key)) out.append(u'(default: {0})'.format(meta.default)) if meta.about: out.append(wrap(meta.about.strip())) out.append(u'') if not out: out.append(u'Installed plugins have no settings.')
def about(self, argv): """ Provide about/help on each plugin setting. """ path = argv.path def wrap(payload): indent = ' ' tw = TextWrapper( width=70, initial_indent=indent, subsequent_indent=indent) return u'\n'.join(tw.wrap(payload)) with self.out() as out: config = get_jigconfig(path) pm = PluginManager(config) if not pm.plugins: out.append(u'No plugins installed.') out.extend(NO_PLUGINS_INSTALLED) return for meta in self._settings(pm): out.append(u'{bundle}.{plugin}.{config_key}'.format( bundle=meta.plugin.bundle, plugin=meta.plugin.name, config_key=meta.key)) out.append(u'(default: {0})'.format(meta.default)) if meta.about: out.append(wrap(meta.about.strip())) out.append(u'') if not out: out.append(u'Installed plugins have no settings.')
def test_get_config_not_initialized(self): """ Attempting to get a config for a directory not initialized. """ with self.assertRaises(GitRepoNotInitialized): get_jigconfig(self.gitrepodir)
def results(self, gitrepo, plugin=None, rev_range=None): """ Run jig in the repository and return results. Results will be a dictionary where the keys will be individual plugins and the value the result of calling their ``pre_commit()`` methods. :param unicode gitrepo: path to the Git repository :param unicode plugin: the name of the plugin to run, if None then run all plugins :param unicode rev_range: the revision range to use instead of the Git index """ self.gitrepo = gitrepo # Is this repository initialized to use jig on? with self.view.out() as out: if not repo_jiginitialized(self.gitrepo): raise GitRepoNotInitialized( 'This repository has not been initialized.') pm = PluginManager(get_jigconfig(self.gitrepo)) # Check to make sure we have some plugins to run with self.view.out() as out: if len(pm.plugins) == 0: out.append( 'There are no plugins installed, ' 'use jig install to add some.') return self.repo = Repo(gitrepo) diff = _diff_for(self.repo, rev_range) if diff is None: # No diff on head, no commits have been written yet out.append( 'This repository is empty, jig needs at ' 'least 1 commit to continue.') # Let execution continue so they *can* commit that first # changeset. This is a special mode that should not cause Jig # to exit with non-zero. return if len(diff) == 0: # There is nothing changed in this repository, no need for # jig to run so we exit with 0. out.append( 'No staged changes in the repository, skipping jig.') return # Our git diff index is an object that makes working with the diff much # easier in the context of our plugins. gdi = GitDiffIndex(self.gitrepo, diff) # Go through the plugins and gather up the results results = OrderedDict() for installed in pm.plugins: if plugin and installed.name != plugin: # This plugin doesn't match the requested continue retcode, stdout, stderr = installed.pre_commit(gdi) try: # Is it JSON data? data = json.loads(stdout) except ValueError: # Not JSON data = stdout results[installed] = (retcode, data, stderr) return results
def results(self, gitrepo, plugin=None, rev_range=None): """ Run jig in the repository and return results. Results will be a dictionary where the keys will be individual plugins and the value the result of calling their ``pre_commit()`` methods. :param unicode gitrepo: path to the Git repository :param unicode plugin: the name of the plugin to run, if None then run all plugins :param unicode rev_range: the revision range to use instead of the Git index """ self.gitrepo = gitrepo # Is this repository initialized to use jig on? with self.view.out() as out: if not repo_jiginitialized(self.gitrepo): raise GitRepoNotInitialized( 'This repository has not been initialized.') pm = PluginManager(get_jigconfig(self.gitrepo)) # Check to make sure we have some plugins to run with self.view.out() as out: if len(pm.plugins) == 0: out.append('There are no plugins installed, ' 'use jig install to add some.') return self.repo = Repo(gitrepo) diff = _diff_for(self.repo, rev_range) if diff is None: # No diff on head, no commits have been written yet out.append('This repository is empty, jig needs at ' 'least 1 commit to continue.') # Let execution continue so they *can* commit that first # changeset. This is a special mode that should not cause Jig # to exit with non-zero. return if len(diff) == 0: # There is nothing changed in this repository, no need for # jig to run so we exit with 0. out.append( 'No staged changes in the repository, skipping jig.') return # Our git diff index is an object that makes working with the diff much # easier in the context of our plugins. gdi = GitDiffIndex(self.gitrepo, diff) # Go through the plugins and gather up the results results = OrderedDict() for installed in pm.plugins: if plugin and installed.name != plugin: # This plugin doesn't match the requested continue retcode, stdout, stderr = installed.pre_commit(gdi) try: # Is it JSON data? data = json.loads(stdout) except ValueError: # Not JSON data = stdout results[installed] = (retcode, data, stderr) return results