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 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 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 recipe_names_ordered(book): body = ast.parse(el.slurp(book)).body return [f.name for f in body if isinstance(f, ast.FunctionDef)]
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"))