Beispiel #1
0
def do_patch(patch_file: Path,
             original: Path,
             output: Path,
             context_size=5,
             force=False):
    original_lines = []
    patch_lines = []
    with open(patch_file, 'rt') as f:
        for line in f:
            patch_lines.append(line.rstrip("\r\n"))
    patch = parse_unified_diff(patch_lines)
    patch_lines = None  # Free
    with open(original, 'rt') as f:
        for line in f:
            original_lines.append(line.rstrip("\r\n"))
    try:
        result_lines = patch.apply_to(original_lines)
    except PatchFailedException as e:
        raise CommandError(str(e)) from None
    try:
        with open(output, 'wt' if force else 'xt') as f:
            for line in result_lines:
                f.write(line)
                f.write('\n')
    except FileExistsError:
        raise CommandError("Output file already exists: {}".format(output))
Beispiel #2
0
def fix_patch(patch_file: Path, original_file: Path, strict=False, context=5):
    """Fixes errors detected in the patch, by leniently parsing it and then re-emitting it"""
    if not patch_file.is_file():
        if patch_file.exists():
            raise CommandError(
                "Patch file is a directory: {}".format(patch_file))
        else:
            raise CommandError(
                "Patch file doesn't exist: {}".format(patch_file))
    if not original_file.is_file():
        if original_file.exists():
            raise CommandError(
                "Original file is a directory: {}".format(original_file))
        else:
            raise CommandError(
                "Original file doesn't exist: {}".format(original_file))
    patch_lines = []
    # TODO: Make a public API for parsing original_name and revised_name
    original_name, revised_name = None, None
    with open(patch_file, 'rt') as f:
        for line in f:
            if original_name is None and line.startswith('---'):
                original_name = line[3:].split()[0]
            elif revised_name is None and line.startswith('+++'):
                revised_name = line[3:].split()[0]
            patch_lines.append(line.rstrip("\r\n"))
    original_lines = []
    with open(original_file, 'rt') as f:
        for line in f:
            original_lines.append(line.rstrip("\r\n"))
    if original_name is None:
        raise CommandError(
            "Unable to detect original file name in {}".format(patch_file))
    elif revised_name is None:
        raise CommandError(
            "Unable to detect revised file name in {}".format(patch_file))
    patch = parse_unified_diff(patch_lines, lenient=not strict)
    with open(patch_file, 'wt') as f:
        for line in generate_unified_diff(original_name,
                                          revised_name,
                                          original_lines,
                                          patch,
                                          context_size=context):
            f.write(line)
            f.write('\n')
Beispiel #3
0
def patch(quiet=False):
    """Applies the patch files to the working directory, overriding any existing work."""
    setup = setup_patching()
    patches, unpatched_sources, patched_sources = setup.patches, setup.unpatched_sources, setup.patched_sources
    print("---- Applying Fountain patches via DiffUtils")
    for patch_root, dirs, files in os.walk(str(patches)):
        for patch_file_name in files:
            patch_file = Path(patch_root, patch_file_name)
            if patch_file.suffix != '.patch':
                raise CommandError(
                    f"Patch file doesn't end with '.patch': {patch_file_name}")
            relative_path = Path(patch_file.parent.relative_to(patches),
                                 patch_file.stem)
            original_file = Path(unpatched_sources, relative_path)
            output_file = Path(patched_sources, relative_path)
            if not original_file.exists():
                raise CommandError(
                    f"Couldn't find  original {original_file} for patch {patch_file}!"
                )
            output_file.parent.mkdir(parents=True, exist_ok=True)
            patch_lines = []
            with open(patch_file, 'rt') as f:
                for line in f:
                    patch_lines.append(line.rstrip('\r\n'))
            patch = parse_unified_diff(patch_lines)
            patch_lines = None  # Free
            original_lines = []
            with open(original_file, 'rt') as f:
                for line in f:
                    original_lines.append(line.rstrip('\r\n'))
            try:
                result_lines = patch.apply_to(original_lines)
            except PatchFailedException as e:
                raise CommandError(
                    f"Unable to apply {relative_path}.patch: {e}") from None
            # TODO: Should we be forcibly overriding files here?
            with open(output_file, 'wt') as f:
                for line in result_lines:
                    f.write(line)
                    f.write('\n')