def target_path_for_source(source_path): 'Return the target path for `source_path` (which may itself be a product).' path = path_stem(source_path) # strip off source ext. if is_product_path(path): # source might be a product. return path[len(build_dir_slash):] else: return path
def product_path_for_source(source_path): 'Retern the product path for `sourc_path` (which may itself be a product).' path = path_stem(source_path) # strip off source ext. if is_product_path(path): # source might be a product. return path else: return path_join(build_dir, path)
def muck_patch(ctx, args): if not len(args) in (1, 2): failF('''\ muck patch error: patch command takes one or two arguments. usage: muck patch [original_target] [target] creates a new target by copying either the source or product of the original to _build/[target], and then creates an empty [target].pat. muck patch [target.pat] update the patch file with the diff of the previously specified original and target. ''') if len(args) == 2: # create new patch. orig_target_path, target_path = args if orig_target_path.endswith('.pat'): errFL('muck patch error: original should not be a patch file: {}', orig_target_path) if target_path.endswith('.pat'): errFL('muck patch error: {} {}: target should not be a patch file: {}', target_path) patch_path = target_path + '.pat' if path_exists(patch_path): failF('muck patch error: {}: patch already exists.', patch_path) update_dependency(ctx, orig_target_path, dependent=None) orig_path = actual_path_for_target(orig_target_path) prod_path = product_path_for_target(target_path) if path_exists(prod_path): errFL('muck patch note: product already exists: {}', prod_path) else: errFL('muck patch note: copying original to product: {} -> {}', orig_path, prod_path) copy_file(orig_path, prod_path) else: # update existing patch. patch_path = args[0] if path_ext(patch_path) != '.pat': failF('muck patch error: argument does not specify a .pat file: {!r}', patch_path) deps = pat_dependencies(patch_path, open(patch_path), {}) orig_target_path = deps[0] update_dependency(ctx, orig_target_path, dependent=None) orig_path = actual_path_for_target(orig_target_path) target_path = path_stem(patch_path) prod_path = product_path_for_target(target_path) # update patch (both cases). patch_path_tmp = patch_path + tmp_ext cmd = ['pat', 'diff', orig_path, prod_path] errFL('muck patch note: diffing: `{}`', ' '.join(shlex.quote(w) for w in cmd)) with open(patch_path_tmp, 'wb') as f: code = runC(cmd, out=f) move_file(patch_path_tmp, patch_path, overwrite=True) if len(args) == 1: # updated existing patch. # need to remove or update the target record to avoid the 'did you mean to patch?' safeguard. # for now, just delete it to be safe; this makes the target look stale. try: ctx.db.delete_record(target_path=target_path) except KeyError: pass
def transform(target_path, ext=None, **kwargs): ''' Open a dependency using muck.load and then transform it using pithy.Transformer. Additional keyword arguments are passed to the specific load function matching `ext`; see muck.load for details. Muck's static analysis looks specifically for this function to infer dependencies; `target_path` must be a string literal. ''' seq = load(target_path, ext=ext, **kwargs) product = product_path_for_source(argv[0]) # TODO: needs to process wildcards. return Transformer(seq, log_stem=path_stem(product) + '.')