#!/usr/bin/env python3 import argparse import datetime from hashlib import sha1 from pathlib import Path import subprocess import shutil from textwrap import fill import tempfile from git import Repo import pytz import sarge from slugify import slugify import yaml def is_jekyll_root(path: Path): return (Path / "_config.yml").exists() def hash_file(filename: Path) -> str: # Git-like SHA1 hashing filesize = filename.stat().st_size with filename.open() as handle: data = handle.read() contents = "blob " + str(filesize) + "\0" + data file_hash = sha1(contents.encode()) return file_hash.hexdigest() def perform_commit(filepath: Path, title: str=None) -> None: repo = Repo("./") # FIXME repo.index.add(str(filepath)) message = "New post: {}".format(title) message = fill(message, width=78) repo.commit(message) repo.remotes.origin.push() def create_new_post(title: str, categories: list=None, tags: list=None, post_metadata: dict=None, comments: bool=True) -> Path: title_slug = slugify(title) current_time = datetime.datetime.now(pytz.timezone("Europe/Rome")) date_slug = current_time.date().isoformat() filename = "{0}-{1}.markdown".format(date_slug, title_slug) formatted_date = current_time.strftime("%Y-%m-%d %H:%M:%S%z") metadata = dict(title=title, comments=comments, date=formatted_date) if categories is not None: metadata["categories"] = categories else: metadata["categories"] = ["General"] if tags is not None: metadata["tags"] = tags if post_metadata is not None: for key, value in post_metadata.items(): metadata[key] = value final_path = Path("_posts") / filename with tempfile.NamedTemporaryFile() as temp: temp_path = Path(temp.name) temp.write("---\n") yaml.safe_dump(metadata, temp, default_flow_style=False) temp.write("---\n") temp.flush() pre_edit_hash = hash_file(temp_path) subprocess.check_call("/usr/bin/kate {}".format(temp.name), shell=True) post_edit_hash = hash_file(final_path) if pre_edit_hash == post_edit_hash: print("No post content. Aborting.") return shutil.copy(temp.name, str(final_path)) return (final_path) def main(): parser = argparse.ArgumentParser() parser.add_argument("-t", "--tags", nargs="+", help="Post tags (space separated)") parser.add_argument("-c", "--categories", nargs="+", help="Post categories (space separated)") parser.add_argument("--disable_comments", action="store_false", help="Disable comments for the post") parser.add_argument("--commit", action="store_true", help="Commit and push to the remote repository") parser.add_argument("title", help="Title of the new post") options = parser.parse_args() if not is_jekyll_root(Path("./")): raise FileNotFoundError("Jekyll root not found.") path = create_new_post(options.title, options.categories, options.tags, comments=options.disable_comments) if path is None: exit(1) print("Created new post {}".format(path.name)) if options.commit: print("Committing to upstream repository...") perform_commit(path, options.title) print("Done.") if __name__ == "__main__": main()