bazaar.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import os
  2. import tempfile
  3. import re
  4. from pip.backwardcompat import urlparse
  5. from pip.log import logger
  6. from pip.util import rmtree, display_path, call_subprocess
  7. from pip.vcs import vcs, VersionControl
  8. from pip.download import path_to_url
  9. class Bazaar(VersionControl):
  10. name = 'bzr'
  11. dirname = '.bzr'
  12. repo_name = 'branch'
  13. bundle_file = 'bzr-branch.txt'
  14. schemes = ('bzr', 'bzr+http', 'bzr+https', 'bzr+ssh', 'bzr+sftp', 'bzr+ftp', 'bzr+lp')
  15. guide = ('# This was a Bazaar branch; to make it a branch again run:\n'
  16. 'bzr branch -r %(rev)s %(url)s .\n')
  17. def __init__(self, url=None, *args, **kwargs):
  18. super(Bazaar, self).__init__(url, *args, **kwargs)
  19. # Python >= 2.7.4, 3.3 doesn't have uses_fragment or non_hierarchical
  20. # Register lp but do not expose as a scheme to support bzr+lp.
  21. if getattr(urlparse, 'uses_fragment', None):
  22. urlparse.uses_fragment.extend(['lp'])
  23. urlparse.non_hierarchical.extend(['lp'])
  24. def parse_vcs_bundle_file(self, content):
  25. url = rev = None
  26. for line in content.splitlines():
  27. if not line.strip() or line.strip().startswith('#'):
  28. continue
  29. match = re.search(r'^bzr\s*branch\s*-r\s*(\d*)', line)
  30. if match:
  31. rev = match.group(1).strip()
  32. url = line[match.end():].strip().split(None, 1)[0]
  33. if url and rev:
  34. return url, rev
  35. return None, None
  36. def export(self, location):
  37. """Export the Bazaar repository at the url to the destination location"""
  38. temp_dir = tempfile.mkdtemp('-export', 'pip-')
  39. self.unpack(temp_dir)
  40. if os.path.exists(location):
  41. # Remove the location to make sure Bazaar can export it correctly
  42. rmtree(location)
  43. try:
  44. call_subprocess([self.cmd, 'export', location], cwd=temp_dir,
  45. filter_stdout=self._filter, show_stdout=False)
  46. finally:
  47. rmtree(temp_dir)
  48. def switch(self, dest, url, rev_options):
  49. call_subprocess([self.cmd, 'switch', url], cwd=dest)
  50. def update(self, dest, rev_options):
  51. call_subprocess(
  52. [self.cmd, 'pull', '-q'] + rev_options, cwd=dest)
  53. def obtain(self, dest):
  54. url, rev = self.get_url_rev()
  55. if rev:
  56. rev_options = ['-r', rev]
  57. rev_display = ' (to revision %s)' % rev
  58. else:
  59. rev_options = []
  60. rev_display = ''
  61. if self.check_destination(dest, url, rev_options, rev_display):
  62. logger.notify('Checking out %s%s to %s'
  63. % (url, rev_display, display_path(dest)))
  64. call_subprocess(
  65. [self.cmd, 'branch', '-q'] + rev_options + [url, dest])
  66. def get_url_rev(self):
  67. # hotfix the URL scheme after removing bzr+ from bzr+ssh:// readd it
  68. url, rev = super(Bazaar, self).get_url_rev()
  69. if url.startswith('ssh://'):
  70. url = 'bzr+' + url
  71. return url, rev
  72. def get_url(self, location):
  73. urls = call_subprocess(
  74. [self.cmd, 'info'], show_stdout=False, cwd=location)
  75. for line in urls.splitlines():
  76. line = line.strip()
  77. for x in ('checkout of branch: ',
  78. 'parent branch: '):
  79. if line.startswith(x):
  80. repo = line.split(x)[1]
  81. if self._is_local_repository(repo):
  82. return path_to_url(repo)
  83. return repo
  84. return None
  85. def get_revision(self, location):
  86. revision = call_subprocess(
  87. [self.cmd, 'revno'], show_stdout=False, cwd=location)
  88. return revision.splitlines()[-1]
  89. def get_tag_revs(self, location):
  90. tags = call_subprocess(
  91. [self.cmd, 'tags'], show_stdout=False, cwd=location)
  92. tag_revs = []
  93. for line in tags.splitlines():
  94. tags_match = re.search(r'([.\w-]+)\s*(.*)$', line)
  95. if tags_match:
  96. tag = tags_match.group(1)
  97. rev = tags_match.group(2)
  98. tag_revs.append((rev.strip(), tag.strip()))
  99. return dict(tag_revs)
  100. def get_src_requirement(self, dist, location, find_tags):
  101. repo = self.get_url(location)
  102. if not repo.lower().startswith('bzr:'):
  103. repo = 'bzr+' + repo
  104. egg_project_name = dist.egg_name().split('-', 1)[0]
  105. if not repo:
  106. return None
  107. current_rev = self.get_revision(location)
  108. tag_revs = self.get_tag_revs(location)
  109. if current_rev in tag_revs:
  110. # It's a tag
  111. full_egg_name = '%s-%s' % (egg_project_name, tag_revs[current_rev])
  112. else:
  113. full_egg_name = '%s-dev_r%s' % (dist.egg_name(), current_rev)
  114. return '%s@%s#egg=%s' % (repo, current_rev, full_egg_name)
  115. vcs.register(Bazaar)