Mercurial > hg
comparison hgext/convert/monotone.py @ 6307:6840668e3bf6
cleanup monotone conversion and use commandline class
author | Mikkel Fahnøe Jørgensen <mikkel@dvide.com> |
---|---|
date | Sun, 03 Feb 2008 16:14:05 +0100 |
parents | 2f9de4aaea9e |
children | 950e72fc7cf3 |
comparison
equal
deleted
inserted
replaced
6306:2f9de4aaea9e | 6307:6840668e3bf6 |
---|---|
1 # monotone support for the convert extension | 1 # monotone support for the convert extension |
2 | 2 |
3 import os | 3 import os, re, time |
4 import re | |
5 import time | |
6 from mercurial import util | 4 from mercurial import util |
5 from common import NoRepo, commit, converter_source, checktool, commandline | |
6 from mercurial.i18n import _ | |
7 | 7 |
8 from common import NoRepo, commit, converter_source, checktool | 8 class monotone_source(converter_source, commandline): |
9 | |
10 class monotone_source(converter_source): | |
11 def __init__(self, ui, path=None, rev=None): | 9 def __init__(self, ui, path=None, rev=None): |
12 converter_source.__init__(self, ui, path, rev) | 10 converter_source.__init__(self, ui, path, rev) |
13 | 11 commandline.__init__(self, ui, 'mtn') |
12 | |
14 self.ui = ui | 13 self.ui = ui |
15 self.path = path | 14 self.path = path |
16 | 15 |
17 | |
18 # regular expressions for parsing monotone output | 16 # regular expressions for parsing monotone output |
19 | |
20 space = r'\s*' | 17 space = r'\s*' |
21 name = r'\s+"((?:[^"]|\\")*)"\s*' | 18 name = r'\s+"((?:[^"]|\\")*)"\s*' |
22 value = name | 19 value = name |
23 revision = r'\s+\[(\w+)\]\s*' | 20 revision = r'\s+\[(\w+)\]\s*' |
24 lines = r'(?:.|\n)+' | 21 lines = r'(?:.|\n)+' |
25 | 22 |
26 self.dir_re = re.compile(space + "dir" + name) | 23 self.dir_re = re.compile(space + "dir" + name) |
27 self.file_re = re.compile(space + "file" + name + "content" + revision) | 24 self.file_re = re.compile(space + "file" + name + "content" + revision) |
28 self.add_file_re = re.compile(space + "add_file" + name + "content" + revision) | 25 self.add_file_re = re.compile(space + "add_file" + name + "content" + revision) |
29 self.patch_re = re.compile(space + "patch" + name + "from" + revision + "to" + revision) | 26 self.patch_re = re.compile(space + "patch" + name + "from" + revision + "to" + revision) |
30 self.rename_re = re.compile(space + "rename" + name + "to" + name) | 27 self.rename_re = re.compile(space + "rename" + name + "to" + name) |
31 self.tag_re = re.compile(space + "tag" + name + "revision" + revision) | 28 self.tag_re = re.compile(space + "tag" + name + "revision" + revision) |
32 self.cert_re = re.compile(lines + space + "name" + name + "value" + value) | 29 self.cert_re = re.compile(lines + space + "name" + name + "value" + value) |
33 | 30 |
34 attr = space + "file" + lines + space + "attr" + space | 31 attr = space + "file" + lines + space + "attr" + space |
35 self.attr_execute_re = re.compile(attr + '"mtn:execute"' + space + '"true"') | 32 self.attr_execute_re = re.compile(attr + '"mtn:execute"' + space + '"true"') |
36 | 33 |
37 # cached data | 34 # cached data |
38 | |
39 self.manifest_rev = None | 35 self.manifest_rev = None |
40 self.manifest = None | 36 self.manifest = None |
41 self.files = None | 37 self.files = None |
42 self.dirs = None | 38 self.dirs = None |
43 | 39 |
44 norepo = NoRepo("%s does not look like a monotone repo" % path) | 40 norepo = NoRepo (_("%s does not look like a monotone repo") % path) |
45 if not os.path.exists(path): | 41 if not os.path.exists(path): |
46 raise norepo | 42 raise norepo |
47 | 43 |
48 checktool('mtn') | 44 checktool('mtn') |
49 | 45 |
50 # test if there are are any revisions | 46 # test if there are any revisions |
51 self.rev = None | 47 self.rev = None |
52 try : | 48 try: |
53 self.getheads() | 49 self.getheads() |
54 except : | 50 except: |
55 raise norepo | 51 raise norepo |
56 | |
57 self.rev = rev | 52 self.rev = rev |
58 | 53 |
59 | 54 def mtnrun(self, *args, **kwargs): |
60 def mtncmd(self, arg): | 55 kwargs['d'] = self.path |
61 cmdline = "mtn -d %s automate %s" % (util.shellquote(self.path), arg) | 56 return self.run0('automate', *args, **kwargs) |
62 self.ui.debug(cmdline, '\n') | 57 |
63 p = util.popen(cmdline) | |
64 result = p.read() | |
65 if p.close(): | |
66 raise IOError() | |
67 return result | |
68 | |
69 def mtnloadmanifest(self, rev): | 58 def mtnloadmanifest(self, rev): |
70 if self.manifest_rev == rev: | 59 if self.manifest_rev == rev: |
71 return | 60 return |
61 self.manifest = self.mtnrun("get_manifest_of", rev).split("\n\n") | |
72 self.manifest_rev = rev | 62 self.manifest_rev = rev |
73 self.manifest = self.mtncmd("get_manifest_of %s" % rev).split("\n\n") | 63 self.files = {} |
74 | 64 self.dirs = {} |
75 manifest = self.manifest | |
76 files = {} | |
77 dirs = {} | |
78 | 65 |
79 for e in manifest: | 66 for e in self.manifest: |
80 m = self.file_re.match(e) | 67 m = self.file_re.match(e) |
81 if m: | 68 if m: |
82 attr = "" | 69 attr = "" |
83 name = m.group(1) | 70 name = m.group(1) |
84 node = m.group(2) | 71 node = m.group(2) |
85 if self.attr_execute_re.match(e): | 72 if self.attr_execute_re.match(e): |
86 attr += "x" | 73 attr += "x" |
87 files[name] = (node, attr) | 74 self.files[name] = (node, attr) |
88 m = self.dir_re.match(e) | 75 m = self.dir_re.match(e) |
89 if m: | 76 if m: |
90 dirs[m.group(1)] = True | 77 self.dirs[m.group(1)] = True |
91 | |
92 self.files = files | |
93 self.dirs = dirs | |
94 | 78 |
95 def mtnisfile(self, name, rev): | 79 def mtnisfile(self, name, rev): |
96 # a non-file could be a directory or a deleted or renamed file | 80 # a non-file could be a directory or a deleted or renamed file |
97 self.mtnloadmanifest(rev) | 81 self.mtnloadmanifest(rev) |
98 try : | 82 try: |
99 self.files[name] | 83 self.files[name] |
100 return True | 84 return True |
101 except KeyError: | 85 except KeyError: |
102 return False | 86 return False |
103 | 87 |
104 def mtnisdir(self, name, rev): | 88 def mtnisdir(self, name, rev): |
105 self.mtnloadmanifest(rev) | 89 self.mtnloadmanifest(rev) |
106 try : | 90 try: |
107 self.dirs[name] | 91 self.dirs[name] |
108 return True | 92 return True |
109 except KeyError: | 93 except KeyError: |
110 return False | 94 return False |
111 | 95 |
112 def mtngetcerts(self, rev): | 96 def mtngetcerts(self, rev): |
113 certs = {"author":"<missing>", "date":"<missing>", | 97 certs = {"author":"<missing>", "date":"<missing>", |
114 "changelog":"<missing>", "branch":"<missing>"} | 98 "changelog":"<missing>", "branch":"<missing>"} |
115 cert_list = self.mtncmd("certs %s" % rev).split("\n\n") | 99 cert_list = self.mtnrun("certs", rev).split("\n\n") |
116 for e in cert_list: | 100 for e in cert_list: |
117 m = self.cert_re.match(e) | 101 m = self.cert_re.match(e) |
118 if m: | 102 if m: |
119 certs[m.group(1)] = m.group(2) | 103 certs[m.group(1)] = m.group(2) |
120 return certs | 104 return certs |
121 | |
122 def mtngetparents(self, rev): | |
123 parents = self.mtncmd("parents %s" % rev).strip("\n").split("\n") | |
124 p = [] | |
125 for x in parents: | |
126 if len(x) >= 40: # blank revs have been seen otherwise | |
127 p.append(x) | |
128 return p | |
129 | 105 |
130 def mtnrenamefiles(self, files, fromdir, todir): | 106 def mtnrenamefiles(self, files, fromdir, todir): |
131 renamed = {} | 107 renamed = {} |
132 for tofile in files: | 108 for tofile in files: |
133 suffix = tofile.lstrip(todir) | 109 suffix = tofile.lstrip(todir) |
134 if todir + suffix == tofile: | 110 if todir + suffix == tofile: |
135 renamed[tofile] = (fromdir + suffix).lstrip("/") | 111 renamed[tofile] = (fromdir + suffix).lstrip("/") |
136 return renamed | 112 return renamed |
137 | 113 |
138 | 114 |
139 # implement the converter_source interface: | 115 # implement the converter_source interface: |
140 | 116 |
141 def getheads(self): | 117 def getheads(self): |
142 if not self.rev or self.rev == "": | 118 if not self.rev: |
143 return self.mtncmd("leaves").splitlines() | 119 return self.mtnrun("leaves").splitlines() |
144 else: | 120 else: |
145 return [self.rev] | 121 return [self.rev] |
146 | 122 |
147 def getchanges(self, rev): | 123 def getchanges(self, rev): |
148 revision = self.mtncmd("get_revision %s" % rev).split("\n\n") | 124 #revision = self.mtncmd("get_revision %s" % rev).split("\n\n") |
125 revision = self.mtnrun("get_revision", rev).split("\n\n") | |
149 files = {} | 126 files = {} |
150 copies = {} | 127 copies = {} |
151 for e in revision: | 128 for e in revision: |
152 m = self.add_file_re.match(e) | 129 m = self.add_file_re.match(e) |
153 if m: | 130 if m: |
168 files[toname] = rev | 145 files[toname] = rev |
169 files[fromname] = rev | 146 files[fromname] = rev |
170 if self.mtnisdir(toname, rev): | 147 if self.mtnisdir(toname, rev): |
171 renamed = self.mtnrenamefiles(self.files, fromname, toname) | 148 renamed = self.mtnrenamefiles(self.files, fromname, toname) |
172 for tofile, fromfile in renamed.items(): | 149 for tofile, fromfile in renamed.items(): |
173 self.ui.debug (("copying file in renamed dir from '%s' to '%s'" % (fromfile, tofile)), "\n") | 150 self.ui.debug (_("copying file in renamed dir from '%s' to '%s'") % (fromfile, tofile), '\n') |
174 files[tofile] = rev | 151 files[tofile] = rev |
175 for fromfile in renamed.values(): | 152 for fromfile in renamed.values(): |
176 files[fromfile] = rev | 153 files[fromfile] = rev |
154 return (files.items(), copies) | |
177 | 155 |
178 return (files.items(), copies) | |
179 | |
180 def getmode(self, name, rev): | 156 def getmode(self, name, rev): |
181 self.mtnloadmanifest(rev) | 157 self.mtnloadmanifest(rev) |
182 try : | 158 try: |
183 node, attr = self.files[name] | 159 node, attr = self.files[name] |
184 return attr | 160 return attr |
185 except KeyError: | 161 except KeyError: |
186 return "" | 162 return "" |
187 | 163 |
188 def getfile(self, name, rev): | 164 def getfile(self, name, rev): |
189 if not self.mtnisfile(name, rev): | 165 if not self.mtnisfile(name, rev): |
190 raise IOError() # file was deleted or renamed | 166 raise IOError() # file was deleted or renamed |
191 return self.mtncmd("get_file_of %s -r %s" % (util.shellquote(name), rev)) | 167 try: |
192 | 168 return self.mtnrun("get_file_of", name, r=rev) |
193 def getcommit(self, rev): | 169 except: |
170 raise IOError() # file was deleted or renamed | |
171 | |
172 def getcommit(self, rev): | |
194 certs = self.mtngetcerts(rev) | 173 certs = self.mtngetcerts(rev) |
195 return commit( | 174 return commit( |
196 author=certs["author"], | 175 author=certs["author"], |
197 date=util.datestr(util.strdate(certs["date"], "%Y-%m-%dT%H:%M:%S")), | 176 date=util.datestr(util.strdate(certs["date"], "%Y-%m-%dT%H:%M:%S")), |
198 desc=certs["changelog"], | 177 desc=certs["changelog"], |
199 rev=rev, | 178 rev=rev, |
200 parents=self.mtngetparents(rev), | 179 parents=self.mtnrun("parents", rev).splitlines(), |
201 branch=certs["branch"]) | 180 branch=certs["branch"]) |
202 | 181 |
203 def gettags(self): | 182 def gettags(self): |
204 tags = {} | 183 tags = {} |
205 for e in self.mtncmd("tags").split("\n\n"): | 184 for e in self.mtnrun("tags").split("\n\n"): |
206 m = self.tag_re.match(e) | 185 m = self.tag_re.match(e) |
207 if m: | 186 if m: |
208 tags[m.group(1)] = m.group(2) | 187 tags[m.group(1)] = m.group(2) |
209 return tags | 188 return tags |
210 | 189 |