vimPlugins: update auto-commiting based on review

- Use git.Repo(ROOT, search_parent_directories=True) to find nixpkgs
repo.
- Don't commit overrides.nix.
- Remove "-a" short argument.
- Remove "--commit" flag and commit by default.
- Improve help/error messages.
- Favor closure pattern over classes.Use a closure to wrap the update
function with state rather than a callable class.
- break NixpkgsRepo class into functions
- Optional None-type arguments
- Remove repo checks from update.py. Git is too flexible and permits too
many workflows for my attempt to replace documentation with code to work.
My goal would be to separate the `--add` functionality from the update
functionality in the near term and then there will be no reason for this
usage to create commits anyway.
This commit is contained in:
ryneeverett 2020-03-31 01:01:33 +00:00
parent 1c0f0de46c
commit 0a2759483a
2 changed files with 54 additions and 92 deletions

View File

@ -261,7 +261,7 @@ deoplete-fish = super.deoplete-fish.overrideAttrs(old: {
Sometimes plugins require an override that must be changed when the plugin is updated. This can cause issues when Vim plugins are auto-updated but the associated override isn't updated. For these plugins, the override should be written so that it specifies all information required to install the plugin, and running `./update.py` doesn't change the derivation for the plugin. Manually updating the override is required to update these types of plugins. An example of such a plugin is `LanguageClient-neovim`. Sometimes plugins require an override that must be changed when the plugin is updated. This can cause issues when Vim plugins are auto-updated but the associated override isn't updated. For these plugins, the override should be written so that it specifies all information required to install the plugin, and running `./update.py` doesn't change the derivation for the plugin. Manually updating the override is required to update these types of plugins. An example of such a plugin is `LanguageClient-neovim`.
To add a new plugin, run `./update.py --commit --add "[owner]/[name]"`. To add a new plugin, run `./update.py --add "[owner]/[name]"`. **NOTE**: This script automatically commits to your git repository. Be sure to check out a fresh branch before running.
## Important repositories ## Important repositories

View File

@ -34,11 +34,9 @@ ATOM_LINK = "{http://www.w3.org/2005/Atom}link" # "
ATOM_UPDATED = "{http://www.w3.org/2005/Atom}updated" # " ATOM_UPDATED = "{http://www.w3.org/2005/Atom}updated" # "
ROOT = Path(__file__).parent ROOT = Path(__file__).parent
NIXPKGS_PATH = ROOT.cwd().parents[2]
DEFAULT_IN = ROOT.joinpath("vim-plugin-names") DEFAULT_IN = ROOT.joinpath("vim-plugin-names")
DEFAULT_OUT = ROOT.joinpath("generated.nix") DEFAULT_OUT = ROOT.joinpath("generated.nix")
DEPRECATED = ROOT.joinpath("deprecated.json") DEPRECATED = ROOT.joinpath("deprecated.json")
OVERRIDES = ROOT.joinpath("overrides.nix")
import time import time
from functools import wraps from functools import wraps
@ -78,7 +76,7 @@ def retry(ExceptionToCheck: Any, tries: int = 4, delay: float = 3, backoff: floa
class Repo: class Repo:
def __init__(self, owner: str, name: str, alias: str) -> None: def __init__(self, owner: str, name: str, alias: Optional[str]) -> None:
self.owner = owner self.owner = owner
self.name = name self.name = name
self.alias = alias self.alias = alias
@ -128,7 +126,7 @@ class Repo:
new_owner, new_name = ( new_owner, new_name = (
urllib.parse.urlsplit(response_url).path.strip("/").split("/")[:2] urllib.parse.urlsplit(response_url).path.strip("/").split("/")[:2]
) )
end_line = "\n" if self.alias == "" else f" as {self.alias}\n" end_line = "\n" if self.alias is None else f" as {self.alias}\n"
plugin_line = "{owner}/{name}" + end_line plugin_line = "{owner}/{name}" + end_line
old_plugin = plugin_line.format(owner=self.owner, name=self.name) old_plugin = plugin_line.format(owner=self.owner, name=self.name)
@ -222,17 +220,16 @@ def get_current_plugins() -> List[Plugin]:
def prefetch_plugin( def prefetch_plugin(
user: str, repo_name: str, alias: str, cache: "Cache" = None user: str, repo_name: str, alias: Optional[str], cache: "Optional[Cache]" = None
) -> Tuple[Plugin, Dict[str, str]]: ) -> Tuple[Plugin, Dict[str, str]]:
repo = Repo(user, repo_name, alias) repo = Repo(user, repo_name, alias)
commit, date = repo.latest_commit() commit, date = repo.latest_commit()
has_submodules = repo.has_submodules() has_submodules = repo.has_submodules()
if cache is not None: cached_plugin = cache[commit] if cache else None
cached_plugin = cache[commit] if cached_plugin is not None:
if cached_plugin is not None: cached_plugin.name = alias or repo_name
cached_plugin.name = alias or repo_name cached_plugin.date = date
cached_plugin.date = date return cached_plugin, repo.redirect
return cached_plugin, repo.redirect
print(f"prefetch {user}/{repo_name}") print(f"prefetch {user}/{repo_name}")
if has_submodules: if has_submodules:
@ -287,17 +284,17 @@ def check_results(
sys.exit(1) sys.exit(1)
def parse_plugin_line(line: str) -> Tuple[str, str, str]: def parse_plugin_line(line: str) -> Tuple[str, str, Optional[str]]:
name, repo = line.split("/") name, repo = line.split("/")
try: try:
repo, alias = repo.split(" as ") repo, alias = repo.split(" as ")
return (name, repo, alias.strip()) return (name, repo, alias.strip())
except ValueError: except ValueError:
# no alias defined # no alias defined
return (name, repo.strip(), "") return (name, repo.strip(), None)
def load_plugin_spec(plugin_file: str) -> List[Tuple[str, str, str]]: def load_plugin_spec(plugin_file: str) -> List[Tuple[str, str, Optional[str]]]:
plugins = [] plugins = []
with open(plugin_file) as f: with open(plugin_file) as f:
for line in f: for line in f:
@ -463,11 +460,10 @@ def parse_args():
) )
parser.add_argument( parser.add_argument(
"--add", "--add",
"-a",
dest="add_plugins", dest="add_plugins",
default=[], default=[],
action="append", action="append",
help="Plugin to add to vimPlugins in the form owner/repo", help="Plugin to add to vimPlugins from Github in the form owner/repo",
) )
parser.add_argument( parser.add_argument(
"--input-names", "--input-names",
@ -491,103 +487,69 @@ def parse_args():
default=30, default=30,
help="Number of concurrent processes to spawn.", help="Number of concurrent processes to spawn.",
) )
parser.add_argument(
"--commit",
dest="commit",
action="store_true",
help="Automatically commit updates",
)
parser.add_argument(
"--allow-dirty",
dest="allow_dirty",
action="store_true",
help=(
"Allow commit to continue even if state is unexpectedly dirty. "
"This is only helpful when developing vimPlugins infrastructure."
),
)
return parser.parse_args() return parser.parse_args()
class NixpkgsRepo: def commit(repo: git.Repo, message: str, files: List[Path]) -> None:
def __init__(self, allow_dirty: bool): files_staged = repo.index.add([str(f.resolve()) for f in files])
self.allow_dirty: bool = allow_dirty
self.repo: git.Repo = git.Repo(NIXPKGS_PATH)
if self.is_unexpectedly_dirty(): if files_staged:
raise Exception("Please stash changes before updating.") print(f'committing to nixpkgs "{message}"')
repo.index.commit(message)
def commit(self, message: str, files: List[Path]) -> None: else:
files_staged = self.repo.index.add([str(f.resolve()) for f in files]) print("no changes in working tree to commit")
if files_staged:
print(f'committing to nixpkgs "{message}"')
self.repo.index.commit(message)
assert self.is_unexpectedly_dirty() is False
else:
print("no changes in working tree to commit")
def is_unexpectedly_dirty(self) -> bool:
return self.repo.is_dirty() and not self.allow_dirty
class PluginUpdater: def get_update(input_file: str, outfile: str, proc: int):
def __init__(self, input_file: str, outfile: str, proc: int): cache: Cache = Cache(get_current_plugins())
self.input_file: str = input_file _prefetch = functools.partial(prefetch, cache=cache)
self.outfile: str = outfile
self.proc = proc
self.cache: Cache = Cache(get_current_plugins())
self.prefetch = functools.partial(prefetch, cache=self.cache)
def __call__(self) -> Dict: def update() -> dict:
plugin_names = load_plugin_spec(self.input_file) plugin_names = load_plugin_spec(input_file)
try: try:
# synchronous variant for debugging pool = Pool(processes=proc)
# results = list(map(self.prefetch, plugin_names)) results = pool.map(_prefetch, plugin_names)
pool = Pool(processes=self.proc)
results = pool.map(self.prefetch, plugin_names)
finally: finally:
self.cache.store() cache.store()
plugins, redirects = check_results(results) plugins, redirects = check_results(results)
generate_nix(plugins, self.outfile) generate_nix(plugins, outfile)
return redirects return redirects
return update
def main() -> None:
def main():
args = parse_args() args = parse_args()
if args.add_plugins and not args.commit: nixpkgs_repo = git.Repo(ROOT, search_parent_directories=True)
raise Exception("The --add argument requires setting the --commit flag.") update = get_update(args.input_file, args.outfile, args.proc)
if args.commit:
nixpkgs_repo = NixpkgsRepo(args.allow_dirty)
updater = PluginUpdater(args.input_file, args.outfile, args.proc)
redirects = updater() redirects = update()
rewrite_input(args.input_file, redirects) rewrite_input(args.input_file, redirects)
commit(nixpkgs_repo, "vimPlugins: update", [args.outfile])
if args.commit: if redirects:
nixpkgs_repo.commit("vimPlugins: Update", [args.outfile]) update()
if redirects: commit(
updater() nixpkgs_repo,
nixpkgs_repo.commit( "vimPlugins: resolve github repository redirects",
"vimPlugins: Update redirects", [args.outfile, args.input_file, DEPRECATED],
[args.outfile, args.input_file, DEPRECATED], )
)
for plugin_line in args.add_plugins:
rewrite_input(args.input_file, append=(plugin_line + "\n",))
updater()
plugin = fetch_plugin_from_pluginline(plugin_line) for plugin_line in args.add_plugins:
nixpkgs_repo.commit( rewrite_input(args.input_file, append=(plugin_line + "\n",))
"vimPlugins.{name}: init at {version}".format( update()
name=plugin.normalized_name, version=plugin.version plugin = fetch_plugin_from_pluginline(plugin_line)
), commit(
[args.outfile, args.input_file, OVERRIDES], nixpkgs_repo,
) "vimPlugins.{name}: init at {version}".format(
name=plugin.normalized_name, version=plugin.version
),
[args.outfile, args.input_file],
)
if __name__ == "__main__": if __name__ == "__main__":