mpm/main.py

268 lines
9.2 KiB
Python
Executable File

#!/bin/env python
import argparse
import pathlib
import sys
import yaml
import os
from repo import Repo
from server import Server
from model import *
try:
from yaml import CLoader as Loader, CDumper as Dumper
except ImportError:
from yaml import Loader, Dumper
DEFAULT_CONFIG = """
repositories: {}
servers: {}
"""
class Config():
def __init__(self, path):
if path is None:
path = './mpm.yaml'
self.path = path
with open(path, 'r') as fd:
self.yaml = yaml.load(fd, Loader=Loader)
self.config = yaml.load(DEFAULT_CONFIG, Loader=Loader)
if isinstance(self.yaml, dict):
self.config.update(self.yaml)
def repository(self, name):
return Repo(name, self.config['repositories'][name])
def repositories(self):
return [Repo(name, c) for (name, c) in self.config['repositories'].items()]
def update_repository(self, name, config):
self.config['repositories'][name] = config
def add_repository(self, name, path):
if name in self.config['repositories']:
raise ValueError('Repository already exists')
self.update_repository(name, {
'path': path
})
def servers(self):
return [Server(name, c) for (name, c) in self.config['servers'].items()]
def server(self, name):
return Server(name, self.config['servers'][name])
def update_server(self, server, config):
self.config['servers'][server] = config
def add_server(self, name, path):
if name in self.config['servers']:
raise ValueError("Server already exists")
self.update_server(name, {
'path': path,
'plugins': [],
'inherit': []
})
def save(self):
stream = open(self.path, 'w')
yaml.dump(self.config, stream, Dumper=Dumper)
stream.close()
def do_repo_add(args, config):
if not os.path.exists(args.path):
os.makedirs(args.path)
config.add_repository(args.name, args.path)
config.save()
print("Added repository {}".format(args.path))
def do_repo_list(args, config):
for repo in config.repositories():
print("{} ({})".format(repo.name, repo.path))
for plugin in sorted(repo.plugins()):
print('\t', plugin.name, '\t', plugin.version)
for badFile in sorted(repo.badFiles()):
print('\tWARNING: Unknown file', badFile)
def do_repo_import(args, config):
repo = config.repository(args.name)
plugins = []
for path in args.path:
try:
plugins.append(Plugin(path))
except:
print("Bad plugin filename {}".format(path))
if len(plugins) == 0:
print("No plugins found.")
print('Found the following plugins:')
for plugin in plugins:
print("\t{} {}".format(plugin.name, plugin.version))
print("Import plugins into {}? [y/N]".format(repo.name))
answer = input().lower()
if answer == "y":
for plugin in plugins:
repo.importPlugin(plugin)
print("Imported!")
else:
print("Cancelled.")
def do_server_add(args, config):
config.add_server(args.name, args.path)
config.save()
print("Added server {} in {}".format(args.name, args.path))
def do_server_list(args, config):
for server in config.servers():
print('{} ({}):'.format(server.name, server.path))
outdatedLinks = []
missing = []
installed = []
unmanaged = []
conflicts = []
for state in sorted(server.pluginStates(config.repositories())):
if isinstance(state, OutdatedSymlink):
outdatedLinks.append(state)
elif isinstance(state, Installed):
installed.append(state)
elif isinstance(state, MissingVersions):
missing.append(state)
elif isinstance(state, UnmanagedFile):
unmanaged.append(state)
elif isinstance(state, SymlinkConflict):
conflicts.append(state)
print("Installed plugins:")
for state in sorted(installed):
print("\t{} {}: {}".format(state.plugin.name, state.plugin.versionSpec, state.currentVersion))
print("Oudated symlinks:")
for state in sorted(outdatedLinks):
print("\t{} {}: Current: {} Wanted: {}".format(state.plugin.name, state.plugin.versionSpec, state.currentVersion, state.wantedVersion))
print("Missing plugins:")
for state in sorted(missing):
print("\t{}: {}".format(state.plugin.name, state.plugin.versionSpec))
print("Unmanaged files:")
for state in sorted(unmanaged):
print("\t{}".format(state.filename))
print("Symlink Conflicts:")
for state in sorted(conflicts):
print("\t{}.jar".format(state.plugin.name))
def do_server_add_plugin(args, config):
server = config.server(args.server)
plugins = []
for pluginSpec in args.plugin:
if os.path.exists(pluginSpec):
plugin = Plugin(pluginSpec)
pluginSpec = PluginSpec(plugin.name, str(plugin.version))
else:
allVersions = []
for repo in config.repositories():
allVersions += repo.versionsForPlugin(pluginSpec)
pluginSpec = PluginSpec(pluginSpec, list(reversed(sorted(allVersions)))[0])
plugins.append(pluginSpec)
print("Added {} to {}".format(pluginSpec, server.name))
for pluginSpec in plugins:
print("\t{} {}".format(pluginSpec.name, pluginSpec.versionSpec))
print("Add these plugins to server {}? [y/N]".format(server.name))
answer = input().lower()
if answer == "y":
for pluginSpec in plugins:
server.add_plugin(pluginSpec)
config.update_server(server.name, server.config)
config.save()
print("Added!")
else:
print("Cancelled.")
def do_server_sync(args, config):
for server in config.servers():
print('{} ({}):'.format(server.name, server.path))
outdatedLinks = []
available = []
for state in sorted(server.pluginStates(config.repositories())):
if isinstance(state, OutdatedSymlink):
outdatedLinks.append(state)
elif isinstance(state, Available):
available.append(state)
print("Plugins to update:")
for state in sorted(outdatedLinks):
print("\t{} {}: Current: {} Wanted: {}".format(state.plugin.name, state.plugin.versionSpec, state.currentVersion, state.wantedVersion))
print("New plugins to install:")
for state in sorted(available):
print("\t{}: {}".format(state.plugin.name, state.plugin.version))
if len(outdatedLinks) > 0 or len(available) > 0:
print("Apply changes? [y/N]")
answer = input().lower()
if answer == "y":
for state in available:
server.installVersion(state.plugin)
server.updateSymlinkForPlugin(state.plugin, state.plugin.version)
print("Installed {} {}".format(state.plugin.name, state.plugin.version))
for state in outdatedLinks:
server.updateSymlinkForPlugin(state.plugin, state.wantedVersion)
print("Updated {} to {}".format(state.plugin.name, state.wantedVersion))
else:
print("Not applying changes.")
else:
print("No changes to apply.")
def main():
parser = argparse.ArgumentParser(description='Paper Plugin Sync')
parser.add_argument('--config', dest='config_path', type=Config)
subparsers = parser.add_subparsers()
repos = subparsers.add_parser('repo')
repo_sub = repos.add_subparsers()
repo_add = repo_sub.add_parser('add')
repo_add.add_argument('name', help='Name of the repository')
repo_add.add_argument('path', help='Where to add a repository or create a new one')
repo_add.set_defaults(func=do_repo_add)
repo_list = repo_sub.add_parser('list')
repo_list.set_defaults(func=do_repo_list)
repo_import = repo_sub.add_parser('import')
repo_import.add_argument('name', help='Name of the repository')
repo_import.add_argument('path', nargs="+", help='Path of the plugin to import')
repo_import.set_defaults(func=do_repo_import)
servers = subparsers.add_parser('server')
server_sub = servers.add_subparsers()
server_add = server_sub.add_parser('add')
server_add.add_argument('name', help='Name for the server')
server_add.add_argument('path', help='Path to your server\'s root directory')
server_add.set_defaults(func=do_server_add)
server_list = server_sub.add_parser('list')
server_list.set_defaults(func=do_server_list)
server_add_plugin = server_sub.add_parser('add-plugin')
server_add_plugin.add_argument('server', help='Name of server to modify')
server_add_plugin.add_argument('plugin', nargs='+', help='Plugin file or spec to install')
server_add_plugin.set_defaults(func=do_server_add_plugin)
server_sync = server_sub.add_parser('sync')
server_sync.set_defaults(func=do_server_sync)
args = parser.parse_args()
config = Config(args.config_path)
if 'func' not in args:
parser.print_usage()
else:
args.func(args, config)
if __name__ == "__main__":
main()