From 73ffcccec884bbb62699b1df9ed9a4eecbc21c03 Mon Sep 17 00:00:00 2001
From: neodarz <neodarz@neodarz.net>
Date: Sun, 26 May 2019 16:19:08 +0200
Subject: Move generate_blog to external file

---
 generators/generators.py | 140 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

(limited to 'generators')

diff --git a/generators/generators.py b/generators/generators.py
index adfe819a..3122f9c8 100644
--- a/generators/generators.py
+++ b/generators/generators.py
@@ -18,6 +18,8 @@ import copy
 import email.utils
 import time
 
+import shutil
+
 from rss import *
 
 from config.config import *
@@ -689,3 +691,141 @@ def generate_index_and_feed():
         sys.stderr.write("wrote rss.xml\n")
 
     generate_sitemap(feed)
+
+
+# exclude_list is only inialized once to avoid constant disk IO
+@utils.static_vars(exclude_list=None)
+def generate_blog(fresh=False, report_total_errors=True):
+    """Generate the blog in BUILDDIR.
+
+    Parameters
+    ----------
+    fresh : bool
+        If True, remove all existing build artifects and start afresh;
+        otherwise, only copy or build new or modified files. Default is
+        False.
+    report_total_errors : bool
+        If True, a line will be printed to stderr at the end of build
+        (assuming the function doesn't raise early) reporting the total
+        number of errors, e.g., "build finished with 0 errors". This is
+        turned on by default, but pass False to turn it off, which will
+        result in a completely silent session if nothing changed. This
+        is useful for auto-regen, for instance.
+
+    Returns
+    -------
+    failed_builds : int
+        Number of build failures.
+
+    """
+
+    # pylint: disable=too-many-branches,too-many-locals,too-many-statements
+
+    if not os.path.isdir(SOURCEDIR):
+        raise OSError("source directory %s does not exist" % SOURCEDIR)
+    if not os.path.exists(HTMLTEMPLATE):
+        raise OSError("HTML template %s not found" % HTMLTEMPLATE)
+
+    if not os.path.isdir(BUILDDIR):
+        if os.path.exists(BUILDDIR):
+            os.remove(BUILDDIR)
+        os.mkdir(BUILDDIR, mode=0o755)
+    if fresh:
+        for name in os.listdir(BUILDDIR):
+            if name == ".git":
+                continue
+            obj = os.path.join(BUILDDIR, name)
+            if os.path.isdir(obj):
+                shutil.rmtree(obj)
+            else:
+                os.remove(obj)
+
+    # nojekyll: https://help.github.com/articles/files-that-start-with-an-underscore-are-missing/
+    if not os.path.exists(os.path.join(BUILDDIR, ".nojekyll")):
+        with open(os.path.join(BUILDDIR, ".nojekyll"), "w") as fileobj:
+            pass
+
+    if CUSTOM_DOMAIN and not os.path.exists(os.path.join(BUILDDIR, "CNAME")):
+        with open(os.path.join(BUILDDIR, "CNAME"), "w") as fileobj:
+            fileobj.write(CUSTOM_DOMAIN)
+
+    failed_builds = 0
+    generator_mtime = os.path.getmtime(GENERATORSOURCE)
+    template_mtime = os.path.getmtime(HTMLTEMPLATE)
+    fundamental_mtime = max(generator_mtime, template_mtime)
+    anything_modified = False
+
+    exclude_list = generate_blog.exclude_list  # get value of static variable
+    if exclude_list is None:
+        try:
+            with open(EXCLUDELIST) as fp:
+                exclude_list = [os.path.abspath(os.path.join(SOURCEDIR, line.rstrip()))
+                                for line in list(fp)
+                                if line.strip() != "" and not line.startswith('#')]
+        except OSError:
+            exclude_list = []
+        generate_blog.exclude_list = exclude_list  # assign to static variable for the future
+
+    for root, dirs, files in os.walk(SOURCEDIR):
+        # If root is in exclude list, skip all files and remove all subdirs from traversal list.
+        if root in exclude_list:
+            dirs[:] = []
+            continue
+
+        relroot = os.path.relpath(root, start=SOURCEDIR)
+        dstroot = os.path.join(BUILDDIR, relroot)
+        if not os.path.isdir(dstroot):
+            if os.path.exists(dstroot):
+                os.remove(dstroot)
+            os.mkdir(dstroot, mode=0o755)
+
+        for name in files:
+            if name.startswith('.') or os.path.join(root, name) in exclude_list:
+                continue
+
+            extension = name.split(".")[-1]
+            if extension not in ["css", "js", "asc", "html", "jpg", "md", "png", "svg", "ico", "txt",
+                                 "eot", "ttf", "woff", "woff2"]:
+                continue
+
+            relpath = os.path.join(relroot, name)
+            srcpath = os.path.join(root, name)
+            if extension == "md":
+                dstpath = os.path.join(dstroot, re.sub(r'\.md$', '.html', name))
+            else:
+                dstpath = os.path.join(dstroot, name)
+            if ((not os.path.exists(dstpath) or
+                 os.path.getmtime(dstpath) <=
+                 max(fundamental_mtime, os.path.getmtime(srcpath)))):
+                # new post or modified post
+                anything_modified = True
+                if srcpath == INDEXMD:
+                    continue # index will be processed separately
+                if extension in ["css", "js",  "asc", "html", "jpg", "png", "svg", "ico", "txt",
+                                 "eot", "ttf", "woff", "woff2"]:
+                    sys.stderr.write("copying %s\n" % relpath)
+                    shutil.copy(srcpath, dstpath)
+                elif extension == "md":
+                    sys.stderr.write("compiling %s\n" % relpath)
+                    pandoc_args = [
+                        "pandoc", srcpath,
+                        "--template", HTMLTEMPLATE,
+                        "--highlight-style=pygments",
+                        "-o", dstpath,
+                    ]
+                    try:
+                        subprocess.check_call(pandoc_args)
+                    except subprocess.CalledProcessError:
+                        failed_builds += 1
+                        sys.stderr.write("error: failed to generate %s" %
+                                         relpath)
+                    # postprocess generated HTML file
+                    utils.postprocess_html_file(dstpath)
+
+    if anything_modified:
+        generate_index_and_feed()
+        sys.stderr.write("done\n")
+
+    if report_total_errors:
+        sys.stderr.write("build finished with %d errors\n" % failed_builds)
+    return failed_builds
-- 
cgit v1.2.1