##// END OF EJS Templates
convert: raise Abort instead of NoRepo when CVS pserver auth fails....
Brendan Cully -
r5182:7e05bdee default
parent child Browse files
Show More
@@ -1,263 +1,263 b''
1 # CVS conversion code inspired by hg-cvs-import and git-cvsimport
1 # CVS conversion code inspired by hg-cvs-import and git-cvsimport
2
2
3 import os, locale, re, socket
3 import os, locale, re, socket
4 from mercurial import util
4 from mercurial import util
5
5
6 from common import NoRepo, commit, converter_source
6 from common import NoRepo, commit, converter_source
7
7
8 class convert_cvs(converter_source):
8 class convert_cvs(converter_source):
9 def __init__(self, ui, path, rev=None):
9 def __init__(self, ui, path, rev=None):
10 super(convert_cvs, self).__init__(ui, path, rev=rev)
10 super(convert_cvs, self).__init__(ui, path, rev=rev)
11
11
12 cvs = os.path.join(path, "CVS")
12 cvs = os.path.join(path, "CVS")
13 if not os.path.exists(cvs):
13 if not os.path.exists(cvs):
14 raise NoRepo("couldn't open CVS repo %s" % path)
14 raise NoRepo("couldn't open CVS repo %s" % path)
15
15
16 self.changeset = {}
16 self.changeset = {}
17 self.files = {}
17 self.files = {}
18 self.tags = {}
18 self.tags = {}
19 self.lastbranch = {}
19 self.lastbranch = {}
20 self.parent = {}
20 self.parent = {}
21 self.socket = None
21 self.socket = None
22 self.cvsroot = file(os.path.join(cvs, "Root")).read()[:-1]
22 self.cvsroot = file(os.path.join(cvs, "Root")).read()[:-1]
23 self.cvsrepo = file(os.path.join(cvs, "Repository")).read()[:-1]
23 self.cvsrepo = file(os.path.join(cvs, "Repository")).read()[:-1]
24 self.encoding = locale.getpreferredencoding()
24 self.encoding = locale.getpreferredencoding()
25 self._parse()
25 self._parse()
26 self._connect()
26 self._connect()
27
27
28 def _parse(self):
28 def _parse(self):
29 if self.changeset:
29 if self.changeset:
30 return
30 return
31
31
32 maxrev = 0
32 maxrev = 0
33 cmd = 'cvsps -A -u --cvs-direct -q'
33 cmd = 'cvsps -A -u --cvs-direct -q'
34 if self.rev:
34 if self.rev:
35 # TODO: handle tags
35 # TODO: handle tags
36 try:
36 try:
37 # patchset number?
37 # patchset number?
38 maxrev = int(self.rev)
38 maxrev = int(self.rev)
39 except ValueError:
39 except ValueError:
40 try:
40 try:
41 # date
41 # date
42 util.parsedate(self.rev, ['%Y/%m/%d %H:%M:%S'])
42 util.parsedate(self.rev, ['%Y/%m/%d %H:%M:%S'])
43 cmd = "%s -d '1970/01/01 00:00:01' -d '%s'" % (cmd, self.rev)
43 cmd = "%s -d '1970/01/01 00:00:01' -d '%s'" % (cmd, self.rev)
44 except util.Abort:
44 except util.Abort:
45 raise util.Abort('revision %s is not a patchset number or date' % self.rev)
45 raise util.Abort('revision %s is not a patchset number or date' % self.rev)
46
46
47 d = os.getcwd()
47 d = os.getcwd()
48 try:
48 try:
49 os.chdir(self.path)
49 os.chdir(self.path)
50 id = None
50 id = None
51 state = 0
51 state = 0
52 for l in os.popen(cmd):
52 for l in os.popen(cmd):
53 if state == 0: # header
53 if state == 0: # header
54 if l.startswith("PatchSet"):
54 if l.startswith("PatchSet"):
55 id = l[9:-2]
55 id = l[9:-2]
56 if maxrev and int(id) > maxrev:
56 if maxrev and int(id) > maxrev:
57 state = 3
57 state = 3
58 elif l.startswith("Date"):
58 elif l.startswith("Date"):
59 date = util.parsedate(l[6:-1], ["%Y/%m/%d %H:%M:%S"])
59 date = util.parsedate(l[6:-1], ["%Y/%m/%d %H:%M:%S"])
60 date = util.datestr(date)
60 date = util.datestr(date)
61 elif l.startswith("Branch"):
61 elif l.startswith("Branch"):
62 branch = l[8:-1]
62 branch = l[8:-1]
63 self.parent[id] = self.lastbranch.get(branch, 'bad')
63 self.parent[id] = self.lastbranch.get(branch, 'bad')
64 self.lastbranch[branch] = id
64 self.lastbranch[branch] = id
65 elif l.startswith("Ancestor branch"):
65 elif l.startswith("Ancestor branch"):
66 ancestor = l[17:-1]
66 ancestor = l[17:-1]
67 self.parent[id] = self.lastbranch[ancestor]
67 self.parent[id] = self.lastbranch[ancestor]
68 elif l.startswith("Author"):
68 elif l.startswith("Author"):
69 author = self.recode(l[8:-1])
69 author = self.recode(l[8:-1])
70 elif l.startswith("Tag:") or l.startswith("Tags:"):
70 elif l.startswith("Tag:") or l.startswith("Tags:"):
71 t = l[l.index(':')+1:]
71 t = l[l.index(':')+1:]
72 t = [ut.strip() for ut in t.split(',')]
72 t = [ut.strip() for ut in t.split(',')]
73 if (len(t) > 1) or (t[0] and (t[0] != "(none)")):
73 if (len(t) > 1) or (t[0] and (t[0] != "(none)")):
74 self.tags.update(dict.fromkeys(t, id))
74 self.tags.update(dict.fromkeys(t, id))
75 elif l.startswith("Log:"):
75 elif l.startswith("Log:"):
76 state = 1
76 state = 1
77 log = ""
77 log = ""
78 elif state == 1: # log
78 elif state == 1: # log
79 if l == "Members: \n":
79 if l == "Members: \n":
80 files = {}
80 files = {}
81 log = self.recode(log[:-1])
81 log = self.recode(log[:-1])
82 state = 2
82 state = 2
83 else:
83 else:
84 log += l
84 log += l
85 elif state == 2:
85 elif state == 2:
86 if l == "\n": #
86 if l == "\n": #
87 state = 0
87 state = 0
88 p = [self.parent[id]]
88 p = [self.parent[id]]
89 if id == "1":
89 if id == "1":
90 p = []
90 p = []
91 if branch == "HEAD":
91 if branch == "HEAD":
92 branch = ""
92 branch = ""
93 c = commit(author=author, date=date, parents=p,
93 c = commit(author=author, date=date, parents=p,
94 desc=log, branch=branch)
94 desc=log, branch=branch)
95 self.changeset[id] = c
95 self.changeset[id] = c
96 self.files[id] = files
96 self.files[id] = files
97 else:
97 else:
98 colon = l.rfind(':')
98 colon = l.rfind(':')
99 file = l[1:colon]
99 file = l[1:colon]
100 rev = l[colon+1:-2]
100 rev = l[colon+1:-2]
101 rev = rev.split("->")[1]
101 rev = rev.split("->")[1]
102 files[file] = rev
102 files[file] = rev
103 elif state == 3:
103 elif state == 3:
104 continue
104 continue
105
105
106 self.heads = self.lastbranch.values()
106 self.heads = self.lastbranch.values()
107 finally:
107 finally:
108 os.chdir(d)
108 os.chdir(d)
109
109
110 def _connect(self):
110 def _connect(self):
111 root = self.cvsroot
111 root = self.cvsroot
112 conntype = None
112 conntype = None
113 user, host = None, None
113 user, host = None, None
114 cmd = ['cvs', 'server']
114 cmd = ['cvs', 'server']
115
115
116 self.ui.status("connecting to %s\n" % root)
116 self.ui.status("connecting to %s\n" % root)
117
117
118 if root.startswith(":pserver:"):
118 if root.startswith(":pserver:"):
119 root = root[9:]
119 root = root[9:]
120 m = re.match(r'(?:(.*?)(?::(.*?))?@)?([^:\/]*)(?::(\d*))?(.*)',
120 m = re.match(r'(?:(.*?)(?::(.*?))?@)?([^:\/]*)(?::(\d*))?(.*)',
121 root)
121 root)
122 if m:
122 if m:
123 conntype = "pserver"
123 conntype = "pserver"
124 user, passw, serv, port, root = m.groups()
124 user, passw, serv, port, root = m.groups()
125 if not user:
125 if not user:
126 user = "anonymous"
126 user = "anonymous"
127 if not port:
127 if not port:
128 port = 2401
128 port = 2401
129 else:
129 else:
130 port = int(port)
130 port = int(port)
131 format0 = ":pserver:%s@%s:%s" % (user, serv, root)
131 format0 = ":pserver:%s@%s:%s" % (user, serv, root)
132 format1 = ":pserver:%s@%s:%d%s" % (user, serv, port, root)
132 format1 = ":pserver:%s@%s:%d%s" % (user, serv, port, root)
133
133
134 if not passw:
134 if not passw:
135 passw = "A"
135 passw = "A"
136 pf = open(os.path.join(os.environ["HOME"], ".cvspass"))
136 pf = open(os.path.join(os.environ["HOME"], ".cvspass"))
137 for line in pf.read().splitlines():
137 for line in pf.read().splitlines():
138 part1, part2 = line.split(' ', 1)
138 part1, part2 = line.split(' ', 1)
139 if part1 == '/1':
139 if part1 == '/1':
140 # /1 :pserver:user@example.com:2401/cvsroot/foo Ah<Z
140 # /1 :pserver:user@example.com:2401/cvsroot/foo Ah<Z
141 part1, part2 = part2.split(' ', 1)
141 part1, part2 = part2.split(' ', 1)
142 format = format1
142 format = format1
143 else:
143 else:
144 # :pserver:user@example.com:/cvsroot/foo Ah<Z
144 # :pserver:user@example.com:/cvsroot/foo Ah<Z
145 format = format0
145 format = format0
146 if part1 == format:
146 if part1 == format:
147 passw = part2
147 passw = part2
148 break
148 break
149 pf.close()
149 pf.close()
150
150
151 sck = socket.socket()
151 sck = socket.socket()
152 sck.connect((serv, port))
152 sck.connect((serv, port))
153 sck.send("\n".join(["BEGIN AUTH REQUEST", root, user, passw,
153 sck.send("\n".join(["BEGIN AUTH REQUEST", root, user, passw,
154 "END AUTH REQUEST", ""]))
154 "END AUTH REQUEST", ""]))
155 if sck.recv(128) != "I LOVE YOU\n":
155 if sck.recv(128) != "I LOVE YOU\n":
156 raise NoRepo("CVS pserver authentication failed")
156 raise util.Abort("CVS pserver authentication failed")
157
157
158 self.writep = self.readp = sck.makefile('r+')
158 self.writep = self.readp = sck.makefile('r+')
159
159
160 if not conntype and root.startswith(":local:"):
160 if not conntype and root.startswith(":local:"):
161 conntype = "local"
161 conntype = "local"
162 root = root[7:]
162 root = root[7:]
163
163
164 if not conntype:
164 if not conntype:
165 # :ext:user@host/home/user/path/to/cvsroot
165 # :ext:user@host/home/user/path/to/cvsroot
166 if root.startswith(":ext:"):
166 if root.startswith(":ext:"):
167 root = root[5:]
167 root = root[5:]
168 m = re.match(r'(?:([^@:/]+)@)?([^:/]+):?(.*)', root)
168 m = re.match(r'(?:([^@:/]+)@)?([^:/]+):?(.*)', root)
169 if not m:
169 if not m:
170 conntype = "local"
170 conntype = "local"
171 else:
171 else:
172 conntype = "rsh"
172 conntype = "rsh"
173 user, host, root = m.group(1), m.group(2), m.group(3)
173 user, host, root = m.group(1), m.group(2), m.group(3)
174
174
175 if conntype != "pserver":
175 if conntype != "pserver":
176 if conntype == "rsh":
176 if conntype == "rsh":
177 rsh = os.environ.get("CVS_RSH" or "rsh")
177 rsh = os.environ.get("CVS_RSH" or "rsh")
178 if user:
178 if user:
179 cmd = [rsh, '-l', user, host] + cmd
179 cmd = [rsh, '-l', user, host] + cmd
180 else:
180 else:
181 cmd = [rsh, host] + cmd
181 cmd = [rsh, host] + cmd
182
182
183 self.writep, self.readp = os.popen2(cmd)
183 self.writep, self.readp = os.popen2(cmd)
184
184
185 self.realroot = root
185 self.realroot = root
186
186
187 self.writep.write("Root %s\n" % root)
187 self.writep.write("Root %s\n" % root)
188 self.writep.write("Valid-responses ok error Valid-requests Mode"
188 self.writep.write("Valid-responses ok error Valid-requests Mode"
189 " M Mbinary E Checked-in Created Updated"
189 " M Mbinary E Checked-in Created Updated"
190 " Merged Removed\n")
190 " Merged Removed\n")
191 self.writep.write("valid-requests\n")
191 self.writep.write("valid-requests\n")
192 self.writep.flush()
192 self.writep.flush()
193 r = self.readp.readline()
193 r = self.readp.readline()
194 if not r.startswith("Valid-requests"):
194 if not r.startswith("Valid-requests"):
195 raise util.Abort("server sucks")
195 raise util.Abort("server sucks")
196 if "UseUnchanged" in r:
196 if "UseUnchanged" in r:
197 self.writep.write("UseUnchanged\n")
197 self.writep.write("UseUnchanged\n")
198 self.writep.flush()
198 self.writep.flush()
199 r = self.readp.readline()
199 r = self.readp.readline()
200
200
201 def getheads(self):
201 def getheads(self):
202 return self.heads
202 return self.heads
203
203
204 def _getfile(self, name, rev):
204 def _getfile(self, name, rev):
205 if rev.endswith("(DEAD)"):
205 if rev.endswith("(DEAD)"):
206 raise IOError
206 raise IOError
207
207
208 args = ("-N -P -kk -r %s --" % rev).split()
208 args = ("-N -P -kk -r %s --" % rev).split()
209 args.append(os.path.join(self.cvsrepo, name))
209 args.append(os.path.join(self.cvsrepo, name))
210 for x in args:
210 for x in args:
211 self.writep.write("Argument %s\n" % x)
211 self.writep.write("Argument %s\n" % x)
212 self.writep.write("Directory .\n%s\nco\n" % self.realroot)
212 self.writep.write("Directory .\n%s\nco\n" % self.realroot)
213 self.writep.flush()
213 self.writep.flush()
214
214
215 data = ""
215 data = ""
216 while 1:
216 while 1:
217 line = self.readp.readline()
217 line = self.readp.readline()
218 if line.startswith("Created ") or line.startswith("Updated "):
218 if line.startswith("Created ") or line.startswith("Updated "):
219 self.readp.readline() # path
219 self.readp.readline() # path
220 self.readp.readline() # entries
220 self.readp.readline() # entries
221 mode = self.readp.readline()[:-1]
221 mode = self.readp.readline()[:-1]
222 count = int(self.readp.readline()[:-1])
222 count = int(self.readp.readline()[:-1])
223 data = self.readp.read(count)
223 data = self.readp.read(count)
224 elif line.startswith(" "):
224 elif line.startswith(" "):
225 data += line[1:]
225 data += line[1:]
226 elif line.startswith("M "):
226 elif line.startswith("M "):
227 pass
227 pass
228 elif line.startswith("Mbinary "):
228 elif line.startswith("Mbinary "):
229 count = int(self.readp.readline()[:-1])
229 count = int(self.readp.readline()[:-1])
230 data = self.readp.read(count)
230 data = self.readp.read(count)
231 else:
231 else:
232 if line == "ok\n":
232 if line == "ok\n":
233 return (data, "x" in mode and "x" or "")
233 return (data, "x" in mode and "x" or "")
234 elif line.startswith("E "):
234 elif line.startswith("E "):
235 self.ui.warn("cvs server: %s\n" % line[2:])
235 self.ui.warn("cvs server: %s\n" % line[2:])
236 elif line.startswith("Remove"):
236 elif line.startswith("Remove"):
237 l = self.readp.readline()
237 l = self.readp.readline()
238 l = self.readp.readline()
238 l = self.readp.readline()
239 if l != "ok\n":
239 if l != "ok\n":
240 raise util.Abort("unknown CVS response: %s" % l)
240 raise util.Abort("unknown CVS response: %s" % l)
241 else:
241 else:
242 raise util.Abort("unknown CVS response: %s" % line)
242 raise util.Abort("unknown CVS response: %s" % line)
243
243
244 def getfile(self, file, rev):
244 def getfile(self, file, rev):
245 data, mode = self._getfile(file, rev)
245 data, mode = self._getfile(file, rev)
246 self.modecache[(file, rev)] = mode
246 self.modecache[(file, rev)] = mode
247 return data
247 return data
248
248
249 def getmode(self, file, rev):
249 def getmode(self, file, rev):
250 return self.modecache[(file, rev)]
250 return self.modecache[(file, rev)]
251
251
252 def getchanges(self, rev):
252 def getchanges(self, rev):
253 self.modecache = {}
253 self.modecache = {}
254 files = self.files[rev]
254 files = self.files[rev]
255 cl = files.items()
255 cl = files.items()
256 cl.sort()
256 cl.sort()
257 return (cl, {})
257 return (cl, {})
258
258
259 def getcommit(self, rev):
259 def getcommit(self, rev):
260 return self.changeset[rev]
260 return self.changeset[rev]
261
261
262 def gettags(self):
262 def gettags(self):
263 return self.tags
263 return self.tags
General Comments 0
You need to be logged in to leave comments. Login now