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 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_host(fr, to): # if el.file_exists_p(to) and file_equal(fr, to): # print(lf("{to}: OK")) # return False host = el.HOST with el.hostname(None): el.sc("scp '{fr}' '{host}:{to}'") 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 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 cp_host(fr, to=None): # if el.file_exists_p(to) and file_equal(fr, to): # print(lf("{to}: OK")) # return False if to is None: to = el.file_name_nondirectory(fr).replace("_", "/") host = el.HOST with el.hostname(None): fr = el.expand_file_name(fr) el.sc("scp -r '{fr}' '{host}:{to}'") return True
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 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 complete(argv=None): if argv is None: argv = sys.argv assert argv[1] == "cook" (_flags, args) = parse_flags(argv[1:]) # below, assume we're completing the last word # current word being completed is sys.argv[-1] args = args[:-1] # fix the difference between bash-completion.el and the actual bash completion if re.match(":.", args[0]): args = [":", args[0][1:]] + args[1:] if len(args) == 1: if args[0] == ":": print("\n".join(module_names())) else: rs = el.sc("cook --list").split("\n") # remove extra args rs = [re.split(" :", s)[0] for s in rs] fr = [r for r in rs if re.match(args[0], r)] print("\n".join(fr)) elif len(args) == 2 and args[0] == ":": matching_cands = el.re_filter("^" + args[1], module_names()) print("\n".join(matching_cands)) elif len(args) == 3 and args[0] == ":": mod = get_module(args[1]) cands = list(recipe_dict(mod).keys()) matching_cands = el.re_filter("^" + args[2], cands) print("\n".join(matching_cands)) elif len(args) >= 4 and args[0] == ":": mod = get_module(args[1]) fun = recipe_dict(mod)[args[2]] part = args[-1] fun_args = function_arglist(fun) arg_idx = len(args) - 3 if arg_idx < len(fun_args) and fun_args[arg_idx] in [ "fname", "fnames" ]: print(el.sc("compgen -f -- {part}")) else: args = [""] * recipe_arity(fun) print(fun(("complete", part), *args)) else: print("")
def mtime(repo): """Return the last modification time of REPO.""" if clean_p(repo): with dd(repo): res = git_time_to_datetime( el.sc("git log -1 --date=local --format=%cd")) return res else: return datetime.now()
def sudo(cmd, fname=None): if fname: if os.access(fname, os.W_OK): return cmd elif os.access(os.path.dirname(fname), os.W_OK | os.X_OK): return cmd else: return "sudo " + cmd user = sc("whoami") su = "" if user == "root" else "sudo " return su + cmd
def chown(fname, owner): current = sc("stat -c %U:%G {fname}") if current == owner: print(lf("{fname}: OK")) return False else: if el.HOST is not None: bash(lf("chown -R {owner} {fname}")) else: bash(lf("sudo chown -R {owner} {fname}")) return True
def chmod(fname, permissions): current = sc("stat -c %a {fname}") if current == permissions: print(lf("{fname}: OK")) return False else: if el.HOST is not None: scb("chmod {permissions} {fname}") else: cmd = sudo(lf("chmod {permissions} {fname}"), fname) bash(cmd) return True
def exe_to_package(recipe, exe): if type(recipe) is int: return el.lf("dpkg -S $(which {exe})") elif recipe[0] == "complete": return el.sc("compgen -c -A file " + recipe[1])
def update(recipe): cook_el = el.emacs_cook_script("cook.el") user_p = " --user " if "/.local/" in cook_el else " " el.bash(el.lf("pip3 install{user_p}--upgrade pycook")) if "INSIDE_EMACS" in os.environ: el.sc(el.emacsclient_eval(el.lf('(load-file "{cook_el}")')))
def grep(cmd, regex): fcmd = cmd + " 2>/dev/null | grep -q '" + regex + "' && echo Y || echo N" return el.sc(fcmd) == "Y"
def install(recipe, package=None): if recipe == 42: st.install_package(package) elif recipe[0] == "complete": return el.sc("apt-cache pkgnames " + recipe[1])
def export_html(recipe, fname): fname = el.expand_file_name(fname) fhtml = re.sub("org$", "html", fname) el.sc(el.emacs_batch_eval(lf('(cs-org-to-html "{fname}")'))) if "INSIDE_EMACS" not in os.environ: return ["firefox " + shlex.quote(fhtml)]
def package_installed_p_dpkg(package): res = sc("dpkg --get-selections '{package}'") if res == "" or re.search("deinstall$", res): return False else: return True
def symlink_p(fname): return " -> " in el.sc("stat {fname}")
def md5sum(f): return el.sc("md5sum " + shlex.quote(f)).split(" ")[0]
def symlink_p(fname): (host, name) = parse_fname(fname) with hostname(host): txt = el.sc("stat {name}") return " -> " in txt