##// END OF EJS Templates
cleanup monotone conversion and use commandline class
Mikkel Fahnøe Jørgensen -
r6307:6840668e default
parent child Browse files
Show More
@@ -1,214 +1,193
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)
11 commandline.__init__(self, ui, 'mtn')
13
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')
63 p = util.popen(cmdline)
64 result = p.read()
65 if p.close():
66 raise IOError()
67 return result
68
57
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 = {}
64 self.dirs = {}
74
65
75 manifest = self.manifest
66 for e in self.manifest:
76 files = {}
77 dirs = {}
78
79 for e in 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
105
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
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:
154 files[m.group(1)] = rev
131 files[m.group(1)] = rev
155 m = self.patch_re.match(e)
132 m = self.patch_re.match(e)
156 if m:
133 if m:
157 files[m.group(1)] = rev
134 files[m.group(1)] = rev
158
135
159 # Delete/rename is handled later when the convert engine
136 # Delete/rename is handled later when the convert engine
160 # discovers an IOError exception from getfile,
137 # discovers an IOError exception from getfile,
161 # but only if we add the "from" file to the list of changes.
138 # but only if we add the "from" file to the list of changes.
162 m = self.rename_re.match(e)
139 m = self.rename_re.match(e)
163 if m:
140 if m:
164 toname = m.group(2)
141 toname = m.group(2)
165 fromname = m.group(1)
142 fromname = m.group(1)
166 if self.mtnisfile(toname, rev):
143 if self.mtnisfile(toname, rev):
167 copies[toname] = fromname
144 copies[toname] = fromname
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
177
178 return (files.items(), copies)
154 return (files.items(), copies)
179
155
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:
168 return self.mtnrun("get_file_of", name, r=rev)
169 except:
170 raise IOError() # file was deleted or renamed
192
171
193 def getcommit(self, rev):
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
211 def getchangedfiles(self, rev, i):
190 def getchangedfiles(self, rev, i):
212 # This function is only needed to support --filemap
191 # This function is only needed to support --filemap
213 # ... and we don't support that
192 # ... and we don't support that
214 raise NotImplementedError()
193 raise NotImplementedError()
General Comments 0
You need to be logged in to leave comments. Login now