From 2a4e883191b881049a579d777e2c9c2c3fd3accc Mon Sep 17 00:00:00 2001 From: neodarz Date: Sun, 26 May 2019 23:34:35 +0200 Subject: Rename cli.py to better file name --- cli/cli.py | 221 ------------------------------------------------------ cli/management.py | 221 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ pyblog | 12 +-- 3 files changed, 227 insertions(+), 227 deletions(-) delete mode 100644 cli/cli.py create mode 100644 cli/management.py diff --git a/cli/cli.py b/cli/cli.py deleted file mode 100644 index 9d35c643..00000000 --- a/cli/cli.py +++ /dev/null @@ -1,221 +0,0 @@ -#/bin/python3 - -import subprocess -import sys -import re -import time -import signal - -from config.config import * -from utils import utils -from generators import generators - - -def generate(args): - """Wrapper for generate_blog(fresh=False).""" - # pylint: disable=unused-argument - exit(generators.generate_blog(fresh=False)) - - -def regenerate(args): - """Wrapper for generate_blog(fresh=True).""" - # pylint: disable=unused-argument - exit(generators.generate_blog(fresh=True)) - - -def deploy(args): - """Deploys build directory to origin/master without regenerating. - - Returns - ------- - 0 - On success. Exit early with nonzero status otherwise. - - """ - - # pylint: disable=unused-argument,too-many-statements - - # check whether root is dirty - os.chdir(ROOTDIR) - dirty = subprocess.check_output(["git", "status", "--porcelain"]) - if dirty: - sys.stderr.write(YELLOW) - sys.stderr.write("Project root is dirty.\n") - sys.stderr.write("You may want to commit in your changes " - "to the source branch, since the SHA and title " - "of the latest commit on the source branch will be " - "incorporated into the commit message on " - "the deployment branch. Type s[hell] on the " - "next prompt to open an interactive shell.\n") - sys.stderr.write(RESET) - while True: - sys.stderr.write("Continue? [yNs] ") - answer = input() - if not answer: - # default - abort = True - break - elif answer.startswith(('y', 'Y')): - abort = False - break - elif answer.startswith(('n', 'N')): - abort = True - break - elif answer.startswith(('s', 'S')): - shell = (os.environ['SHELL'] if 'SHELL' in os.environ and os.environ['SHELL'] - else 'zsh') - subprocess.call(shell) - stilldirty = subprocess.check_output(["git", "status", "--porcelain"]) - if stilldirty: - sys.stderr.write(YELLOW) - sys.stderr.write("Project root is still dirty.\n") - sys.stderr.write(RESET) - else: - sys.stderr.write("Please answer yes or no.\n") - if abort: - sys.stderr.write("%saborting deployment%s\n" % (RED, RESET)) - return 1 - - # extract latest commit on the source branch - source_commit = subprocess.check_output( - ["git", "log", "-1", "--pretty=oneline", "source", "--"]).decode('utf-8').strip() - - # cd into BUILDDIR and assemble commit message - sys.stderr.write("%scommand: cd '%s'%s\n" % (BLUE, BUILDDIR, RESET)) - os.chdir(BUILDDIR) - - # extract updated time from atom.xml - if not os.path.exists("atom.xml"): - sys.stderr.write("atom.xml not found, cannot deploy\naborting\n") - return 1 - atomxml = ET.parse("atom.xml").getroot() - updated = atomxml.find('{http://www.w3.org/2005/Atom}updated').text - - commit_message = ("Site updated at %s\n\nsource branch was at:\n%s\n" % - (updated, source_commit)) - - # commit changes in BUILDDIR - sys.stderr.write("%scommand: git add --all%s\n" % (BLUE, RESET)) - subprocess.check_call(["git", "add", "--all"]) - sys.stderr.write("%scommand: git commit --no-verify --gpg-sign --message='%s'%s\n" % - (BLUE, commit_message, RESET)) - try: - subprocess.check_call(["git", "commit", "--gpg-sign", - "--message=%s" % commit_message]) - except subprocess.CalledProcessError: - sys.stderr.write("\n%serror: git commit failed%s\n" % (RED, RESET)) - return 1 - - # check dirty status - dirty = subprocess.check_output(["git", "status", "--porcelain"]) - if dirty: - sys.stderr.write(RED) - sys.stderr.write("error: failed to commit all changes; " - "build directory still dirty\n") - sys.stderr.write("error: please manually inspect what was left out\n") - sys.stderr.write(RESET) - return 1 - - # push to origin/master - sys.stderr.write("%scommand: git push origin master%s\n" % (BLUE, RESET)) - try: - subprocess.check_call(["git", "push", "origin", "master"]) - except subprocess.CalledProcessError: - sys.stderr.write("\n%serror: git push failed%s\n" % (RED, RESET)) - return 1 - return 0 - - -def gen_deploy(args): - """Regenerate and deploy.""" - # pylint: disable=unused-argument,too-many-branches - - # try to smartly determine the latest post, and prompt to touch it - current_time = time.time() - latest_post = None - latest_postdate = 0 - latest_mtime = 0 - for name in os.listdir(POSTSDIR): - matchobj = re.match(r"^([0-9]{4})-([0-9]{2})-([0-9]{2})-.*\.md", name) - if not matchobj: - continue - fullpath = os.path.join(POSTSDIR, name) - mtime = os.path.getmtime(fullpath) - # get post date from the date metadata field of the post - postdate = 0 - with open(fullpath) as postobj: - for line in postobj: - dateregex = r"^date: (\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}-\d{2}:?\d{2})" - datematch = re.match(dateregex, line.rstrip()) - if datematch: - postdate = dateutil.parser.parse(datematch.group(1)).timestamp() - break - # skip the post if it is dated more than three days ago - if current_time - postdate > 3 * 24 * 3600: - continue - if mtime > latest_mtime: - latest_post = name - latest_postdate = postdate - latest_mtime = mtime - # prompt for touching if the latest post determined above was - # modified within the last hour but the date registered in the post - # isn't within the last ten minutes - if ((latest_post is not None and current_time - latest_mtime < 3600 and - current_time - latest_postdate > 600)): - sys.stderr.write("%sIt appears that %s might be a new post.\n" - "Do you want to touch its timestamp?%s\n" % - (GREEN, latest_post, RESET)) - while True: - yesnoquit = input("[ynq]: ") - if yesnoquit.startswith(("Y", "y")): - yesno = True - break - elif yesnoquit.startswith(("N", "n")): - yesno = False - break - elif yesnoquit.startswith(("Q", "q")): - sys.stderr.write("%saborting gen_deploy%s\n" % (RED, RESET)) - return 1 - else: - sys.stderr.write("Please answer yes, no, or quit.\n") - if yesno: - sys.stderr.write("%stouching %s%s\n" % (BLUE, latest_post, RESET)) - touch(latest_post) - sys.stderr.write("\n") - - generators.generate_blog(fresh=True) - deploy(None) - - -def preview(args): - """Serve the blog and auto regenerate upon changes.""" - - # pylint: disable=unused-argument - - server_process = utils.HTTPServerProcess(BUILDDIR) - server_process.start() - sys.stderr.write("watching for changes\n") - sys.stderr.write("send SIGINT to stop\n") - - # install a SIGINT handler only for this process - sigint_raised = False - - def sigint_mitigator(signum, frame): - """Translate SIGINT to setting the sigint_raised flag.""" - nonlocal sigint_raised - sigint_raised = True - - signal.signal(signal.SIGINT, sigint_mitigator) - - # Watch and auto-regen. - # No need to actually implement watch separately, since - # generate_blog(fresh=False, report_total_errors=False) already - # watches for modifications and only regens upon changes, and it is - # completely silent when there's no change. - while not sigint_raised: - generators.generate_blog(fresh=False, report_total_errors=False) - time.sleep(0.5) - - sys.stderr.write("\nSIGINT received, cleaning up...\n") - server_process.join() - return 0 diff --git a/cli/management.py b/cli/management.py new file mode 100644 index 00000000..9d35c643 --- /dev/null +++ b/cli/management.py @@ -0,0 +1,221 @@ +#/bin/python3 + +import subprocess +import sys +import re +import time +import signal + +from config.config import * +from utils import utils +from generators import generators + + +def generate(args): + """Wrapper for generate_blog(fresh=False).""" + # pylint: disable=unused-argument + exit(generators.generate_blog(fresh=False)) + + +def regenerate(args): + """Wrapper for generate_blog(fresh=True).""" + # pylint: disable=unused-argument + exit(generators.generate_blog(fresh=True)) + + +def deploy(args): + """Deploys build directory to origin/master without regenerating. + + Returns + ------- + 0 + On success. Exit early with nonzero status otherwise. + + """ + + # pylint: disable=unused-argument,too-many-statements + + # check whether root is dirty + os.chdir(ROOTDIR) + dirty = subprocess.check_output(["git", "status", "--porcelain"]) + if dirty: + sys.stderr.write(YELLOW) + sys.stderr.write("Project root is dirty.\n") + sys.stderr.write("You may want to commit in your changes " + "to the source branch, since the SHA and title " + "of the latest commit on the source branch will be " + "incorporated into the commit message on " + "the deployment branch. Type s[hell] on the " + "next prompt to open an interactive shell.\n") + sys.stderr.write(RESET) + while True: + sys.stderr.write("Continue? [yNs] ") + answer = input() + if not answer: + # default + abort = True + break + elif answer.startswith(('y', 'Y')): + abort = False + break + elif answer.startswith(('n', 'N')): + abort = True + break + elif answer.startswith(('s', 'S')): + shell = (os.environ['SHELL'] if 'SHELL' in os.environ and os.environ['SHELL'] + else 'zsh') + subprocess.call(shell) + stilldirty = subprocess.check_output(["git", "status", "--porcelain"]) + if stilldirty: + sys.stderr.write(YELLOW) + sys.stderr.write("Project root is still dirty.\n") + sys.stderr.write(RESET) + else: + sys.stderr.write("Please answer yes or no.\n") + if abort: + sys.stderr.write("%saborting deployment%s\n" % (RED, RESET)) + return 1 + + # extract latest commit on the source branch + source_commit = subprocess.check_output( + ["git", "log", "-1", "--pretty=oneline", "source", "--"]).decode('utf-8').strip() + + # cd into BUILDDIR and assemble commit message + sys.stderr.write("%scommand: cd '%s'%s\n" % (BLUE, BUILDDIR, RESET)) + os.chdir(BUILDDIR) + + # extract updated time from atom.xml + if not os.path.exists("atom.xml"): + sys.stderr.write("atom.xml not found, cannot deploy\naborting\n") + return 1 + atomxml = ET.parse("atom.xml").getroot() + updated = atomxml.find('{http://www.w3.org/2005/Atom}updated').text + + commit_message = ("Site updated at %s\n\nsource branch was at:\n%s\n" % + (updated, source_commit)) + + # commit changes in BUILDDIR + sys.stderr.write("%scommand: git add --all%s\n" % (BLUE, RESET)) + subprocess.check_call(["git", "add", "--all"]) + sys.stderr.write("%scommand: git commit --no-verify --gpg-sign --message='%s'%s\n" % + (BLUE, commit_message, RESET)) + try: + subprocess.check_call(["git", "commit", "--gpg-sign", + "--message=%s" % commit_message]) + except subprocess.CalledProcessError: + sys.stderr.write("\n%serror: git commit failed%s\n" % (RED, RESET)) + return 1 + + # check dirty status + dirty = subprocess.check_output(["git", "status", "--porcelain"]) + if dirty: + sys.stderr.write(RED) + sys.stderr.write("error: failed to commit all changes; " + "build directory still dirty\n") + sys.stderr.write("error: please manually inspect what was left out\n") + sys.stderr.write(RESET) + return 1 + + # push to origin/master + sys.stderr.write("%scommand: git push origin master%s\n" % (BLUE, RESET)) + try: + subprocess.check_call(["git", "push", "origin", "master"]) + except subprocess.CalledProcessError: + sys.stderr.write("\n%serror: git push failed%s\n" % (RED, RESET)) + return 1 + return 0 + + +def gen_deploy(args): + """Regenerate and deploy.""" + # pylint: disable=unused-argument,too-many-branches + + # try to smartly determine the latest post, and prompt to touch it + current_time = time.time() + latest_post = None + latest_postdate = 0 + latest_mtime = 0 + for name in os.listdir(POSTSDIR): + matchobj = re.match(r"^([0-9]{4})-([0-9]{2})-([0-9]{2})-.*\.md", name) + if not matchobj: + continue + fullpath = os.path.join(POSTSDIR, name) + mtime = os.path.getmtime(fullpath) + # get post date from the date metadata field of the post + postdate = 0 + with open(fullpath) as postobj: + for line in postobj: + dateregex = r"^date: (\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}-\d{2}:?\d{2})" + datematch = re.match(dateregex, line.rstrip()) + if datematch: + postdate = dateutil.parser.parse(datematch.group(1)).timestamp() + break + # skip the post if it is dated more than three days ago + if current_time - postdate > 3 * 24 * 3600: + continue + if mtime > latest_mtime: + latest_post = name + latest_postdate = postdate + latest_mtime = mtime + # prompt for touching if the latest post determined above was + # modified within the last hour but the date registered in the post + # isn't within the last ten minutes + if ((latest_post is not None and current_time - latest_mtime < 3600 and + current_time - latest_postdate > 600)): + sys.stderr.write("%sIt appears that %s might be a new post.\n" + "Do you want to touch its timestamp?%s\n" % + (GREEN, latest_post, RESET)) + while True: + yesnoquit = input("[ynq]: ") + if yesnoquit.startswith(("Y", "y")): + yesno = True + break + elif yesnoquit.startswith(("N", "n")): + yesno = False + break + elif yesnoquit.startswith(("Q", "q")): + sys.stderr.write("%saborting gen_deploy%s\n" % (RED, RESET)) + return 1 + else: + sys.stderr.write("Please answer yes, no, or quit.\n") + if yesno: + sys.stderr.write("%stouching %s%s\n" % (BLUE, latest_post, RESET)) + touch(latest_post) + sys.stderr.write("\n") + + generators.generate_blog(fresh=True) + deploy(None) + + +def preview(args): + """Serve the blog and auto regenerate upon changes.""" + + # pylint: disable=unused-argument + + server_process = utils.HTTPServerProcess(BUILDDIR) + server_process.start() + sys.stderr.write("watching for changes\n") + sys.stderr.write("send SIGINT to stop\n") + + # install a SIGINT handler only for this process + sigint_raised = False + + def sigint_mitigator(signum, frame): + """Translate SIGINT to setting the sigint_raised flag.""" + nonlocal sigint_raised + sigint_raised = True + + signal.signal(signal.SIGINT, sigint_mitigator) + + # Watch and auto-regen. + # No need to actually implement watch separately, since + # generate_blog(fresh=False, report_total_errors=False) already + # watches for modifications and only regens upon changes, and it is + # completely silent when there's no change. + while not sigint_raised: + generators.generate_blog(fresh=False, report_total_errors=False) + time.sleep(0.5) + + sys.stderr.write("\nSIGINT received, cleaning up...\n") + server_process.join() + return 0 diff --git a/pyblog b/pyblog index b8cd4e71..7ad662c8 100755 --- a/pyblog +++ b/pyblog @@ -12,7 +12,7 @@ import dateutil.parser from utils import utils -from cli import cli +from cli import management as manage from cli import post @@ -47,27 +47,27 @@ def main(): parser_generate = subparsers.add_parser( "generate", aliases=["g", "gen"], description="Generate new or changed objects.") - parser_generate.set_defaults(func=cli.generate) + parser_generate.set_defaults(func=manage.generate) parser_regenerate = subparsers.add_parser( "regenerate", aliases=["r", "regen"], description="Regenerate the entire blog afresh.") - parser_regenerate.set_defaults(func=cli.regenerate) + parser_regenerate.set_defaults(func=manage.regenerate) parser_new_post = subparsers.add_parser( "preview", aliases=["p", "pre"], description="Serve the blog locally and auto regenerate upon changes.") - parser_new_post.set_defaults(func=cli.preview) + parser_new_post.set_defaults(func=manage.preview) parser_new_post = subparsers.add_parser( "deploy", aliases=["d", "dep"], description="Deploy build/ to origin/master without regenerating.") - parser_new_post.set_defaults(func=cli.deploy) + parser_new_post.set_defaults(func=manage.deploy) parser_new_post = subparsers.add_parser( "gen_deploy", aliases=["gd", "gendep"], description="Rebuild entire blog and deploy build/ to origin/master.") - parser_new_post.set_defaults(func=cli.gen_deploy) + parser_new_post.set_defaults(func=manage.gen_deploy) parser_new_post = subparsers.add_parser( "edit", aliases=["e", "ed"], -- cgit v1.2.1