/versions/backends/hg/base.py
Python | 121 lines | 100 code | 19 blank | 2 comment | 19 complexity | f03c7f2b500225af5129bd0ce54dbb4a MD5 | raw file
- import logging
- import os
- from mercurial.cmdutil import walkchangerevs
- from mercurial import context
- from mercurial import error
- from mercurial import hg
- from mercurial import match
- from mercurial import node
- from mercurial import ui
- from versions.backends.base import BaseRepository
- from versions.exceptions import VersionDoesNotExist
- from versions.base import revision, Version
- class Repository(BaseRepository):
- def __init__(self, *args, **kwargs):
- self._ui = LogUI()
- self._ui.setconfig('ui', 'interactive', 'off')
- super(Repository, self).__init__(*args, **kwargs)
- @property
- def _local_repo(self):
- if self.key not in revision._state.repositories:
- if not os.path.exists(self.local):
- try:
- os.makedirs(self.local)
- revision._state.repositories[self.key] = hg.repository(self._ui, self.local, create=True)
- except error.RepoError:
- pass
- if self.key not in revision._state.repositories:
- revision._state.repositories[self.key] = hg.repository(self._ui, self.local)
- return revision._state.repositories[self.key]
- @property
- def _remote_repo(self):
- if self.remote:
- return hg.repository(self._ui, self.remote)
- def commit(self, items):
- def file_callback(repo, memctx, path):
- return context.memfilectx(
- path=path,
- data=items[path],
- islink=False,
- isexec=False,
- copied=False,
- )
- local_repo = self._local_repo
- remote_repo = self._remote_repo
- lock = local_repo.lock()
- try:
- if remote_repo:
- local_repo.pull(self._remote_repo)
- ctx = context.memctx(
- repo=local_repo,
- parents=('tip', None),
- text=revision.message,
- files=items.keys(),
- filectxfn=file_callback,
- user=str(revision.user.id),
- )
- version = node.hex(local_repo.commitctx(ctx))
- # TODO: if we want the working copy of the repository to be updated as well add logic to enable this.
- # hg.update(local_repo, local_repo['tip'].node())
- if remote_repo:
- local_repo.push(remote_repo)
- return version
- finally:
- lock.release()
- def versions(self, item):
- local_repo = self._local_repo
- instance_match = match.exact(local_repo.root, local_repo.getcwd(), [item])
- change_contexts = walkchangerevs(local_repo, instance_match, {'rev': None}, lambda ctx, fns: ctx)
- for change_context in change_contexts:
- yield Version(change_context)
- def version(self, item, rev=None):
- if rev is None:
- rev = 'tip'
- local_repo = self._local_repo
- fctx = local_repo.filectx(item, rev)
- try:
- raw_data = fctx.data()
- except error.LookupError:
- raise VersionDoesNotExist('Version `%s` does not exist for %s in %s' % (rev, item, self.local))
- return raw_data
- class LogUI(ui.ui):
- def __init__(self, *args, **kwargs):
- self.log = logging.getLogger('versions')
- super(LogUI, self).__init__(*args, **kwargs)
- def write(self, *args, **opts):
- if self._buffers:
- self._buffers[-1].extend([str(a) for a in args])
- else:
- for a in args:
- self.log.info(str(a))
- def write_err(self, *args, **opts):
- for a in args:
- self.log.error(str(a))
- def flush(self):
- pass
- def interactive(self):
- return False
- def formatted(self):
- return False
- def _readline(self, prompt=''):
- raise Exception('Unable to readline on a non-interactive client.')