def __init__(self, repo, git=None): self.repo = repo self._temp_dir = Tempdir() self._opened = False self._git = git or Git()
class GitInstall(object): """Tool to install a Python package by cloning its git repo and if necessary modifying files inside. Used as a context manager, it allows to run python code (for instance the :class:`LineReplacer` on setup.py or installing patches, etc) after the repo has been cloned and before the install. The value returned by entering the context manager is the directory in which the repo has been cloned. Example: add ``from sett.utils import *`` at the end of the ``__init__.py`` >>> from paver.easy import * >>> with GitInstall('gitlab.enix.org:grocher/sett.git') as sett_dir: ... # Git repository is cloned ... with open(sett_dir.joinpath('sett/__init__.py', 'a+', encoding='utf-8')) as init: ... init.write('\nfrom sett.utils import *\n') ... # setup.py install is called """ def __init__(self, repo, git=None): self.repo = repo self._temp_dir = Tempdir() self._opened = False self._git = git or Git() def open(self): """Makes a shallow copy of the repository in a temporary directory""" if not self._opened: self.temp_dir = self._temp_dir.open() self._git.clone(self.repo, self.temp_dir) self._opened = True return self.temp_dir def __enter__(self): return self.open() def install(self): """Installs the software by calling setup.py install""" with pushd(self.open()): sh([sys.executable, self.temp_dir.joinpath('setup.py'), 'install']) def close(self): """Closes the temporary directory""" if not self._opened: raise ValueError('Cannot close a unopened instance') self._temp_dir.close() self._opened = False def __exit__(self, exc_value, exc_type, tb): try: if exc_value is None: self.install() finally: self.close() def __call__(self): try: self.open() self.install() finally: self.close() def patch(self, patch_file, *args, **kw): """ Apply a diff via the patch command on the cloned copy. """ temp_dir = self.open() strip = kw.pop('p', 1) cmd = [which.patch, '--batch', '-p', str(strip), '-i', patch_file, '-d', temp_dir] cmd.extend(args) cmd.extend('--{}={}'.format(k, v) for k, v in kw.items()) sh(cmd)