tzk/tw.py

165 lines
4.9 KiB
Python
Raw Normal View History

from contextlib import contextmanager
import functools
import json
import os
from pathlib import Path
2021-08-25 20:25:50 +00:00
import subprocess
from textwrap import dedent
from typing import Optional, Sequence
2021-08-25 20:25:50 +00:00
2021-08-26 19:04:09 +00:00
import config
import git
2021-08-25 20:25:50 +00:00
@functools.lru_cache(1)
def _npm_bin() -> str:
return subprocess.check_output(("npm", "bin"), text=True).strip()
@contextmanager
def _pushd(directory: str):
"""
Change directory into the directory /directory/ until the end of the with-block,
then return to previous directory.
"""
old_directory = os.getcwd()
try:
os.chdir(directory)
yield
finally:
os.chdir(old_directory)
def _tw_path() -> str:
return _npm_bin() + "/tiddlywiki"
@functools.lru_cache(1)
def _whoami() -> str:
try:
return subprocess.check_output(("whoami",), text=True).strip()
except subprocess.CalledProcessError:
return "user"
2021-08-26 19:11:56 +00:00
def exec(args: Sequence[Sequence[str]], base_wiki_folder: str = None) -> int:
call_args = [_tw_path()]
2021-08-26 19:11:56 +00:00
if base_wiki_folder is not None:
call_args.append(base_wiki_folder)
2021-08-25 20:25:50 +00:00
for tw_arg in args:
call_args.append(f"--{tw_arg[0]}")
for inner_arg in tw_arg[1:]:
call_args.append(inner_arg)
return subprocess.call(call_args)
def _init_npm(wiki_name: str, tw_version_spec: str, author: str) -> None:
"""
Create a package.json file for this repository, requiring TiddlyWiki
at the specified version, and install the npm dependencies.
"""
print("tzk: Creating package.json...")
PACKAGE_JSON = dedent("""
{
"name": "%(wiki_name)s",
"version": "1.0.0",
"description": "My nice notes",
"dependencies": {
"tiddlywiki": "%(tw_version_spec)s"
},
"author": "%(author)s",
"license": "See copyright notice in wiki"
}
""").strip() % ({'tw_version_spec': tw_version_spec, 'author': author,
'wiki_name': wiki_name})
with open("package.json", "w") as f:
f.write(PACKAGE_JSON)
print("tzk: Installing npm packages from package.json...")
subprocess.check_call(("npm", "install"))
def _init_tw(wiki_name: str) -> None:
"""
Create a new TiddlyWiki in the subfolder named 'wiki_name'
using 'tiddlywiki --init'.
"""
print("tzk: Creating new TiddlyWiki...")
try:
os.mkdir(wiki_name)
except FileExistsError:
pass
with _pushd(wiki_name):
subprocess.check_call((_tw_path(), "--init"))
def _save_wikifolder_to_config(wiki_name: str) -> bool:
"""
Set the wiki_folder config option to the wiki_name we initialized with,
if it's not already set in the config.
Return True if the option ended set to wiki_name, False otherwise.
"""
print("tzk: Writing new wiki folder to config file...")
2021-08-26 19:04:09 +00:00
if not config.cm.write_attr("wiki_folder", wiki_name):
if config.cm.wiki_folder == wiki_name:
print("tzk: (Looks like it was already there.)")
else:
print(f"tzk: WARNING: The wiki_folder option in your config appears "
2021-08-26 19:04:09 +00:00
f"to be set to '{config.cm.wiki_folder}', rather than the wiki folder "
f"you're initializing, {wiki_name}. Please check your config file "
"and update this option if necessary.")
return False
return True
def _add_filesystem_plugins(wiki_name: str) -> None:
print("tzk: Adding filesystem plugins to tiddlywiki.info...")
info_path = Path.cwd() / wiki_name / "tiddlywiki.info"
with info_path.open("r") as f:
info_data = json.load(f)
info_data['plugins'] = ["tiddlywiki/filesystem", "tiddlywiki/tiddlyweb"]
with info_path.open("w") as f:
json.dump(info_data, f)
def _init_gitignore() -> None:
print("tzk: Creating gitignore...")
GITIGNORE = dedent("""
__pycache__/
node_modules/
.peru/
output/
\$__StoryList.tid
""").strip()
with open(".gitignore", "w") as f:
f.write(GITIGNORE)
def _initial_commit() -> None:
print("tzk: Initializing new Git repository for wiki...")
git.exec("init")
print("tzk: Committing changes to repository...")
git.exec("add", "-A")
git.exec("commit", "-m", "Initial commit")
def install(wiki_name: str, tw_version_spec: str, author: Optional[str]):
# assert: caller has checked npm and git are installed
warnings = False
if author is None:
author = _whoami()
_init_npm(wiki_name, tw_version_spec, author)
_init_tw(wiki_name)
warnings |= not _save_wikifolder_to_config(wiki_name)
_add_filesystem_plugins(wiki_name)
_init_gitignore()
_initial_commit()
if warnings:
print("tzk: Initialization completed with warnings. Read the output and "
"make any changes required, then run 'tzk listen' to start the server.")
else:
print("tzk: Initialized successfully. Run 'tzk listen' to start the server.")