From 6cf478d92f538e8f3d1704dbc5a0ce5677f93ee3 Mon Sep 17 00:00:00 2001 From: Mykyta Holubakha Date: Thu, 6 Jul 2017 04:47:17 +0300 Subject: patch package source module patch application in packages new dependency: patch --- pomu/package.py | 9 +++++++ pomu/source/patch.py | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++ setup.py | 2 +- 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 pomu/source/patch.py diff --git a/pomu/package.py b/pomu/package.py index 7c9321e..5027569 100644 --- a/pomu/package.py +++ b/pomu/package.py @@ -10,6 +10,8 @@ from shutil import copy2 import subprocess +from patch import PatchSet + from pomu.util.fs import strip_prefix from pomu.util.result import Result @@ -82,6 +84,13 @@ class Package(): return Result.Err('You do not have enough permissions') return Result.Ok() + def apply_patches(self, location, patches): + """Applies a sequence of patches at the location""" + ps = PatchSet() + for p in patches: + ps.parse(open(p, 'r')) + ps.apply(root=location) + def gen_manifests(self, dst): """ Generate manifests for the installed package (in the dst directory). diff --git a/pomu/source/patch.py b/pomu/source/patch.py new file mode 100644 index 0000000..69a0821 --- /dev/null +++ b/pomu/source/patch.py @@ -0,0 +1,72 @@ +""" +A package source module to import packages from filesystem locations (ebuilds) +""" + +from os import path, mkdtemp + +from pomu.package import Package +from pomu.source import dispatcher +from pomu.util.pkg import cpv_split, ver_str +from pomu.util.query import query +from pomu.util.result import Result + +class Patcher(): + """A class to represent a local ebuild""" + __name__ = 'patch' + + def __init__(self, wrapped, *patches): + self.patches = patches + self.wrapped = wrapped + # nested patching + if wrapped is Patcher: + self.patches = wrapped.patches + self.patches + self.wrapped = wrapped.wrapped + + def fetch(self): + pkg = self.wrapped.fetch() + pkg.backend = self + pd = mkdtemp() + pkg.merge_into(pd) + pkg.apply_patches(pd, self.patches) + return Package(pkg.name, pd, self, pkg.category, pkg.version) + + @staticmethod + def from_data_dir(pkgdir): + with open(path.join(pkgdir, 'PATCH_ORIG_BACKEND'), 'r') as f: + wrapped = dispatcher.backends[bname].from_meta_dir(pkgdir) + patches = [path.join(pkgdir, 'patches', x.strip()) + for x in open(path.join(pkgdir, 'PATCH_PATCHES_ORDER'))] + + def write_meta(self, pkgdir): + with open(path.join(pkgdir, 'PATCH_ORIG_BACKEND'), 'w') as f: + f.write('{}\n'.format(self.wrapped.__name__)) + with open(path.join(pkgdir, 'PATCH_PATCHES_ORDER'), 'w') as f: + for p in self.patches: + f.write(path.basename(p) + '\n') + os.makedirs(path.join(pkgdir, 'patches'), exist_ok=True) + for p in self.patches: + shutil.copy2(p, path.join(pkgdir, 'patches')) + # write originals? + + def __str__(self): + return '{}/{}-{} (from {})'.format(self.category, self.name, self.version, self.path) + +@dispatcher.source +class LocalEbuildSource(): + """The source module responsible for importing and patching various ebuilds""" + @dispatcher.handler() + def parse_full(uri): + if not uri.startswith('patch:'): + return Result.Err() + uri = uri[6:] + patchf, _, pks = uri.partition(':') + if not path.isfile(patchf): + return Result.Err('Invalid patch file') + if not pks: + return Result.Err('Package not provided') + pkg = dispatcher.get_package(pks) + return Result.Ok(Patcher(patchf, pkg) + + @classmethod + def from_meta_dir(cls, metadir): + return Patcher.from_data_dir(cls, metadir) diff --git a/setup.py b/setup.py index c247110..53fcb80 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( author_email='hilobakho@gmail.com', license='GNU GPLv2', packages=find_packages(exclude=['tests']), - install_requires=['Click', 'GitPython'], + install_requires=['Click', 'GitPython', 'patch'], entry_points={ 'console_scripts':['pomu = pomu.cli:main_'] } -- cgit v1.2.3-65-gdbad