PageRenderTime 49ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/versions/backends/hg/base.py

https://github.com/pombredanne/django-versions
Python | 121 lines | 100 code | 19 blank | 2 comment | 19 complexity | f03c7f2b500225af5129bd0ce54dbb4a MD5 | raw file
  1. import logging
  2. import os
  3. from mercurial.cmdutil import walkchangerevs
  4. from mercurial import context
  5. from mercurial import error
  6. from mercurial import hg
  7. from mercurial import match
  8. from mercurial import node
  9. from mercurial import ui
  10. from versions.backends.base import BaseRepository
  11. from versions.exceptions import VersionDoesNotExist
  12. from versions.base import revision, Version
  13. class Repository(BaseRepository):
  14. def __init__(self, *args, **kwargs):
  15. self._ui = LogUI()
  16. self._ui.setconfig('ui', 'interactive', 'off')
  17. super(Repository, self).__init__(*args, **kwargs)
  18. @property
  19. def _local_repo(self):
  20. if self.key not in revision._state.repositories:
  21. if not os.path.exists(self.local):
  22. try:
  23. os.makedirs(self.local)
  24. revision._state.repositories[self.key] = hg.repository(self._ui, self.local, create=True)
  25. except error.RepoError:
  26. pass
  27. if self.key not in revision._state.repositories:
  28. revision._state.repositories[self.key] = hg.repository(self._ui, self.local)
  29. return revision._state.repositories[self.key]
  30. @property
  31. def _remote_repo(self):
  32. if self.remote:
  33. return hg.repository(self._ui, self.remote)
  34. def commit(self, items):
  35. def file_callback(repo, memctx, path):
  36. return context.memfilectx(
  37. path=path,
  38. data=items[path],
  39. islink=False,
  40. isexec=False,
  41. copied=False,
  42. )
  43. local_repo = self._local_repo
  44. remote_repo = self._remote_repo
  45. lock = local_repo.lock()
  46. try:
  47. if remote_repo:
  48. local_repo.pull(self._remote_repo)
  49. ctx = context.memctx(
  50. repo=local_repo,
  51. parents=('tip', None),
  52. text=revision.message,
  53. files=items.keys(),
  54. filectxfn=file_callback,
  55. user=str(revision.user.id),
  56. )
  57. version = node.hex(local_repo.commitctx(ctx))
  58. # TODO: if we want the working copy of the repository to be updated as well add logic to enable this.
  59. # hg.update(local_repo, local_repo['tip'].node())
  60. if remote_repo:
  61. local_repo.push(remote_repo)
  62. return version
  63. finally:
  64. lock.release()
  65. def versions(self, item):
  66. local_repo = self._local_repo
  67. instance_match = match.exact(local_repo.root, local_repo.getcwd(), [item])
  68. change_contexts = walkchangerevs(local_repo, instance_match, {'rev': None}, lambda ctx, fns: ctx)
  69. for change_context in change_contexts:
  70. yield Version(change_context)
  71. def version(self, item, rev=None):
  72. if rev is None:
  73. rev = 'tip'
  74. local_repo = self._local_repo
  75. fctx = local_repo.filectx(item, rev)
  76. try:
  77. raw_data = fctx.data()
  78. except error.LookupError:
  79. raise VersionDoesNotExist('Version `%s` does not exist for %s in %s' % (rev, item, self.local))
  80. return raw_data
  81. class LogUI(ui.ui):
  82. def __init__(self, *args, **kwargs):
  83. self.log = logging.getLogger('versions')
  84. super(LogUI, self).__init__(*args, **kwargs)
  85. def write(self, *args, **opts):
  86. if self._buffers:
  87. self._buffers[-1].extend([str(a) for a in args])
  88. else:
  89. for a in args:
  90. self.log.info(str(a))
  91. def write_err(self, *args, **opts):
  92. for a in args:
  93. self.log.error(str(a))
  94. def flush(self):
  95. pass
  96. def interactive(self):
  97. return False
  98. def formatted(self):
  99. return False
  100. def _readline(self, prompt=''):
  101. raise Exception('Unable to readline on a non-interactive client.')