From 44c7fb5f0312a09d1f93e60f71384f912110e666 Mon Sep 17 00:00:00 2001 From: Torrie Fischer Date: Sat, 1 Jul 2023 14:46:34 +0200 Subject: [PATCH] cli: pretty++ --- src/mpm/commands/repo.py | 18 ++++++-- src/mpm/commands/server.py | 91 +++++++++++++++++++++++++++++--------- src/mpm/model.py | 12 ++++- src/mpm/server.py | 7 ++- 4 files changed, 102 insertions(+), 26 deletions(-) diff --git a/src/mpm/commands/repo.py b/src/mpm/commands/repo.py index 54b7a8f..37b3cfd 100644 --- a/src/mpm/commands/repo.py +++ b/src/mpm/commands/repo.py @@ -15,13 +15,25 @@ def list_(ctx): for repo in ctx.obj['config'].repositories(): click.echo("{} ({})".format(click.style(repo.name,bold=True), repo.path)) rows = [] + currentPlugin = None + pluginVersions = [] for plugin in sorted(repo.plugins()): + if currentPlugin != plugin.name: + if currentPlugin is not None: + rows.append([ + click.style(currentPlugin, fg='green'), + click.style(', '.join(pluginVersions), fg='yellow') + ]) + currentPlugin = plugin.name + pluginVersions = [] + pluginVersions.append(str(plugin.version)) + if currentPlugin is not None: rows.append([ - click.style(plugin.name, fg='green'), - click.style(str(plugin.version), fg='yellow') + click.style(currentPlugin, fg='green'), + click.style(', '.join(pluginVersions), fg='yellow') ]) if len(rows) > 0: - click.echo(columnar(rows, ['Plugin', 'Version'], no_borders=True)) + click.echo(columnar(rows, ['Plugin', 'Versions'], no_borders=True)) else: click.echo("No plugins found.") for badFile in sorted(repo.badFiles()): diff --git a/src/mpm/commands/server.py b/src/mpm/commands/server.py index 907ec4d..8499e42 100644 --- a/src/mpm/commands/server.py +++ b/src/mpm/commands/server.py @@ -2,6 +2,7 @@ import click from mpm.model import * import pathlib from mpm.config import ServerParamType +from columnar import columnar @click.group(help='Add, remove, and synchronize Servers') def server(): @@ -18,8 +19,11 @@ def add(ctx, name, path): @server.command('list', help='List configured servers') @click.pass_context -def list_(ctx): - for server in ctx.obj['config'].servers(): +@click.argument('servers', type=ServerParamType(), nargs=-1) +def list_(ctx, servers): + if len(servers) == 0: + servers = ctx.obj['config'].servers() + for server in servers: click.echo('{} ({}):'.format(server.name, server.path)) serverPath = pathlib.Path(server.path) if not serverPath.exists(): @@ -46,22 +50,50 @@ def list_(ctx): elif isinstance(state, SymlinkConflict): conflicts.append(state) - click.echo("Installed plugins:") + rows = [] for state in sorted(installed): - click.echo("\t{} {}: {}".format(state.plugin.name, state.plugin.versionSpec, state.currentVersion)) - click.echo("Oudated symlinks:") + rows.append([ + state.plugin.name, + str(state.plugin.versionSpec), + str(state.currentVersion), + str(state.currentVersion), + ]) for state in sorted(outdatedLinks): - click.echo("\t{} {}: Current: {} Wanted: {}".format(state.plugin.name, state.plugin.versionSpec, state.currentVersion, state.wantedVersion)) - click.echo("Missing plugins:") + rows.append([ + state.plugin.name, + click.style(str(state.wantedVersion), fg='green'), + click.style(str(state.currentVersion), fg='yellow'), + click.style(str(state.plugin.versionSpec), fg='green') + ]) for state in sorted(missing): - click.echo("\t{}: {}".format(state.plugin.name, state.plugin.versionSpec)) - click.echo("Unmanaged files:") + rows.append([ + click.style(state.plugin.name, fg='red'), + click.style(str(state.plugin.versionSpec), fg='yellow'), + click.style('Missing', fg='red'), + click.style('Missing', fg='red') + ]) for state in sorted(unmanaged): - click.echo("\t{}".format(state.filename)) - click.echo("Symlink Conflicts:") + rows.append([ + click.style(state.filename, fg='yellow'), + '?', + click.style('Unmanaged', fg='yellow', bold=True), + '' + ]) for state in sorted(conflicts): + rows.append([ + state.plugin.name, + click.style(str(state.plugin.versionSpec), fg='yellow'), + click.style('Symlink Conflict', fg='red', bold=True), + click.style(str(state.plugin.versionSpec), fg='yellow'), + ]) click.echo("\t{}.jar".format(state.plugin.name)) + if len(rows) > 0: + click.echo(columnar(rows, ['Plugin', 'Wanted', 'Installed', + 'Available'], no_borders=True)) + else: + click.echo(click.style('No plugins configured!', fg='yellow')) + @server.command(help='Add a plugin to a server') @click.pass_context @click.argument('server', type=ServerParamType()) @@ -100,10 +132,9 @@ def add_plugin(ctx, server, plugins): else: click.echo("Cancelled.") - @server.command(help="Synchronize a server's plugins") @click.pass_context -@click.argument('servers', type=ServerParamType, nargs=-1) +@click.argument('servers', type=ServerParamType(), nargs=-1) def sync(ctx, servers): allServers = ctx.obj['config'].servers() if len(servers) > 0: @@ -121,17 +152,37 @@ def sync(ctx, servers): elif isinstance(state, MissingVersions): missing.append(state) - click.echo("Plugins to update:") + rows = [] + for state in sorted(outdatedLinks): - click.echo("\t{} {}: Current: {} Wanted: {}".format(state.plugin.name, state.plugin.versionSpec, state.currentVersion, state.wantedVersion)) - click.echo("New plugins to install:") + rows.append([ + state.plugin.name, + click.style(str(state.wantedVersion), fg='green'), + click.style(str(state.currentVersion), fg='yellow'), + click.style(str(state.plugin.versionSpec), fg='green') + ]) + for state in sorted(available): - click.echo("\t{}: {}".format(state.plugin.name, state.plugin.version)) + rows.append([ + state.plugin.name, + click.style(str(state.wantedVersion), fg='green'), + click.style('Missing', fg='red'), + click.style(str(state.plugin.version), fg='green') + ]) + click.echo("Missing plugins:") for state in sorted(missing): - click.echo("\t{} {}".format(click.style(state.plugin.name, fg='red'), - click.style(str(state.plugin.versionSpec), - fg='yellow'))) + rows.append([ + click.style(state.plugin.name, fg='red'), + click.style(str(state.plugin.versionSpec), fg='yellow'), + click.style('Missing', fg='red'), + click.style('Missing', fg='red') + ]) + + if len(rows) > 0: + click.echo(columnar(rows, ['Plugin', 'Wanted', 'Installed', + 'Available'], no_borders=True)) + if len(outdatedLinks) > 0 or len(available) > 0: click.echo("Apply changes? [y/N]", nl=False) answer = click.getchar().lower() diff --git a/src/mpm/model.py b/src/mpm/model.py index 84916d5..71e2de9 100644 --- a/src/mpm/model.py +++ b/src/mpm/model.py @@ -83,6 +83,9 @@ class OutdatedSymlink(PluginState): self.currentVersion = currentVersion self.wantedVersion = wantedVersion + def __str__(self): + return 'OutdatedSymlink({})'.format(self.plugin) + class SymlinkConflict(PluginState): pass @@ -90,10 +93,17 @@ class MissingVersions(PluginState): pass class Available(PluginState): - def __init__(self, repoPlugin): + def __init__(self, repoPlugin, wantedVersion): super().__init__(repoPlugin) + self.wantedVersion = wantedVersion + + def __str__(self): + return 'Available({})'.format(self.plugin) class Installed(PluginState): def __init__(self, plugin, currentVersion): super().__init__(plugin) self.currentVersion = currentVersion + + def __str__(self): + return 'Installed({} @ )'.format(self.plugin, self.currentVersion) diff --git a/src/mpm/server.py b/src/mpm/server.py index c5b773f..ed92dc1 100644 --- a/src/mpm/server.py +++ b/src/mpm/server.py @@ -42,7 +42,7 @@ class Server: yield MissingVersions(plugin) else: preferredVersion = list(reversed(sorted(compatibleVersions)))[0] - yield Available(preferredVersion) + yield Available(preferredVersion, plugin.versionSpec) else: preferredVersion = list(reversed(sorted(compatibleVersions)))[0] currentVersion = self.currentVersionForPlugin(plugin.name) @@ -97,4 +97,7 @@ class Server: if not os.path.exists(os.path.join(self.pluginPath, 'versions')): os.path.mkdir(os.path.join(self.pluginPath, 'versions')) dest = os.path.join(self.pluginPath, 'versions/{}-{}.jar'.format(plugin.name, plugin.version)) - shutil.copyfile(plugin.path, dest) + try: + os.link(plugin.path, dest) + except Exception: + shutil.copyfile(plugin.path, dest)