mirror of
https://github.com/getpelican/pelican.git
synced 2025-10-15 20:28:56 +02:00
Delete pelican/tools directory
This commit is contained in:
parent
dd6338e387
commit
143bec67e2
8 changed files with 0 additions and 2038 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -1,354 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import locale
|
|
||||||
import os
|
|
||||||
|
|
||||||
from jinja2 import Environment, FileSystemLoader
|
|
||||||
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
try:
|
|
||||||
import readline # NOQA
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
import tzlocal
|
|
||||||
_DEFAULT_TIMEZONE = tzlocal.get_localzone().zone
|
|
||||||
except ImportError:
|
|
||||||
_DEFAULT_TIMEZONE = 'Europe/Paris'
|
|
||||||
|
|
||||||
from pelican import __version__
|
|
||||||
|
|
||||||
locale.setlocale(locale.LC_ALL, '')
|
|
||||||
try:
|
|
||||||
_DEFAULT_LANGUAGE = locale.getlocale()[0]
|
|
||||||
except ValueError:
|
|
||||||
# Don't fail on macosx: "unknown locale: UTF-8"
|
|
||||||
_DEFAULT_LANGUAGE = None
|
|
||||||
if _DEFAULT_LANGUAGE is None:
|
|
||||||
_DEFAULT_LANGUAGE = 'en'
|
|
||||||
else:
|
|
||||||
_DEFAULT_LANGUAGE = _DEFAULT_LANGUAGE.split('_')[0]
|
|
||||||
|
|
||||||
_TEMPLATES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
|
||||||
"templates")
|
|
||||||
_jinja_env = Environment(
|
|
||||||
loader=FileSystemLoader(_TEMPLATES_DIR),
|
|
||||||
trim_blocks=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
_GITHUB_PAGES_BRANCHES = {
|
|
||||||
'personal': 'main',
|
|
||||||
'project': 'gh-pages'
|
|
||||||
}
|
|
||||||
|
|
||||||
CONF = {
|
|
||||||
'pelican': 'pelican',
|
|
||||||
'pelicanopts': '',
|
|
||||||
'basedir': os.curdir,
|
|
||||||
'ftp_host': 'localhost',
|
|
||||||
'ftp_user': 'anonymous',
|
|
||||||
'ftp_target_dir': '/',
|
|
||||||
'ssh_host': 'localhost',
|
|
||||||
'ssh_port': 22,
|
|
||||||
'ssh_user': 'root',
|
|
||||||
'ssh_target_dir': '/var/www',
|
|
||||||
's3_bucket': 'my_s3_bucket',
|
|
||||||
'cloudfiles_username': 'my_rackspace_username',
|
|
||||||
'cloudfiles_api_key': 'my_rackspace_api_key',
|
|
||||||
'cloudfiles_container': 'my_cloudfiles_container',
|
|
||||||
'dropbox_dir': '~/Dropbox/Public/',
|
|
||||||
'github_pages_branch': _GITHUB_PAGES_BRANCHES['project'],
|
|
||||||
'default_pagination': 10,
|
|
||||||
'siteurl': '',
|
|
||||||
'lang': _DEFAULT_LANGUAGE,
|
|
||||||
'timezone': _DEFAULT_TIMEZONE
|
|
||||||
}
|
|
||||||
|
|
||||||
# url for list of valid timezones
|
|
||||||
_TZ_URL = 'https://en.wikipedia.org/wiki/List_of_tz_database_time_zones'
|
|
||||||
|
|
||||||
|
|
||||||
# Create a 'marked' default path, to determine if someone has supplied
|
|
||||||
# a path on the command-line.
|
|
||||||
class _DEFAULT_PATH_TYPE(str):
|
|
||||||
is_default_path = True
|
|
||||||
|
|
||||||
|
|
||||||
_DEFAULT_PATH = _DEFAULT_PATH_TYPE(os.curdir)
|
|
||||||
|
|
||||||
|
|
||||||
def ask(question, answer=str, default=None, length=None):
|
|
||||||
if answer == str:
|
|
||||||
r = ''
|
|
||||||
while True:
|
|
||||||
if default:
|
|
||||||
r = input('> {} [{}] '.format(question, default))
|
|
||||||
else:
|
|
||||||
r = input('> {} '.format(question))
|
|
||||||
|
|
||||||
r = r.strip()
|
|
||||||
|
|
||||||
if len(r) <= 0:
|
|
||||||
if default:
|
|
||||||
r = default
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
print('You must enter something')
|
|
||||||
else:
|
|
||||||
if length and len(r) != length:
|
|
||||||
print('Entry must be {} characters long'.format(length))
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
|
|
||||||
return r
|
|
||||||
|
|
||||||
elif answer == bool:
|
|
||||||
r = None
|
|
||||||
while True:
|
|
||||||
if default is True:
|
|
||||||
r = input('> {} (Y/n) '.format(question))
|
|
||||||
elif default is False:
|
|
||||||
r = input('> {} (y/N) '.format(question))
|
|
||||||
else:
|
|
||||||
r = input('> {} (y/n) '.format(question))
|
|
||||||
|
|
||||||
r = r.strip().lower()
|
|
||||||
|
|
||||||
if r in ('y', 'yes'):
|
|
||||||
r = True
|
|
||||||
break
|
|
||||||
elif r in ('n', 'no'):
|
|
||||||
r = False
|
|
||||||
break
|
|
||||||
elif not r:
|
|
||||||
r = default
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
print("You must answer 'yes' or 'no'")
|
|
||||||
return r
|
|
||||||
elif answer == int:
|
|
||||||
r = None
|
|
||||||
while True:
|
|
||||||
if default:
|
|
||||||
r = input('> {} [{}] '.format(question, default))
|
|
||||||
else:
|
|
||||||
r = input('> {} '.format(question))
|
|
||||||
|
|
||||||
r = r.strip()
|
|
||||||
|
|
||||||
if not r:
|
|
||||||
r = default
|
|
||||||
break
|
|
||||||
|
|
||||||
try:
|
|
||||||
r = int(r)
|
|
||||||
break
|
|
||||||
except ValueError:
|
|
||||||
print('You must enter an integer')
|
|
||||||
return r
|
|
||||||
else:
|
|
||||||
raise NotImplementedError(
|
|
||||||
'Argument `answer` must be str, bool, or integer')
|
|
||||||
|
|
||||||
|
|
||||||
def ask_timezone(question, default, tzurl):
|
|
||||||
"""Prompt for time zone and validate input"""
|
|
||||||
lower_tz = [tz.lower() for tz in pytz.all_timezones]
|
|
||||||
while True:
|
|
||||||
r = ask(question, str, default)
|
|
||||||
r = r.strip().replace(' ', '_').lower()
|
|
||||||
if r in lower_tz:
|
|
||||||
r = pytz.all_timezones[lower_tz.index(r)]
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
print('Please enter a valid time zone:\n'
|
|
||||||
' (check [{}])'.format(tzurl))
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description="A kickstarter for Pelican",
|
|
||||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
|
||||||
parser.add_argument('-p', '--path', default=_DEFAULT_PATH,
|
|
||||||
help="The path to generate the blog into")
|
|
||||||
parser.add_argument('-t', '--title', metavar="title",
|
|
||||||
help='Set the title of the website')
|
|
||||||
parser.add_argument('-a', '--author', metavar="author",
|
|
||||||
help='Set the author name of the website')
|
|
||||||
parser.add_argument('-l', '--lang', metavar="lang",
|
|
||||||
help='Set the default web site language')
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
print('''Welcome to pelican-quickstart v{v}.
|
|
||||||
|
|
||||||
This script will help you create a new Pelican-based website.
|
|
||||||
|
|
||||||
Please answer the following questions so this script can generate the files
|
|
||||||
needed by Pelican.
|
|
||||||
|
|
||||||
'''.format(v=__version__))
|
|
||||||
|
|
||||||
project = os.path.join(
|
|
||||||
os.environ.get('VIRTUAL_ENV', os.curdir), '.project')
|
|
||||||
no_path_was_specified = hasattr(args.path, 'is_default_path')
|
|
||||||
if os.path.isfile(project) and no_path_was_specified:
|
|
||||||
CONF['basedir'] = open(project).read().rstrip("\n")
|
|
||||||
print('Using project associated with current virtual environment. '
|
|
||||||
'Will save to:\n%s\n' % CONF['basedir'])
|
|
||||||
else:
|
|
||||||
CONF['basedir'] = os.path.abspath(os.path.expanduser(
|
|
||||||
ask('Where do you want to create your new web site?',
|
|
||||||
answer=str, default=args.path)))
|
|
||||||
|
|
||||||
CONF['sitename'] = ask('What will be the title of this web site?',
|
|
||||||
answer=str, default=args.title)
|
|
||||||
CONF['author'] = ask('Who will be the author of this web site?',
|
|
||||||
answer=str, default=args.author)
|
|
||||||
CONF['lang'] = ask('What will be the default language of this web site?',
|
|
||||||
str, args.lang or CONF['lang'], 2)
|
|
||||||
|
|
||||||
if ask('Do you want to specify a URL prefix? e.g., https://example.com ',
|
|
||||||
answer=bool, default=True):
|
|
||||||
CONF['siteurl'] = ask('What is your URL prefix? (see '
|
|
||||||
'above example; no trailing slash)',
|
|
||||||
str, CONF['siteurl'])
|
|
||||||
|
|
||||||
CONF['with_pagination'] = ask('Do you want to enable article pagination?',
|
|
||||||
bool, bool(CONF['default_pagination']))
|
|
||||||
|
|
||||||
if CONF['with_pagination']:
|
|
||||||
CONF['default_pagination'] = ask('How many articles per page '
|
|
||||||
'do you want?',
|
|
||||||
int, CONF['default_pagination'])
|
|
||||||
else:
|
|
||||||
CONF['default_pagination'] = False
|
|
||||||
|
|
||||||
CONF['timezone'] = ask_timezone('What is your time zone?',
|
|
||||||
CONF['timezone'], _TZ_URL)
|
|
||||||
|
|
||||||
automation = ask('Do you want to generate a tasks.py/Makefile '
|
|
||||||
'to automate generation and publishing?', bool, True)
|
|
||||||
|
|
||||||
if automation:
|
|
||||||
if ask('Do you want to upload your website using FTP?',
|
|
||||||
answer=bool, default=False):
|
|
||||||
CONF['ftp'] = True,
|
|
||||||
CONF['ftp_host'] = ask('What is the hostname of your FTP server?',
|
|
||||||
str, CONF['ftp_host'])
|
|
||||||
CONF['ftp_user'] = ask('What is your username on that server?',
|
|
||||||
str, CONF['ftp_user'])
|
|
||||||
CONF['ftp_target_dir'] = ask('Where do you want to put your '
|
|
||||||
'web site on that server?',
|
|
||||||
str, CONF['ftp_target_dir'])
|
|
||||||
if ask('Do you want to upload your website using SSH?',
|
|
||||||
answer=bool, default=False):
|
|
||||||
CONF['ssh'] = True,
|
|
||||||
CONF['ssh_host'] = ask('What is the hostname of your SSH server?',
|
|
||||||
str, CONF['ssh_host'])
|
|
||||||
CONF['ssh_port'] = ask('What is the port of your SSH server?',
|
|
||||||
int, CONF['ssh_port'])
|
|
||||||
CONF['ssh_user'] = ask('What is your username on that server?',
|
|
||||||
str, CONF['ssh_user'])
|
|
||||||
CONF['ssh_target_dir'] = ask('Where do you want to put your '
|
|
||||||
'web site on that server?',
|
|
||||||
str, CONF['ssh_target_dir'])
|
|
||||||
|
|
||||||
if ask('Do you want to upload your website using Dropbox?',
|
|
||||||
answer=bool, default=False):
|
|
||||||
CONF['dropbox'] = True,
|
|
||||||
CONF['dropbox_dir'] = ask('Where is your Dropbox directory?',
|
|
||||||
str, CONF['dropbox_dir'])
|
|
||||||
|
|
||||||
if ask('Do you want to upload your website using S3?',
|
|
||||||
answer=bool, default=False):
|
|
||||||
CONF['s3'] = True,
|
|
||||||
CONF['s3_bucket'] = ask('What is the name of your S3 bucket?',
|
|
||||||
str, CONF['s3_bucket'])
|
|
||||||
|
|
||||||
if ask('Do you want to upload your website using '
|
|
||||||
'Rackspace Cloud Files?', answer=bool, default=False):
|
|
||||||
CONF['cloudfiles'] = True,
|
|
||||||
CONF['cloudfiles_username'] = ask('What is your Rackspace '
|
|
||||||
'Cloud username?', str,
|
|
||||||
CONF['cloudfiles_username'])
|
|
||||||
CONF['cloudfiles_api_key'] = ask('What is your Rackspace '
|
|
||||||
'Cloud API key?', str,
|
|
||||||
CONF['cloudfiles_api_key'])
|
|
||||||
CONF['cloudfiles_container'] = ask('What is the name of your '
|
|
||||||
'Cloud Files container?',
|
|
||||||
str,
|
|
||||||
CONF['cloudfiles_container'])
|
|
||||||
|
|
||||||
if ask('Do you want to upload your website using GitHub Pages?',
|
|
||||||
answer=bool, default=False):
|
|
||||||
CONF['github'] = True,
|
|
||||||
if ask('Is this your personal page (username.github.io)?',
|
|
||||||
answer=bool, default=False):
|
|
||||||
CONF['github_pages_branch'] = \
|
|
||||||
_GITHUB_PAGES_BRANCHES['personal']
|
|
||||||
else:
|
|
||||||
CONF['github_pages_branch'] = \
|
|
||||||
_GITHUB_PAGES_BRANCHES['project']
|
|
||||||
|
|
||||||
try:
|
|
||||||
os.makedirs(os.path.join(CONF['basedir'], 'content'))
|
|
||||||
except OSError as e:
|
|
||||||
print('Error: {}'.format(e))
|
|
||||||
|
|
||||||
try:
|
|
||||||
os.makedirs(os.path.join(CONF['basedir'], 'output'))
|
|
||||||
except OSError as e:
|
|
||||||
print('Error: {}'.format(e))
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(os.path.join(CONF['basedir'], 'pelicanconf.py'),
|
|
||||||
'w', encoding='utf-8') as fd:
|
|
||||||
conf_python = dict()
|
|
||||||
for key, value in CONF.items():
|
|
||||||
conf_python[key] = repr(value)
|
|
||||||
|
|
||||||
_template = _jinja_env.get_template('pelicanconf.py.jinja2')
|
|
||||||
fd.write(_template.render(**conf_python))
|
|
||||||
fd.close()
|
|
||||||
except OSError as e:
|
|
||||||
print('Error: {}'.format(e))
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(os.path.join(CONF['basedir'], 'publishconf.py'),
|
|
||||||
'w', encoding='utf-8') as fd:
|
|
||||||
_template = _jinja_env.get_template('publishconf.py.jinja2')
|
|
||||||
fd.write(_template.render(**CONF))
|
|
||||||
fd.close()
|
|
||||||
except OSError as e:
|
|
||||||
print('Error: {}'.format(e))
|
|
||||||
|
|
||||||
if automation:
|
|
||||||
try:
|
|
||||||
with open(os.path.join(CONF['basedir'], 'tasks.py'),
|
|
||||||
'w', encoding='utf-8') as fd:
|
|
||||||
_template = _jinja_env.get_template('tasks.py.jinja2')
|
|
||||||
fd.write(_template.render(**CONF))
|
|
||||||
fd.close()
|
|
||||||
except OSError as e:
|
|
||||||
print('Error: {}'.format(e))
|
|
||||||
try:
|
|
||||||
with open(os.path.join(CONF['basedir'], 'Makefile'),
|
|
||||||
'w', encoding='utf-8') as fd:
|
|
||||||
py_v = 'python3'
|
|
||||||
_template = _jinja_env.get_template('Makefile.jinja2')
|
|
||||||
fd.write(_template.render(py_v=py_v, **CONF))
|
|
||||||
fd.close()
|
|
||||||
except OSError as e:
|
|
||||||
print('Error: {}'.format(e))
|
|
||||||
|
|
||||||
print('Done. Your new project is available at %s' % CONF['basedir'])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
|
|
@ -1,259 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def err(msg, die=None):
|
|
||||||
"""Print an error message and exits if an exit code is given"""
|
|
||||||
sys.stderr.write(msg + '\n')
|
|
||||||
if die:
|
|
||||||
sys.exit(die if type(die) is int else 1)
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
import pelican
|
|
||||||
except ImportError:
|
|
||||||
err('Cannot import pelican.\nYou must '
|
|
||||||
'install Pelican in order to run this script.',
|
|
||||||
-1)
|
|
||||||
|
|
||||||
|
|
||||||
global _THEMES_PATH
|
|
||||||
_THEMES_PATH = os.path.join(
|
|
||||||
os.path.dirname(
|
|
||||||
os.path.abspath(pelican.__file__)
|
|
||||||
),
|
|
||||||
'themes'
|
|
||||||
)
|
|
||||||
|
|
||||||
__version__ = '0.2'
|
|
||||||
_BUILTIN_THEMES = ['simple', 'notmyidea']
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Main function"""
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description="""Install themes for Pelican""")
|
|
||||||
|
|
||||||
excl = parser.add_mutually_exclusive_group()
|
|
||||||
excl.add_argument(
|
|
||||||
'-l', '--list', dest='action', action="store_const", const='list',
|
|
||||||
help="Show the themes already installed and exit")
|
|
||||||
excl.add_argument(
|
|
||||||
'-p', '--path', dest='action', action="store_const", const='path',
|
|
||||||
help="Show the themes path and exit")
|
|
||||||
excl.add_argument(
|
|
||||||
'-V', '--version', action='version',
|
|
||||||
version='pelican-themes v{}'.format(__version__),
|
|
||||||
help='Print the version of this script')
|
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
'-i', '--install', dest='to_install', nargs='+', metavar="theme path",
|
|
||||||
help='The themes to install')
|
|
||||||
parser.add_argument(
|
|
||||||
'-r', '--remove', dest='to_remove', nargs='+', metavar="theme name",
|
|
||||||
help='The themes to remove')
|
|
||||||
parser.add_argument(
|
|
||||||
'-U', '--upgrade', dest='to_upgrade', nargs='+',
|
|
||||||
metavar="theme path", help='The themes to upgrade')
|
|
||||||
parser.add_argument(
|
|
||||||
'-s', '--symlink', dest='to_symlink', nargs='+', metavar="theme path",
|
|
||||||
help="Same as `--install', but create a symbolic link instead of "
|
|
||||||
"copying the theme. Useful for theme development")
|
|
||||||
parser.add_argument(
|
|
||||||
'-c', '--clean', dest='clean', action="store_true",
|
|
||||||
help="Remove the broken symbolic links of the theme path")
|
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
'-v', '--verbose', dest='verbose',
|
|
||||||
action="store_true",
|
|
||||||
help="Verbose output")
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
to_install = args.to_install or args.to_upgrade
|
|
||||||
to_sym = args.to_symlink or args.clean
|
|
||||||
|
|
||||||
if args.action:
|
|
||||||
if args.action == 'list':
|
|
||||||
list_themes(args.verbose)
|
|
||||||
elif args.action == 'path':
|
|
||||||
print(_THEMES_PATH)
|
|
||||||
elif to_install or args.to_remove or to_sym:
|
|
||||||
if args.to_remove:
|
|
||||||
if args.verbose:
|
|
||||||
print('Removing themes...')
|
|
||||||
|
|
||||||
for i in args.to_remove:
|
|
||||||
remove(i, v=args.verbose)
|
|
||||||
|
|
||||||
if args.to_install:
|
|
||||||
if args.verbose:
|
|
||||||
print('Installing themes...')
|
|
||||||
|
|
||||||
for i in args.to_install:
|
|
||||||
install(i, v=args.verbose)
|
|
||||||
|
|
||||||
if args.to_upgrade:
|
|
||||||
if args.verbose:
|
|
||||||
print('Upgrading themes...')
|
|
||||||
|
|
||||||
for i in args.to_upgrade:
|
|
||||||
install(i, v=args.verbose, u=True)
|
|
||||||
|
|
||||||
if args.to_symlink:
|
|
||||||
if args.verbose:
|
|
||||||
print('Linking themes...')
|
|
||||||
|
|
||||||
for i in args.to_symlink:
|
|
||||||
symlink(i, v=args.verbose)
|
|
||||||
|
|
||||||
if args.clean:
|
|
||||||
if args.verbose:
|
|
||||||
print('Cleaning the themes directory...')
|
|
||||||
|
|
||||||
clean(v=args.verbose)
|
|
||||||
else:
|
|
||||||
print('No argument given... exiting.')
|
|
||||||
|
|
||||||
|
|
||||||
def themes():
|
|
||||||
"""Returns the list of the themes"""
|
|
||||||
for i in os.listdir(_THEMES_PATH):
|
|
||||||
e = os.path.join(_THEMES_PATH, i)
|
|
||||||
|
|
||||||
if os.path.isdir(e):
|
|
||||||
if os.path.islink(e):
|
|
||||||
yield (e, os.readlink(e))
|
|
||||||
else:
|
|
||||||
yield (e, None)
|
|
||||||
|
|
||||||
|
|
||||||
def list_themes(v=False):
|
|
||||||
"""Display the list of the themes"""
|
|
||||||
for t, l in themes():
|
|
||||||
if not v:
|
|
||||||
t = os.path.basename(t)
|
|
||||||
if l:
|
|
||||||
if v:
|
|
||||||
print(t + (" (symbolic link to `" + l + "')"))
|
|
||||||
else:
|
|
||||||
print(t + '@')
|
|
||||||
else:
|
|
||||||
print(t)
|
|
||||||
|
|
||||||
|
|
||||||
def remove(theme_name, v=False):
|
|
||||||
"""Removes a theme"""
|
|
||||||
|
|
||||||
theme_name = theme_name.replace('/', '')
|
|
||||||
target = os.path.join(_THEMES_PATH, theme_name)
|
|
||||||
|
|
||||||
if theme_name in _BUILTIN_THEMES:
|
|
||||||
err(theme_name + ' is a builtin theme.\n'
|
|
||||||
'You cannot remove a builtin theme with this script, '
|
|
||||||
'remove it by hand if you want.')
|
|
||||||
elif os.path.islink(target):
|
|
||||||
if v:
|
|
||||||
print('Removing link `' + target + "'")
|
|
||||||
os.remove(target)
|
|
||||||
elif os.path.isdir(target):
|
|
||||||
if v:
|
|
||||||
print('Removing directory `' + target + "'")
|
|
||||||
shutil.rmtree(target)
|
|
||||||
elif os.path.exists(target):
|
|
||||||
err(target + ' : not a valid theme')
|
|
||||||
else:
|
|
||||||
err(target + ' : no such file or directory')
|
|
||||||
|
|
||||||
|
|
||||||
def install(path, v=False, u=False):
|
|
||||||
"""Installs a theme"""
|
|
||||||
if not os.path.exists(path):
|
|
||||||
err(path + ' : no such file or directory')
|
|
||||||
elif not os.path.isdir(path):
|
|
||||||
err(path + ' : not a directory')
|
|
||||||
else:
|
|
||||||
theme_name = os.path.basename(os.path.normpath(path))
|
|
||||||
theme_path = os.path.join(_THEMES_PATH, theme_name)
|
|
||||||
exists = os.path.exists(theme_path)
|
|
||||||
if exists and not u:
|
|
||||||
err(path + ' : already exists')
|
|
||||||
elif exists and u:
|
|
||||||
remove(theme_name, v)
|
|
||||||
install(path, v)
|
|
||||||
else:
|
|
||||||
if v:
|
|
||||||
print("Copying '{p}' to '{t}' ...".format(p=path,
|
|
||||||
t=theme_path))
|
|
||||||
try:
|
|
||||||
shutil.copytree(path, theme_path)
|
|
||||||
|
|
||||||
try:
|
|
||||||
if os.name == 'posix':
|
|
||||||
for root, dirs, files in os.walk(theme_path):
|
|
||||||
for d in dirs:
|
|
||||||
dname = os.path.join(root, d)
|
|
||||||
os.chmod(dname, 493) # 0o755
|
|
||||||
for f in files:
|
|
||||||
fname = os.path.join(root, f)
|
|
||||||
os.chmod(fname, 420) # 0o644
|
|
||||||
except OSError as e:
|
|
||||||
err("Cannot change permissions of files "
|
|
||||||
"or directory in `{r}':\n{e}".format(r=theme_path,
|
|
||||||
e=str(e)),
|
|
||||||
die=False)
|
|
||||||
except Exception as e:
|
|
||||||
err("Cannot copy `{p}' to `{t}':\n{e}".format(
|
|
||||||
p=path, t=theme_path, e=str(e)))
|
|
||||||
|
|
||||||
|
|
||||||
def symlink(path, v=False):
|
|
||||||
"""Symbolically link a theme"""
|
|
||||||
if not os.path.exists(path):
|
|
||||||
err(path + ' : no such file or directory')
|
|
||||||
elif not os.path.isdir(path):
|
|
||||||
err(path + ' : not a directory')
|
|
||||||
else:
|
|
||||||
theme_name = os.path.basename(os.path.normpath(path))
|
|
||||||
theme_path = os.path.join(_THEMES_PATH, theme_name)
|
|
||||||
if os.path.exists(theme_path):
|
|
||||||
err(path + ' : already exists')
|
|
||||||
else:
|
|
||||||
if v:
|
|
||||||
print("Linking `{p}' to `{t}' ...".format(
|
|
||||||
p=path, t=theme_path))
|
|
||||||
try:
|
|
||||||
os.symlink(path, theme_path)
|
|
||||||
except Exception as e:
|
|
||||||
err("Cannot link `{p}' to `{t}':\n{e}".format(
|
|
||||||
p=path, t=theme_path, e=str(e)))
|
|
||||||
|
|
||||||
|
|
||||||
def is_broken_link(path):
|
|
||||||
"""Returns True if the path given as is a broken symlink"""
|
|
||||||
path = os.readlink(path)
|
|
||||||
return not os.path.exists(path)
|
|
||||||
|
|
||||||
|
|
||||||
def clean(v=False):
|
|
||||||
"""Removes the broken symbolic links"""
|
|
||||||
c = 0
|
|
||||||
for path in os.listdir(_THEMES_PATH):
|
|
||||||
path = os.path.join(_THEMES_PATH, path)
|
|
||||||
if os.path.islink(path):
|
|
||||||
if is_broken_link(path):
|
|
||||||
if v:
|
|
||||||
print('Removing {}'.format(path))
|
|
||||||
try:
|
|
||||||
os.remove(path)
|
|
||||||
except OSError:
|
|
||||||
print('Error: cannot remove {}'.format(path))
|
|
||||||
else:
|
|
||||||
c += 1
|
|
||||||
|
|
||||||
print("\nRemoved {} broken links".format(c))
|
|
||||||
|
|
@ -1,164 +0,0 @@
|
||||||
PY?={{py_v}}
|
|
||||||
PELICAN?={{pelican}}
|
|
||||||
PELICANOPTS={{pelicanopts}}
|
|
||||||
|
|
||||||
BASEDIR=$(CURDIR)
|
|
||||||
INPUTDIR=$(BASEDIR)/content
|
|
||||||
OUTPUTDIR=$(BASEDIR)/output
|
|
||||||
CONFFILE=$(BASEDIR)/pelicanconf.py
|
|
||||||
PUBLISHCONF=$(BASEDIR)/publishconf.py
|
|
||||||
|
|
||||||
{% if ftp %}
|
|
||||||
FTP_HOST={{ftp_host}}
|
|
||||||
FTP_USER={{ftp_user}}
|
|
||||||
FTP_TARGET_DIR={{ftp_target_dir}}
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
{% if ssh %}
|
|
||||||
SSH_HOST={{ssh_host}}
|
|
||||||
SSH_PORT={{ssh_port}}
|
|
||||||
SSH_USER={{ssh_user}}
|
|
||||||
SSH_TARGET_DIR={{ssh_target_dir}}
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
{% if s3 %}
|
|
||||||
S3_BUCKET={{s3_bucket}}
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
{% if cloudfiles %}
|
|
||||||
CLOUDFILES_USERNAME={{cloudfiles_username}}
|
|
||||||
CLOUDFILES_API_KEY={{cloudfiles_api_key}}
|
|
||||||
CLOUDFILES_CONTAINER={{cloudfiles_container}}
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
{% if dropbox %}
|
|
||||||
DROPBOX_DIR={{dropbox_dir}}
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
{% if github %}
|
|
||||||
GITHUB_PAGES_BRANCH={{github_pages_branch}}
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
DEBUG ?= 0
|
|
||||||
ifeq ($(DEBUG), 1)
|
|
||||||
PELICANOPTS += -D
|
|
||||||
endif
|
|
||||||
|
|
||||||
RELATIVE ?= 0
|
|
||||||
ifeq ($(RELATIVE), 1)
|
|
||||||
PELICANOPTS += --relative-urls
|
|
||||||
endif
|
|
||||||
|
|
||||||
SERVER ?= "0.0.0.0"
|
|
||||||
|
|
||||||
PORT ?= 0
|
|
||||||
ifneq ($(PORT), 0)
|
|
||||||
PELICANOPTS += -p $(PORT)
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
help:
|
|
||||||
@echo 'Makefile for a pelican Web site '
|
|
||||||
@echo ' '
|
|
||||||
@echo 'Usage: '
|
|
||||||
@echo ' make html (re)generate the web site '
|
|
||||||
@echo ' make clean remove the generated files '
|
|
||||||
@echo ' make regenerate regenerate files upon modification '
|
|
||||||
@echo ' make publish generate using production settings '
|
|
||||||
@echo ' make serve [PORT=8000] serve site at http://localhost:8000'
|
|
||||||
@echo ' make serve-global [SERVER=0.0.0.0] serve (as root) to $(SERVER):80 '
|
|
||||||
@echo ' make devserver [PORT=8000] serve and regenerate together '
|
|
||||||
@echo ' make devserver-global regenerate and serve on 0.0.0.0 '
|
|
||||||
{% if ssh %}
|
|
||||||
@echo ' make ssh_upload upload the web site via SSH '
|
|
||||||
@echo ' make rsync_upload upload the web site via rsync+ssh '
|
|
||||||
{% endif %}
|
|
||||||
{% if dropbox %}
|
|
||||||
@echo ' make dropbox_upload upload the web site via Dropbox '
|
|
||||||
{% endif %}
|
|
||||||
{% if ftp %}
|
|
||||||
@echo ' make ftp_upload upload the web site via FTP '
|
|
||||||
{% endif %}
|
|
||||||
{% if s3 %}
|
|
||||||
@echo ' make s3_upload upload the web site via S3 '
|
|
||||||
{% endif %}
|
|
||||||
{% if cloudfiles %}
|
|
||||||
@echo ' make cf_upload upload the web site via Cloud Files'
|
|
||||||
{% endif %}
|
|
||||||
{% if github %}
|
|
||||||
@echo ' make github upload the web site via gh-pages '
|
|
||||||
{% endif %}
|
|
||||||
@echo ' '
|
|
||||||
@echo 'Set the DEBUG variable to 1 to enable debugging, e.g. make DEBUG=1 html '
|
|
||||||
@echo 'Set the RELATIVE variable to 1 to enable relative urls '
|
|
||||||
@echo ' '
|
|
||||||
|
|
||||||
html:
|
|
||||||
"$(PELICAN)" "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
[ ! -d "$(OUTPUTDIR)" ] || rm -rf "$(OUTPUTDIR)"
|
|
||||||
|
|
||||||
regenerate:
|
|
||||||
"$(PELICAN)" -r "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS)
|
|
||||||
|
|
||||||
serve:
|
|
||||||
"$(PELICAN)" -l "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS)
|
|
||||||
|
|
||||||
serve-global:
|
|
||||||
"$(PELICAN)" -l "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) -b $(SERVER)
|
|
||||||
|
|
||||||
devserver:
|
|
||||||
"$(PELICAN)" -lr "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS)
|
|
||||||
|
|
||||||
devserver-global:
|
|
||||||
$(PELICAN) -lr $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) -b 0.0.0.0
|
|
||||||
|
|
||||||
publish:
|
|
||||||
"$(PELICAN)" "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(PUBLISHCONF)" $(PELICANOPTS)
|
|
||||||
|
|
||||||
{% set upload = [] %}
|
|
||||||
{% if ssh %}
|
|
||||||
{% set upload = upload + ["ssh_upload"] %}
|
|
||||||
ssh_upload: publish
|
|
||||||
scp -P $(SSH_PORT) -r "$(OUTPUTDIR)"/* "$(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR)"
|
|
||||||
|
|
||||||
{% set upload = upload + ["rsync_upload"] %}
|
|
||||||
rsync_upload: publish
|
|
||||||
rsync -e "ssh -p $(SSH_PORT)" -P -rvzc --include tags --cvs-exclude --delete "$(OUTPUTDIR)"/ "$(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR)"
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
{% if dropbox %}
|
|
||||||
{% set upload = upload + ["dropbox_upload"] %}
|
|
||||||
dropbox_upload: publish
|
|
||||||
cp -r "$(OUTPUTDIR)"/* "$(DROPBOX_DIR)"/
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
{% if ftp %}
|
|
||||||
{% set upload = upload + ["ftp_upload"] %}
|
|
||||||
ftp_upload: publish
|
|
||||||
lftp ftp://$(FTP_USER)@$(FTP_HOST) -e "mirror -R $(OUTPUTDIR) $(FTP_TARGET_DIR) ; quit"
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
{% if s3 %}
|
|
||||||
{% set upload = upload + ["s3_upload"] %}
|
|
||||||
s3_upload: publish
|
|
||||||
aws s3 sync "$(OUTPUTDIR)"/ s3://$(S3_BUCKET) --acl public-read --delete
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
{% if cloudfiles %}
|
|
||||||
{% set upload = upload + ["cf_upload"] %}
|
|
||||||
cf_upload: publish
|
|
||||||
cd "$(OUTPUTDIR)" && swift -v -A https://auth.api.rackspacecloud.com/v1.0 -U $(CLOUDFILES_USERNAME) -K $(CLOUDFILES_API_KEY) upload -c $(CLOUDFILES_CONTAINER) .
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
{% if github %}
|
|
||||||
{% set upload = upload + ["github"] %}
|
|
||||||
github: publish
|
|
||||||
ghp-import -m "Generate Pelican site" -b $(GITHUB_PAGES_BRANCH) "$(OUTPUTDIR)"
|
|
||||||
git push origin $(GITHUB_PAGES_BRANCH)
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
.PHONY: html help clean regenerate serve serve-global devserver publish {{ upload|join(" ") }}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*- #
|
|
||||||
|
|
||||||
AUTHOR = {{author}}
|
|
||||||
SITENAME = {{sitename}}
|
|
||||||
SITEURL = ''
|
|
||||||
|
|
||||||
PATH = 'content'
|
|
||||||
|
|
||||||
TIMEZONE = {{timezone}}
|
|
||||||
|
|
||||||
DEFAULT_LANG = {{lang}}
|
|
||||||
|
|
||||||
# Feed generation is usually not desired when developing
|
|
||||||
FEED_ALL_ATOM = None
|
|
||||||
CATEGORY_FEED_ATOM = None
|
|
||||||
TRANSLATION_FEED_ATOM = None
|
|
||||||
AUTHOR_FEED_ATOM = None
|
|
||||||
AUTHOR_FEED_RSS = None
|
|
||||||
|
|
||||||
# Blogroll
|
|
||||||
LINKS = (('Pelican', 'https://getpelican.com/'),
|
|
||||||
('Python.org', 'https://www.python.org/'),
|
|
||||||
('Jinja2', 'https://palletsprojects.com/p/jinja/'),
|
|
||||||
('You can modify those links in your config file', '#'),)
|
|
||||||
|
|
||||||
# Social widget
|
|
||||||
SOCIAL = (('You can add links in your config file', '#'),
|
|
||||||
('Another social link', '#'),)
|
|
||||||
|
|
||||||
DEFAULT_PAGINATION = {{default_pagination}}
|
|
||||||
|
|
||||||
# Uncomment following line if you want document-relative URLs when developing
|
|
||||||
#RELATIVE_URLS = True
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*- #
|
|
||||||
|
|
||||||
# This file is only used if you use `make publish` or
|
|
||||||
# explicitly specify it as your config file.
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
sys.path.append(os.curdir)
|
|
||||||
from pelicanconf import *
|
|
||||||
|
|
||||||
# If your site is available via HTTPS, make sure SITEURL begins with https://
|
|
||||||
SITEURL = '{{siteurl}}'
|
|
||||||
RELATIVE_URLS = False
|
|
||||||
|
|
||||||
FEED_ALL_ATOM = 'feeds/all.atom.xml'
|
|
||||||
CATEGORY_FEED_ATOM = 'feeds/{slug}.atom.xml'
|
|
||||||
|
|
||||||
DELETE_OUTPUT_DIRECTORY = True
|
|
||||||
|
|
||||||
# Following items are often useful when publishing
|
|
||||||
|
|
||||||
#DISQUS_SITENAME = ""
|
|
||||||
#GOOGLE_ANALYTICS = ""
|
|
||||||
|
|
@ -1,176 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
import os
|
|
||||||
import shlex
|
|
||||||
import shutil
|
|
||||||
import sys
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
from invoke import task
|
|
||||||
from invoke.main import program
|
|
||||||
from invoke.util import cd
|
|
||||||
from pelican import main as pelican_main
|
|
||||||
from pelican.server import ComplexHTTPRequestHandler, RootedHTTPServer
|
|
||||||
from pelican.settings import DEFAULT_CONFIG, get_settings_from_file
|
|
||||||
|
|
||||||
OPEN_BROWSER_ON_SERVE = True
|
|
||||||
SETTINGS_FILE_BASE = 'pelicanconf.py'
|
|
||||||
SETTINGS = {}
|
|
||||||
SETTINGS.update(DEFAULT_CONFIG)
|
|
||||||
LOCAL_SETTINGS = get_settings_from_file(SETTINGS_FILE_BASE)
|
|
||||||
SETTINGS.update(LOCAL_SETTINGS)
|
|
||||||
|
|
||||||
CONFIG = {
|
|
||||||
'settings_base': SETTINGS_FILE_BASE,
|
|
||||||
'settings_publish': 'publishconf.py',
|
|
||||||
# Output path. Can be absolute or relative to tasks.py. Default: 'output'
|
|
||||||
'deploy_path': SETTINGS['OUTPUT_PATH'],
|
|
||||||
{% if ssh %}
|
|
||||||
# Remote server configuration
|
|
||||||
'ssh_user': '{{ssh_user}}',
|
|
||||||
'ssh_host': '{{ssh_host}}',
|
|
||||||
'ssh_port': '{{ssh_port}}',
|
|
||||||
'ssh_path': '{{ssh_target_dir}}',
|
|
||||||
{% endif %}
|
|
||||||
{% if cloudfiles %}
|
|
||||||
# Rackspace Cloud Files configuration settings
|
|
||||||
'cloudfiles_username': '{{cloudfiles_username}}',
|
|
||||||
'cloudfiles_api_key': '{{cloudfiles_api_key}}',
|
|
||||||
'cloudfiles_container': '{{cloudfiles_container}}',
|
|
||||||
{% endif %}
|
|
||||||
{% if github %}
|
|
||||||
# Github Pages configuration
|
|
||||||
'github_pages_branch': '{{github_pages_branch}}',
|
|
||||||
'commit_message': "'Publish site on {}'".format(datetime.date.today().isoformat()),
|
|
||||||
{% endif %}
|
|
||||||
# Host and port for `serve`
|
|
||||||
'host': 'localhost',
|
|
||||||
'port': 8000,
|
|
||||||
}
|
|
||||||
|
|
||||||
@task
|
|
||||||
def clean(c):
|
|
||||||
"""Remove generated files"""
|
|
||||||
if os.path.isdir(CONFIG['deploy_path']):
|
|
||||||
shutil.rmtree(CONFIG['deploy_path'])
|
|
||||||
os.makedirs(CONFIG['deploy_path'])
|
|
||||||
|
|
||||||
@task
|
|
||||||
def build(c):
|
|
||||||
"""Build local version of site"""
|
|
||||||
pelican_run('-s {settings_base}'.format(**CONFIG))
|
|
||||||
|
|
||||||
@task
|
|
||||||
def rebuild(c):
|
|
||||||
"""`build` with the delete switch"""
|
|
||||||
pelican_run('-d -s {settings_base}'.format(**CONFIG))
|
|
||||||
|
|
||||||
@task
|
|
||||||
def regenerate(c):
|
|
||||||
"""Automatically regenerate site upon file modification"""
|
|
||||||
pelican_run('-r -s {settings_base}'.format(**CONFIG))
|
|
||||||
|
|
||||||
@task
|
|
||||||
def serve(c):
|
|
||||||
"""Serve site at http://$HOST:$PORT/ (default is localhost:8000)"""
|
|
||||||
|
|
||||||
class AddressReuseTCPServer(RootedHTTPServer):
|
|
||||||
allow_reuse_address = True
|
|
||||||
|
|
||||||
server = AddressReuseTCPServer(
|
|
||||||
CONFIG['deploy_path'],
|
|
||||||
(CONFIG['host'], CONFIG['port']),
|
|
||||||
ComplexHTTPRequestHandler)
|
|
||||||
|
|
||||||
if OPEN_BROWSER_ON_SERVE:
|
|
||||||
# Open site in default browser
|
|
||||||
import webbrowser
|
|
||||||
webbrowser.open("http://{host}:{port}".format(**CONFIG))
|
|
||||||
|
|
||||||
sys.stderr.write('Serving at {host}:{port} ...\n'.format(**CONFIG))
|
|
||||||
server.serve_forever()
|
|
||||||
|
|
||||||
@task
|
|
||||||
def reserve(c):
|
|
||||||
"""`build`, then `serve`"""
|
|
||||||
build(c)
|
|
||||||
serve(c)
|
|
||||||
|
|
||||||
@task
|
|
||||||
def preview(c):
|
|
||||||
"""Build production version of site"""
|
|
||||||
pelican_run('-s {settings_publish}'.format(**CONFIG))
|
|
||||||
|
|
||||||
@task
|
|
||||||
def livereload(c):
|
|
||||||
"""Automatically reload browser tab upon file modification."""
|
|
||||||
from livereload import Server
|
|
||||||
|
|
||||||
def cached_build():
|
|
||||||
cmd = '-s {settings_base} -e CACHE_CONTENT=True LOAD_CONTENT_CACHE=True'
|
|
||||||
pelican_run(cmd.format(**CONFIG))
|
|
||||||
|
|
||||||
cached_build()
|
|
||||||
server = Server()
|
|
||||||
theme_path = SETTINGS['THEME']
|
|
||||||
watched_globs = [
|
|
||||||
CONFIG['settings_base'],
|
|
||||||
'{}/templates/**/*.html'.format(theme_path),
|
|
||||||
]
|
|
||||||
|
|
||||||
content_file_extensions = ['.md', '.rst']
|
|
||||||
for extension in content_file_extensions:
|
|
||||||
content_glob = '{0}/**/*{1}'.format(SETTINGS['PATH'], extension)
|
|
||||||
watched_globs.append(content_glob)
|
|
||||||
|
|
||||||
static_file_extensions = ['.css', '.js']
|
|
||||||
for extension in static_file_extensions:
|
|
||||||
static_file_glob = '{0}/static/**/*{1}'.format(theme_path, extension)
|
|
||||||
watched_globs.append(static_file_glob)
|
|
||||||
|
|
||||||
for glob in watched_globs:
|
|
||||||
server.watch(glob, cached_build)
|
|
||||||
|
|
||||||
if OPEN_BROWSER_ON_SERVE:
|
|
||||||
# Open site in default browser
|
|
||||||
import webbrowser
|
|
||||||
webbrowser.open("http://{host}:{port}".format(**CONFIG))
|
|
||||||
|
|
||||||
server.serve(host=CONFIG['host'], port=CONFIG['port'], root=CONFIG['deploy_path'])
|
|
||||||
|
|
||||||
{% if cloudfiles %}
|
|
||||||
@task
|
|
||||||
def cf_upload(c):
|
|
||||||
"""Publish to Rackspace Cloud Files"""
|
|
||||||
rebuild(c)
|
|
||||||
with cd(CONFIG['deploy_path']):
|
|
||||||
c.run('swift -v -A https://auth.api.rackspacecloud.com/v1.0 '
|
|
||||||
'-U {cloudfiles_username} '
|
|
||||||
'-K {cloudfiles_api_key} '
|
|
||||||
'upload -c {cloudfiles_container} .'.format(**CONFIG))
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
@task
|
|
||||||
def publish(c):
|
|
||||||
"""Publish to production via rsync"""
|
|
||||||
pelican_run('-s {settings_publish}'.format(**CONFIG))
|
|
||||||
c.run(
|
|
||||||
'rsync --delete --exclude ".DS_Store" -pthrvz -c '
|
|
||||||
'-e "ssh -p {ssh_port}" '
|
|
||||||
'{} {ssh_user}@{ssh_host}:{ssh_path}'.format(
|
|
||||||
CONFIG['deploy_path'].rstrip('/') + '/',
|
|
||||||
**CONFIG))
|
|
||||||
|
|
||||||
{% if github %}
|
|
||||||
@task
|
|
||||||
def gh_pages(c):
|
|
||||||
"""Publish to GitHub Pages"""
|
|
||||||
preview(c)
|
|
||||||
c.run('ghp-import -b {github_pages_branch} '
|
|
||||||
'-m {commit_message} '
|
|
||||||
'{deploy_path} -p'.format(**CONFIG))
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
def pelican_run(cmd):
|
|
||||||
cmd += ' ' + program.core.remainder # allows to pass-through args to pelican
|
|
||||||
pelican_main(shlex.split(cmd))
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue