aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pomu/package.py9
-rw-r--r--pomu/source/patch.py72
-rw-r--r--setup.py2
3 files changed, 82 insertions, 1 deletions
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_']
}