tilde-wiki/tildewiki/main.py

194 lines
6.4 KiB
Python
Raw Normal View History

import os
2017-08-31 06:19:29 +00:00
import re
2017-08-30 05:52:24 +00:00
from os.path import expanduser
2017-08-29 07:33:03 +00:00
import click
2017-08-30 05:52:24 +00:00
import pygit2
from click import ClickException
2017-08-30 05:52:24 +00:00
from click.types import Path
2017-09-12 05:34:53 +00:00
from shutil import rmtree
from .click_types import (
WikiRepo
)
from .compilation import (
compile_wiki
)
2017-08-30 05:52:24 +00:00
2017-09-12 05:34:53 +00:00
from . import git_wrapper as git
2017-08-30 05:52:24 +00:00
# TODO support reading from env
SITE_NAME = 'tilde.town'
PUBLISH_PATH = '/var/www/{site_name}/wiki'.format(site_name=SITE_NAME)
PREVIEW_PATH = expanduser('~/public_html/wiki')
LOCAL_REPOSITORY_PATH = expanduser('~/wiki')
REPOSITORY_PATH = '/wiki'
2017-09-12 05:36:13 +00:00
WIPE_PROMPT = 'This will wipe everything at {}. Proceed?'
LOCK_PATH = '/tmp/tildewiki.lock'
2017-08-30 05:52:24 +00:00
DEFAULT_PATH_KWARGS = dict(
2017-08-30 05:52:24 +00:00
exists=True,
writable=True,
readable=True,
file_okay=False,
dir_okay=True)
2017-08-30 05:52:24 +00:00
class Config:
def __init__(self):
self.site_name = SITE_NAME
self.publish_path = PUBLISH_PATH
self.preview_path = PREVIEW_PATH
self.local_repo_path = LOCAL_REPOSITORY_PATH
self.repo_path = REPOSITORY_PATH
self.author_name = os.environ.get('LOGNAME')
@property
def author_email(self):
return '{}@{}'.format(self.author_name, self.site_name)
2017-08-30 05:52:24 +00:00
pass_config = click.make_pass_decorator(Config, ensure=True)
@click.group()
@click.option('--site-name', default=SITE_NAME, help='The root domain of the wiki.')
@click.option('--publish-path',
default=PUBLISH_PATH,
help='System level path to wiki for publishing.',
type=Path(**DEFAULT_PATH_KWARGS))
2017-08-30 05:52:24 +00:00
@click.option('--repo-path',
default=REPOSITORY_PATH,
help='Path to the shared wiki repository.',
type=WikiRepo(**DEFAULT_PATH_KWARGS))
2017-08-30 05:52:24 +00:00
@pass_config
def main(config, site_name, publish_path, repo_path):
# TODO click does not appear to call expanduser on things. it'd be nice to
# opt into that with the Path type. Should click be patched? Or should we
# use a custom Path type?
2017-08-30 05:52:24 +00:00
config.site_name = site_name
config.publish_path = publish_path
config.repo_path = repo_path
2017-08-29 07:33:03 +00:00
2017-08-30 05:52:24 +00:00
@main.command()
@click.option('--local-repo-path', default=LOCAL_REPOSITORY_PATH,
help='Path to shared wiki git repository.', type=Path(file_okay=False))
@click.option('--preview-path', default=PREVIEW_PATH,
help='Local path to wiki for previewing.', type=Path(file_okay=False))
2017-08-30 05:52:24 +00:00
@pass_config
def init(config, local_repo_path, preview_path):
"""
This command, `wiki init`, does the following:
- clones REPOSITORY_PATH to LOCAL_REPOSITORY_PATH
- creates PREVIEW_PATH
- calls the preview command
"""
2017-09-12 05:36:13 +00:00
if os.path.exists(os.path.join(local_repo_path)):
raise ClickException(
'{} already exists. Have you already run wiki init?'.format(
local_repo_path))
2017-09-12 05:36:13 +00:00
if os.path.exists(os.path.join(preview_path)):
raise ClickException(
'{} already exists. Have you already run wiki init?'.format(
preview_path))
2017-08-31 06:19:29 +00:00
click.echo('Cloning {} to {}...'.format(config.repo_path, local_repo_path))
2017-09-12 05:36:13 +00:00
git.create_repo(
config.repo_path,
config.local_repo_path,
config.author_name,
config.author_email
)
2017-08-31 06:19:29 +00:00
click.echo('Creating {}...'.format(preview_path))
os.makedirs(preview_path)
2017-09-01 05:09:33 +00:00
click.echo('Compiling wiki preview for the first time...')
_preview(config, preview_path, local_repo_path)
2017-08-31 06:19:29 +00:00
click.echo('~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~')
2017-09-01 05:09:33 +00:00
click.echo("Congrats, you are ready to contribute to {}'s wiki!".format(
config.site_name
))
2017-08-30 05:52:24 +00:00
@main.command()
@click.option('--local-repo-path', default=LOCAL_REPOSITORY_PATH,
help='Path to local clone of wiki repository.', type=WikiRepo(**DEFAULT_PATH_KWARGS))
@click.option('--preview-path',
default=PREVIEW_PATH,
help='Local path to wiki for previewing.',
type=Path(**DEFAULT_PATH_KWARGS))
2017-08-30 05:52:24 +00:00
@pass_config
2017-08-31 06:19:29 +00:00
def preview(config, preview_path, local_repo_path):
click.confirm(
2017-09-12 05:36:13 +00:00
WIPE_PROMPT.format(preview_path),
2017-08-31 06:19:29 +00:00
abort=True)
2017-09-12 05:36:13 +00:00
rmtree(preview_path)
os.makedirs(preview_path)
2017-09-01 05:09:33 +00:00
_preview(config, preview_path, local_repo_path)
2017-08-30 05:52:24 +00:00
@main.command()
@click.option('--local-repo-path', default=LOCAL_REPOSITORY_PATH,
help='Path to local clone of wiki repository.', type=WikiRepo(**DEFAULT_PATH_KWARGS))
2017-08-30 05:52:24 +00:00
@pass_config
def publish(config, local_repo_path):
2017-09-12 05:36:13 +00:00
if os.path.exists(LOCK_PATH):
raise ClickException('The wiki lock file already exists. Seems like someone else is compiling.')
rm_error_paths = []
onerror = lambda f,p,e: rm_error_paths.append(p)
error = None
lockf = open(LOCK_PATH, 'w')
try:
click.echo('Committing your changes locally...')
git.make_commit(local_repo_path, config.author_name, config.author_email)
git.pull_from_origin(local_repo_path)
click.echo('Pushing your changes...')
git.push_all(local_repo_path)
click.echo('Compiling wiki to {}'.format(config.publish_path))
click.confirm(WIPE_PROMPT.format(config.publish_path), abort=True)
2017-09-23 22:05:05 +00:00
# TODO there is a showstopping bug here: remaking the publish path
# strips all permissions. actually delete the stuff in there, not the
# dir itself.
2017-09-12 05:36:13 +00:00
rmtree(config.publish_path, onerror=onerror)
if len(rm_error_paths) == 0:
os.makedirs(config.publish_path)
elif len(rm_error_paths) == 1 and rm_error_paths[0] == config.publish_path:
pass
else:
raise ClickException('Could not remove some paths: {}'.format(rm_error_paths))
compile_wiki(config.repo_path, config.publish_path)
2017-09-23 08:04:40 +00:00
except ClickException:
raise
2017-09-12 05:36:13 +00:00
except Exception as e:
error = e
finally:
lockf.close()
try:
os.remove(LOCK_PATH)
except FileNotFoundError:
pass
if error is not None:
raise ClickException('Failed publishing wiki. Error: {}'.format(error))
2017-08-30 05:52:24 +00:00
@main.command()
@pass_config
def get(config):
raise NotImplementedError()
@main.command()
@click.option('--local-repo-path', default=LOCAL_REPOSITORY_PATH,
help='Path to shared wiki git repository.', type=WikiRepo(**DEFAULT_PATH_KWARGS))
2017-08-30 05:52:24 +00:00
@pass_config
def reset(config, local_repo_path):
2017-08-30 05:52:24 +00:00
raise NotImplementedError()
def _preview(config, preview_path, local_repo_path):
compile_wiki(local_repo_path, preview_path)
click.echo('Your wiki preview is ready! navigate to ~{}/wiki'.format(
os.environ.get('LOGNAME')))