-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
/
Copy pathhg.py
131 lines (110 loc) · 4.02 KB
/
hg.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
"""Mercurial-related utilities."""
from django.conf import settings
from readthedocs.projects.exceptions import RepositoryError
from readthedocs.vcs_support.base import BaseVCS, Deprecated, VCSVersion
class Backend(Deprecated, BaseVCS):
"""Mercurial VCS backend."""
supports_tags = True
supports_branches = True
fallback_branch = "default"
def update(self):
super().update()
return self.clone()
def clone(self):
self.make_clean_working_dir()
try:
# Disable sparse-revlog extension when cloning because it's not
# included in older versions of Mercurial and producess an error
# when using an old version. See
# https://github.com/readthedocs/readthedocs.org/pull/9042/
output = self.run(
"hg", "clone", "--config", "format.sparse-revlog=no", self.repo_url, "."
)
return output
except RepositoryError:
message_id = RepositoryError.CLONE_ERROR_WITH_PRIVATE_REPO_NOT_ALLOWED
if settings.ALLOW_PRIVATE_REPOS:
message_id = RepositoryError.CLONE_ERROR_WITH_PRIVATE_REPO_ALLOWED
raise RepositoryError(message_id=message_id)
@property
def branches(self):
try:
_, stdout, _ = self.run(
"hg",
"branches",
"--quiet",
record_as_success=True,
)
return self.parse_branches(stdout)
except RepositoryError:
# error (or no tags found)
return []
def parse_branches(self, data):
"""
Parses output of `hg branches --quiet`.
Example:
default
0.2
0.1
Into VCSVersion objects with branch name as verbose_name and
identifier.
"""
names = [name.lstrip() for name in data.splitlines()]
return [VCSVersion(self, name, name) for name in names if name]
@property
def tags(self):
try:
_, stdout, _ = self.run("hg", "tags", record_as_success=True)
return self.parse_tags(stdout)
except RepositoryError:
# error (or no tags found)
return []
def parse_tags(self, data):
"""
Parses output of `hg tags`.
Example:
tip 278:c4b2d21db51a
0.2.2 152:6b0364d98837
0.2.1 117:a14b7b6ffa03
0.1 50:30c2c6b3a055
maintenance release 1 10:f83c32fe8126
Into VCSVersion objects with the tag name as verbose_name and the
commit hash as identifier.
"""
vcs_tags = []
tag_lines = [line.strip() for line in data.splitlines()]
# starting from the rhs of each line, split a single value (changeset)
# off at whitespace; the tag name is the string to the left of that
tag_pairs = [line.rsplit(None, 1) for line in tag_lines]
for row in tag_pairs:
if len(row) != 2:
continue
name, commit = row
if name == "tip":
continue
_, commit_hash = commit.split(":")
vcs_tags.append(VCSVersion(self, commit_hash, name))
return vcs_tags
@property
def commit(self):
_, stdout = self.run("hg", "identify", "--id")[:2]
return stdout.strip()
def checkout(self, identifier=None):
super().checkout()
if not identifier:
identifier = "tip"
try:
code, stdout, stderr = self.run(
"hg",
"update",
"--clean",
identifier,
)
return code, stdout, stderr
except RepositoryError:
raise RepositoryError(
message_id=RepositoryError.FAILED_TO_CHECKOUT,
format_values={
"identifier": identifier,
},
)