Mercurial > hg
comparison hgext/convert/subversion.py @ 9829:1b2516a547d4
convert/svn: delegate to svn bindings if HTTP probe fails
convert extension tries to guess the remote repository type with HTTP probes.
Unfortunately, it does not handle authentication or HTTPS handshakes, so regular
svn repositories may be excluded. Instead, when a non-404 error is retrieved,
we keep trying with the svn bindings. The drawback is missing svn bindings will
make the conversion to fail even for non-svn targets. This can be avoided with
--source.
author | Patrick Mezard <pmezard@gmail.com> |
---|---|
date | Wed, 11 Nov 2009 19:45:00 +0100 |
parents | dec177286deb |
children | 2e51cc30fc30 |
comparison
equal
deleted
inserted
replaced
9828:4761e6203b77 | 9829:1b2516a547d4 |
---|---|
6 import re | 6 import re |
7 import sys | 7 import sys |
8 import cPickle as pickle | 8 import cPickle as pickle |
9 import tempfile | 9 import tempfile |
10 import urllib | 10 import urllib |
11 import urllib2 | |
11 | 12 |
12 from mercurial import strutil, util, encoding | 13 from mercurial import strutil, util, encoding |
13 from mercurial.i18n import _ | 14 from mercurial.i18n import _ |
14 | 15 |
15 # Subversion stuff. Works best with very recent Python SVN bindings | 16 # Subversion stuff. Works best with very recent Python SVN bindings |
134 | 135 |
135 | 136 |
136 # Check to see if the given path is a local Subversion repo. Verify this by | 137 # Check to see if the given path is a local Subversion repo. Verify this by |
137 # looking for several svn-specific files and directories in the given | 138 # looking for several svn-specific files and directories in the given |
138 # directory. | 139 # directory. |
139 def filecheck(path, proto): | 140 def filecheck(ui, path, proto): |
140 for x in ('locks', 'hooks', 'format', 'db', ): | 141 for x in ('locks', 'hooks', 'format', 'db', ): |
141 if not os.path.exists(os.path.join(path, x)): | 142 if not os.path.exists(os.path.join(path, x)): |
142 return False | 143 return False |
143 return True | 144 return True |
144 | 145 |
145 # Check to see if a given path is the root of an svn repo over http. We verify | 146 # Check to see if a given path is the root of an svn repo over http. We verify |
146 # this by requesting a version-controlled URL we know can't exist and looking | 147 # this by requesting a version-controlled URL we know can't exist and looking |
147 # for the svn-specific "not found" XML. | 148 # for the svn-specific "not found" XML. |
148 def httpcheck(path, proto): | 149 def httpcheck(ui, path, proto): |
149 return ('<m:human-readable errcode="160013">' in | 150 try: |
150 urllib.urlopen('%s://%s/!svn/ver/0/.svn' % (proto, path)).read()) | 151 opener = urllib2.build_opener() |
152 rsp = opener.open('%s://%s/!svn/ver/0/.svn' % (proto, path)) | |
153 return '<m:human-readable errcode="160013">' in rsp.read() | |
154 except urllib2.HTTPError, inst: | |
155 if inst.code == 404: | |
156 return False | |
157 # Except for 404 we cannot know for sure this is not an svn repo | |
158 ui.warn(_('svn: cannot probe remote repository, assume it could be ' | |
159 'a subversion repository. Use --source if you know better.\n')) | |
160 return True | |
161 except: | |
162 # Could be urllib2.URLError if the URL is invalid or anything else. | |
163 return False | |
151 | 164 |
152 protomap = {'http': httpcheck, | 165 protomap = {'http': httpcheck, |
153 'https': httpcheck, | 166 'https': httpcheck, |
154 'file': filecheck, | 167 'file': filecheck, |
155 } | 168 } |
156 def issvnurl(url): | 169 def issvnurl(ui, url): |
157 try: | 170 try: |
158 proto, path = url.split('://', 1) | 171 proto, path = url.split('://', 1) |
159 if proto == 'file': | 172 if proto == 'file': |
160 path = urllib.url2pathname(path) | 173 path = urllib.url2pathname(path) |
161 except ValueError: | 174 except ValueError: |
163 path = os.path.abspath(url) | 176 path = os.path.abspath(url) |
164 if proto == 'file': | 177 if proto == 'file': |
165 path = path.replace(os.sep, '/') | 178 path = path.replace(os.sep, '/') |
166 check = protomap.get(proto, lambda p, p2: False) | 179 check = protomap.get(proto, lambda p, p2: False) |
167 while '/' in path: | 180 while '/' in path: |
168 if check(path, proto): | 181 if check(ui, path, proto): |
169 return True | 182 return True |
170 path = path.rsplit('/', 1)[0] | 183 path = path.rsplit('/', 1)[0] |
171 return False | 184 return False |
172 | 185 |
173 # SVN conversion code stolen from bzr-svn and tailor | 186 # SVN conversion code stolen from bzr-svn and tailor |
189 super(svn_source, self).__init__(ui, url, rev=rev) | 202 super(svn_source, self).__init__(ui, url, rev=rev) |
190 | 203 |
191 if not (url.startswith('svn://') or url.startswith('svn+ssh://') or | 204 if not (url.startswith('svn://') or url.startswith('svn+ssh://') or |
192 (os.path.exists(url) and | 205 (os.path.exists(url) and |
193 os.path.exists(os.path.join(url, '.svn'))) or | 206 os.path.exists(os.path.join(url, '.svn'))) or |
194 issvnurl(url)): | 207 issvnurl(ui, url)): |
195 raise NoRepo("%s does not look like a Subversion repo" % url) | 208 raise NoRepo("%s does not look like a Subversion repo" % url) |
196 | 209 |
197 try: | 210 try: |
198 SubversionException | 211 SubversionException |
199 except NameError: | 212 except NameError: |