def script_get_book(): if el.file_exists_p("Cookbook.py"): return os.path.realpath("Cookbook.py") elif el.file_exists_p("cook/Cookbook.py"): return os.path.realpath("cook/Cookbook.py") else: raise RuntimeError("No Cookbook.py or cook/Cookbook.py found")
def compile_and_run(recipe, source_file): class_file = re.sub("java$", "class", source_file) assert el.file_exists_p(source_file) source = el.file_name_nondirectory(source_file) path = el.file_name_directory(source_file) name = el.file_name_sans_extension(source) res = [] if (not el.file_exists_p(class_file) or el.file_newer_than_file_p(source_file, class_file)): res += [lf("javac {source_file}")] res += [lf("java -cp {path} {name}")] return res
def git_clone(url, target_dir, commit=None): target_dir = el.expand_file_name(target_dir) if el.file_exists_p(target_dir): print(lf("{target_dir}: OK")) else: gdir = el.expand_file_name(target_dir) pdir = el.file_name_directory(gdir) if not el.file_exists_p(pdir): el.make_directory(pdir) (_, gdir) = el.parse_fname(gdir) sc("git clone --recursive {url} {gdir}") if commit: sc("cd {gdir} && git reset --hard {commit}")
def clone(remote, local): res = [] local = el.expand_file_name(local) if el.file_exists_p(local): if el.file_exists_p(el.expand_file_name(".git", local)): res += ["cd " + local, "git pull"] else: raise RuntimeError("Directory exists and is not a git repo", local) else: (bd, repo) = os.path.split(local) el.make_directory(bd) res += [lf("cd {bd}"), lf("git clone {remote} {repo}")] return res
def cp(fr, to): if el.file_exists_p(to) and file_equal(fr, to): print(lf("{to}: OK")) return False else: el.sc(sudo("cp '{fr}' '{to}'", to)) return True
def install_package(package, url=None): if isinstance(package, list): res = False for p in package: res |= install_package(p, url) return res user = sc("whoami") su = "" if user == "root" else "sudo " if el.file_exists_p("/usr/bin/dpkg"): if package_installed_p_dpkg(package): print(lf("{package}: OK")) return False else: if url is None: bash( lf("{su}apt-get update && DEBIAN_FRONTEND=noninteractive {su}apt-get install -y {package}" )) else: fname = wget(url) bash(lf("{su}dpkg -i {fname}")) return True else: if package_installed_p_yum(package): print(lf("{package}: OK")) return False else: if url is None: bash( lf("{su}yum update -y && {su}yum upgrade -y && {su}yum install -y '{package}'" )) else: fname = wget(url) bash(lf("{su}yum localinstall -y {fname}")) return True
def patch(fname, patches): """Patch FNAME applying PATCHES. Each PATCH in PATCHES is in diff -u format. Each line in PATCH starts with [+- ]. [ ] lines are the optional start and end context. [-] lines are expected to exist in the file and will be removed. [+] lines will be added to the file after [-] lines are removed. PATCH lines should be in contiguous order: optional start context, [-] lines, [+] lines, optional end context. If PATCH was already applied for FNAME, it will be ignored. PATCHES can also be a file name of a "diff -u" output. """ (host, name) = parse_fname(fname) patches = parse_patches(patches) if el.file_exists_p(fname): txt = el.slurp(fname) else: assert not any([ re.search("^\\-", patch, flags=re.MULTILINE) for patch in patches ]) el.sc("touch {name}") txt = "" no_change = True for ptch in patches: patch_lines = el.delete("", ptch.splitlines()) chunk_before = render_patch(patch_lines, True) chunk_after = render_patch(patch_lines, False) if chunk_before == "": if not re.search("^" + re.escape(chunk_after), txt, re.MULTILINE): no_change = False if not (txt == "" or txt[-1] == "\n"): txt += "\n" txt += chunk_after + "\n" elif (re.search("^" + re.escape(chunk_before), txt, re.MULTILINE) and not re.search("^" + re.escape(chunk_after), txt, re.MULTILINE)): no_change = False txt = re.sub("^" + re.escape(chunk_before), chunk_after, txt, flags=re.MULTILINE) else: # either already patched or fail assert chunk_after in txt if no_change: print(fname + ": OK") return False else: print(fname + ": Patch") with el.hostname(None): el.barf("/tmp/insta.txt", txt) if host is not None: cmd = lf("scp /tmp/insta.txt {host}:{name}") else: cmd = sudo(lf("cp /tmp/insta.txt {name}"), name) with el.hostname(None): bash(cmd, desc=(host, "edit " + name)) return True
def cp(fr, to): fr = el.expand_file_name(fr) to = el.expand_file_name(to) if el.file_exists_p(to) and file_equal(fr, to): print(lf("{to}: OK")) return False else: el.sc(sudo("cp '{fr}' '{to}'", to)) return True
def compile_and_run(src_file): exe_file = el.file_name_sans_extension(src_file) if (el.file_exists_p(exe_file) and el.file_newer_than_file_p(exe_file, src_file)): return [lf("./{exe_file}")] else: return [ lf("rustc {src_file}"), lf("./{exe_file}")]
def get_change_time(fname): fname = el.expand_file_name(fname) if el.file_directory_p(fname): git_dir = el.expand_file_name(".git", fname) if el.file_exists_p(git_dir): return float(git.mtime(fname).strftime("%s")) else: raise RuntimeError("Directory is not a git repo") else: return os.path.getctime(fname)
def echo(fr_text, to): if el.file_exists_p(to) and fr_text == el.slurp(to): print(lf("{to}: OK")) return False else: host = el.HOST with el.hostname(None): el.sc("echo '{fr_text}' | ssh '{host}' -T 'cat > {to}'", desc=(host, "write " + to)) return True
def book_config(book): rc_file = el.expand_file_name("~/.cook.d/__config__.py") if el.file_exists_p(rc_file): mod = imp.load_source("book_config", rc_file) config = mod.config if book in config: return config[book] elif "*" in config: return config["*"] return {}
def ln(fr, to): fr_full = el.expand_file_name(fr) if not el.file_exists_p(fr_full): raise RuntimeError("File doesn't exist", fr_full) to_full = el.expand_file_name(to) if el.file_exists_p(to_full): if symlink_p(to_full): print(lf("{to_full}: OK")) else: if file_equal(fr_full, to_full): print(lf("{to_full} exists, contents equal")) else: print(lf("{to_full} exists, contents NOT equal")) else: if el.HOST: cmd = lf("ln -s {fr} {to}") else: fr_abbr = os.path.relpath(fr_full, os.path.dirname(to)) cmd = sudo(lf("ln -s {fr_abbr} {to_full}"), to_full) bash(cmd)
def wget(url, download_dir="/tmp/"): if download_dir[:-1] == "/": fname = url.split("/")[-1] full_name = el.expand_file_name(fname, download_dir) else: full_name = download_dir if el.file_exists_p(full_name): print(lf("{full_name}: OK")) else: bash(lf("wget '{url}' -O {full_name}")) return full_name
def read_layouts(): r = {} config_file = "~/.config/xkb-indicator/xkb-indicator.ini" if el.file_exists_p(config_file): txt = el.slurp(config_file) m = re.search("layouts=(.*)", txt) if m: layouts = m.group(1).split(",") assert len( layouts ) == 2, "Only two layouts are supported currently. See " + config_file return layouts return ["xx", "ua"]
def compile_and_run_cc(inputs, std="c++11", flags="", idirs=(), libs=(), cc="g++"): """Compile INPUTS together into an executable and run it. INPUTS is a list of source files, headers and libraries. The executable is named after the first source file. Any file that doesn't exist is assumed to be a library. """ if isinstance(inputs, list): main_file = inputs[0] else: main_file = inputs assert el.file_exists_p(main_file) sources = el.re_filter("(cc|cpp|h|hh|hpp)$", inputs) diff = set(inputs) - set(sources) libs_inl = [x for x in inputs if x in diff] libs_str = " " + " ".join(["-l" + lib for lib in libs_inl]) lib_dirs = set(map(el.file_name_directory, libs)) lflags = list(map(lib_name, libs)) libs_str += " " + " ".join(["-L" + d for d in lib_dirs] + lflags) exe_file = re.sub("cc$", "e", main_file) res = [] flags += " " + " ".join(["-I" + d for d in idirs]) if (not el.file_exists_p(exe_file) or any([ el.file_newer_than_file_p(f, exe_file) for f in sources + [cook.script_get_book()[0]] ])): ccmd = lf("g++ -g -O2 -std={std} {flags} -o {exe_file} ") + " ".join( sources) + libs_str res += [ccmd] if lib_dirs: res += ["export LD_LIBRARY_PATH=" + ":".join(lib_dirs)] res += [lf("./{exe_file}")] return res
def modules(full=False, match=False): cook_dir = el.file_name_directory(recipes.__file__) cook_modules = el.directory_files(cook_dir, full, match) user_dir = el.expand_file_name("~/.cook.d") if el.file_exists_p(user_dir): df = el.directory_files(user_dir, full, match) user_modules = [ f for f in df if os.path.isfile(el.expand_file_name(f, user_dir)) and os.path.splitext(f)[1] == ".py" ] else: user_modules = [] cook_modules += user_modules return list(filter(lambda s: not re.search("__", s), cook_modules))
def make(target, cmds, deps=()): if (el.file_exists_p(target) and \ all([get_change_time(target) > get_change_time(dep) for dep in deps])): print(lf("{target}: OK")) return False else: if isinstance(cmds, str): cmds = [cmds] elif callable(cmds): cmds(target) return True fcmds = [] for cmd in cmds: cmd1 = re.sub("\\$@", target, cmd) cmd2 = re.sub("\\$\\^", " ".join([shlex.quote(dep) for dep in deps]), cmd1) cmd3 = re.sub("\\$<", shlex.quote(deps[0]), cmd2) if deps else cmd2 if el.sc_hookfn: el.sc_hookfn(cmd3) fcmds.append(cmd3) bash(fcmds) return True
def install_root_cert(certfile, certname=None): """Install root certificate to certificate trust store of applications using NSS""" install_package("libnss3-tools") name_crt = el.file_name_nondirectory(certfile) if certname is None else certname # Firefox and Chromium if not el.file_exists_p("/tmp/cert9.db.done"): dbs = el.sc_l("find ~/ -name cert9.db 2>/dev/null || true") for db in dbs: certdir = el.file_name_directory(db) el.scb("certutil -A -n '{name_crt}' -t 'TCu,Cu,Tu' -i {certfile} -d sql:{certdir}") el.barf("/tmp/cert9.db.done", "") # curl cp_cmd = cp_host if el.HOST else cp fname_crt = lf("/usr/local/share/ca-certificates/{name_crt}") cp_cmd(certfile, fname_crt) chmod(fname_crt, "644") name_pem = el.file_name_sans_extension(name_crt) + ".pem" fname_pem = lf("/etc/ssl/certs/{name_pem}") make(fname_pem, sudo("update-ca-certificates")) # wget install_package("ca-certificates") patch("/etc/wgetrc", ["+ca_directory=/etc/ssl/certs"])
def get_image(i): if i == "." and el.file_exists_p("params.json"): js = json.load(open("params.json", "r")) return js["docker_url"] + ":" + js["docker_version"] else: return i
#* Imports import sys import shutil import pycook.elisp as el sc = el.sc lf = el.lf #* Constants sudo_cmd = "sudo -H " if el.file_exists_p("/usr/bin/sudo") else "su -c" #* Functions def sudo(cmd): return sudo_cmd + cmd def get_pip(): is_sudo = shutil.which("cook").find("/usr/local/bin") != -1 if sys.version_info.major == 3: pip = "pip3" else: pip = "pip" if is_sudo: return sudo(pip) else: return pip def package_installed_p(package): try: s = sc(get_pip() + " show " + package)
def barf(fname, text): if el.file_exists_p(fname) and text == el.slurp(fname): print(lf("{fname}: OK")) else: quoted_text = shlex.quote(text) bash(lf("echo {quoted_text} | sudo tee {fname} > /dev/null"))
def test_interactive(recipe): elfs = ["orca.el", "targets/server-restart.el"] plain = "../swiper/targets/plain.el" if el.file_exists_p("../swiper/targets/plain.el"): elfs.append(plain) return [" ".join(["emacs -Q"] + ["-l " + p for p in elfs])]
def repo_p(d): return el.file_exists_p(el.expand_file_name(".git", d))