165 lines
4.9 KiB
Python
165 lines
4.9 KiB
Python
print("running extra script...")
|
|
|
|
import os
|
|
import sys
|
|
import inspect
|
|
import gzip
|
|
import shutil
|
|
|
|
Import("env")
|
|
|
|
GEN_DIR = 'lib/generated'
|
|
OWN_FILE = "extra_script.py"
|
|
|
|
INDEXJS = "index.js"
|
|
INDEXCSS = "index.css"
|
|
|
|
# embedded files definition is generated inside here
|
|
EMBEDDED_INCLUDE="embeddedfiles.h"
|
|
|
|
def basePath():
|
|
#see: https://stackoverflow.com/questions/16771894/python-nameerror-global-name-file-is-not-defined
|
|
return os.path.dirname(inspect.getfile(lambda: None))
|
|
|
|
def is_current(infile, outfile):
|
|
if os.path.exists(outfile):
|
|
otime = os.path.getmtime(outfile)
|
|
itime = os.path.getmtime(infile)
|
|
if (otime >= itime):
|
|
own = os.path.join(basePath(), OWN_FILE)
|
|
if os.path.exists(own):
|
|
owntime = os.path.getmtime(own)
|
|
if owntime > otime:
|
|
return False
|
|
print(f"{outfile} is newer than {infile}, no need to recreate")
|
|
return True
|
|
return False
|
|
|
|
def compress_file(infile, outfile):
|
|
if is_current(infile, outfile):
|
|
return
|
|
print(f"compressing {infile}")
|
|
with open(infile, 'rb') as f_in:
|
|
with gzip.open(outfile, 'wb') as f_out:
|
|
shutil.copyfileobj(f_in, f_out)
|
|
|
|
def write_file_if_changed(filename, data):
|
|
"""
|
|
Create or update file if it not contains data as content
|
|
"""
|
|
if os.path.exists(filename):
|
|
changetype = 'updating'
|
|
with open(filename, 'r') as fh:
|
|
if fh.read() == data:
|
|
print(f"{filename} is up to date")
|
|
return False
|
|
else:
|
|
changetype = 'generating'
|
|
print(f"#{changetype} {filename}")
|
|
with open(filename, 'w') as fh:
|
|
fh.write(data)
|
|
return True
|
|
|
|
def get_embedded_files(env):
|
|
filelist = []
|
|
efiles = env.GetProjectOption("board_build.embed_files")
|
|
for f in efiles.split("\n"):
|
|
if f == '':
|
|
continue
|
|
filelist.append(f)
|
|
return filelist
|
|
|
|
def get_content_type(fn):
|
|
if (fn.endswith('.gz')):
|
|
fn = fn[0:-3]
|
|
if (fn.endswith('html')):
|
|
return "text/html"
|
|
if (fn.endswith('json')):
|
|
return "application/json"
|
|
if (fn.endswith('js')):
|
|
return "text/javascript"
|
|
if (fn.endswith('css')):
|
|
return "text/css"
|
|
if (fn.endswith('png')):
|
|
return "image/png"
|
|
if (fn.endswith('jpg') or fn.endswith('jpeg')):
|
|
return "image/jpeg"
|
|
return "application/octet-stream"
|
|
|
|
def join_files(target, filename, dirlist):
|
|
"""
|
|
Join files named filename within different directories
|
|
into one single gzip archive (located in generated dir)
|
|
"""
|
|
print("joinfiles: {} into {} from dirs [{}]".format(filename, target, ','.join(dirlist)))
|
|
flist = []
|
|
for dir in dirlist:
|
|
fn = os.path.join(dir, filename)
|
|
if os.path.exists(fn):
|
|
flist.append(fn)
|
|
current = False
|
|
if os.path.exists(target):
|
|
current = True
|
|
for f in flist:
|
|
if not is_current(f, target):
|
|
current = False
|
|
break
|
|
if current:
|
|
print(f"{target} is up to date")
|
|
return
|
|
print(f"creating {target}")
|
|
|
|
# add multiple files
|
|
with gzip.open(target, "wb") as oh:
|
|
for fn in flist:
|
|
print("adding {} to {}".format(fn, target))
|
|
with open(fn, "rb") as rh:
|
|
shutil.copyfileobj(rh, oh)
|
|
|
|
def prebuild(env):
|
|
print("#prebuild running")
|
|
|
|
# directory for dynamically generated files
|
|
gendir = os.path.join(basePath(), GEN_DIR)
|
|
if not os.path.exists(gendir):
|
|
os.makedirs(gendir)
|
|
if not os.path.isdir(gendir):
|
|
print("unable to create directory {}".format(gendir))
|
|
sys.exit(1)
|
|
|
|
# join static web server files
|
|
|
|
# only useful for different task dirs with custom configs
|
|
# join_files(os.path.join(gendir, INDEXJS+".gz"), INDEXJS, ["web"])
|
|
# join_files(os.path.join(gendir, INDEXCSS+".gz"), INDEXCSS, ["web"])
|
|
|
|
# platformio defined embedded files as list
|
|
pio_embedded = get_embedded_files(env)
|
|
|
|
filedefs = []
|
|
for ef in pio_embedded:
|
|
print(f"#checking embedded file {ef}")
|
|
# files are defined with relative path to platformio.ini
|
|
# the name can be with extension gz or without
|
|
(dn, fn) = os.path.split(ef)
|
|
pureName = fn
|
|
if pureName.endswith('.gz'):
|
|
pureName = pureName[0:-3]
|
|
usname = ef.replace('/','_').replace('.','_') # sanitize filenames
|
|
filedefs.append((pureName, usname, get_content_type(pureName)))
|
|
infile = os.path.join(basePath(), "web", pureName)
|
|
if os.path.exists(infile):
|
|
compress_file(infile, ef)
|
|
else:
|
|
print("#WARNING: infile {infile} for {ef} not found")
|
|
|
|
# generate c-header file for embedding zip files
|
|
content = ""
|
|
for entry in filedefs:
|
|
content += 'EMBED_GZ_FILE("{}", {}, "{}");\n'.format(*entry)
|
|
write_file_if_changed(os.path.join(gendir, EMBEDDED_INCLUDE), content)
|
|
|
|
print("#prescript...")
|
|
prebuild(env)
|
|
|