Mercurial > hg
comparison hgext/convert/cvsps.py @ 7097:d4218edd55bd
convert: fix builtin cvsps under Windows
Drafted and reviewed by Frank Kingswood <frank@kingswood-consulting.co.uk>.
author | Patrick Mezard <pmezard@gmail.com> |
---|---|
date | Mon, 13 Oct 2008 17:31:03 +0100 |
parents | 12472a240398 |
children | 810ca383da9c |
comparison
equal
deleted
inserted
replaced
7096:6dab29f6df37 | 7097:d4218edd55bd |
---|---|
39 self.__dict__.update(entries) | 39 self.__dict__.update(entries) |
40 | 40 |
41 class logerror(Exception): | 41 class logerror(Exception): |
42 pass | 42 pass |
43 | 43 |
44 def getrepopath(cvspath): | |
45 """Return the repository path from a CVS path. | |
46 | |
47 >>> getrepopath('/foo/bar') | |
48 '/foo/bar' | |
49 >>> getrepopath('c:/foo/bar') | |
50 'c:/foo/bar' | |
51 >>> getrepopath(':pserver:10/foo/bar') | |
52 '/foo/bar' | |
53 >>> getrepopath(':pserver:10c:/foo/bar') | |
54 '/foo/bar' | |
55 >>> getrepopath(':pserver:/foo/bar') | |
56 '/foo/bar' | |
57 >>> getrepopath(':pserver:c:/foo/bar') | |
58 'c:/foo/bar' | |
59 >>> getrepopath(':pserver:truc@foo.bar:/foo/bar') | |
60 '/foo/bar' | |
61 >>> getrepopath(':pserver:truc@foo.bar:c:/foo/bar') | |
62 'c:/foo/bar' | |
63 """ | |
64 # According to CVS manual, CVS paths are expressed like: | |
65 # [:method:][[user][:password]@]hostname[:[port]]/path/to/repository | |
66 # | |
67 # Unfortunately, Windows absolute paths start with a drive letter | |
68 # like 'c:' making it harder to parse. Here we assume that drive | |
69 # letters are only one character long and any CVS component before | |
70 # the repository path is at least 2 characters long, and use this | |
71 # to disambiguate. | |
72 parts = cvspath.split(':') | |
73 if len(parts) == 1: | |
74 return parts[0] | |
75 # Here there is an ambiguous case if we have a port number | |
76 # immediately followed by a Windows driver letter. We assume this | |
77 # never happens and decide it must be CVS path component, | |
78 # therefore ignoring it. | |
79 if len(parts[-2]) > 1: | |
80 return parts[-1].lstrip('0123456789') | |
81 return parts[-2] + ':' + parts[-1] | |
82 | |
44 def createlog(ui, directory=None, root="", rlog=True, cache=None): | 83 def createlog(ui, directory=None, root="", rlog=True, cache=None): |
45 '''Collect the CVS rlog''' | 84 '''Collect the CVS rlog''' |
46 | 85 |
47 # Because we store many duplicate commit log messages, reusing strings | 86 # Because we store many duplicate commit log messages, reusing strings |
48 # saves a lot of memory and pickle storage space. | 87 # saves a lot of memory and pickle storage space. |
81 prefix = "" | 120 prefix = "" |
82 directory = prefix | 121 directory = prefix |
83 except IOError: | 122 except IOError: |
84 raise logerror('Not a CVS sandbox') | 123 raise logerror('Not a CVS sandbox') |
85 | 124 |
86 if prefix and not prefix.endswith('/'): | 125 if prefix and not prefix.endswith(os.sep): |
87 prefix += '/' | 126 prefix += os.sep |
88 | 127 |
89 # Use the Root file in the sandbox, if it exists | 128 # Use the Root file in the sandbox, if it exists |
90 try: | 129 try: |
91 root = file(os.path.join('CVS','Root')).read().strip() | 130 root = file(os.path.join('CVS','Root')).read().strip() |
92 except IOError: | 131 except IOError: |
132 | 171 |
133 # build the CVS commandline | 172 # build the CVS commandline |
134 cmd = ['cvs', '-q'] | 173 cmd = ['cvs', '-q'] |
135 if root: | 174 if root: |
136 cmd.append('-d%s' % root) | 175 cmd.append('-d%s' % root) |
137 p = root.split(':')[-1] | 176 p = util.normpath(getrepopath(root)) |
138 if not p.endswith('/'): | 177 if not p.endswith('/'): |
139 p += '/' | 178 p += '/' |
140 prefix = p + prefix | 179 prefix = p + util.normpath(prefix) |
141 cmd.append(['log', 'rlog'][rlog]) | 180 cmd.append(['log', 'rlog'][rlog]) |
142 if date: | 181 if date: |
143 # no space between option and date string | 182 # no space between option and date string |
144 cmd.append('-d>%s' % date) | 183 cmd.append('-d>%s' % date) |
145 cmd.append(directory) | 184 cmd.append(directory) |
163 match = re_00.match(line) | 202 match = re_00.match(line) |
164 if match: | 203 if match: |
165 rcs = match.group(1) | 204 rcs = match.group(1) |
166 tags = {} | 205 tags = {} |
167 if rlog: | 206 if rlog: |
168 filename = rcs[:-2] | 207 filename = util.normpath(rcs[:-2]) |
169 if filename.startswith(prefix): | 208 if filename.startswith(prefix): |
170 filename = filename[len(prefix):] | 209 filename = filename[len(prefix):] |
171 if filename.startswith('/'): | 210 if filename.startswith('/'): |
172 filename = filename[1:] | 211 filename = filename[1:] |
173 if filename.startswith('Attic/'): | 212 if filename.startswith('Attic/'): |
189 | 228 |
190 elif state == 1: | 229 elif state == 1: |
191 # expect 'Working file' (only when using log instead of rlog) | 230 # expect 'Working file' (only when using log instead of rlog) |
192 match = re_10.match(line) | 231 match = re_10.match(line) |
193 assert match, _('RCS file must be followed by working file') | 232 assert match, _('RCS file must be followed by working file') |
194 filename = match.group(1) | 233 filename = util.normpath(match.group(1)) |
195 state = 2 | 234 state = 2 |
196 | 235 |
197 elif state == 2: | 236 elif state == 2: |
198 # expect 'symbolic names' | 237 # expect 'symbolic names' |
199 if re_20.match(line): | 238 if re_20.match(line): |