Mercurial > hgsubversion
comparison hgsubversion/svnexternals.py @ 1352:30193fdd5da4
Addressed using relative URLs to actually divert to another server & added DocTest strings.
Code has been tested on real-world repositories that use relative references
but adding tests which do the round trip testing as a standalone has been beyond
me.
| author | Gadget Steve <gadgetsteve@hotmail.com> |
|---|---|
| date | Sat, 19 Sep 2015 07:27:31 +0100 |
| parents | 9d58ca6253a3 |
| children | c79fdd5f615d |
comparison
equal
deleted
inserted
replaced
| 1351:9d58ca6253a3 | 1352:30193fdd5da4 |
|---|---|
| 123 def resolvedots(url): | 123 def resolvedots(url): |
| 124 """ | 124 """ |
| 125 Fix references that include .. entries. | 125 Fix references that include .. entries. |
| 126 Scans a URL for .. type entries and resolves them but will not allow any | 126 Scans a URL for .. type entries and resolves them but will not allow any |
| 127 number of ..s to take us out of domain so http://.. will raise an exception. | 127 number of ..s to take us out of domain so http://.. will raise an exception. |
| 128 | |
| 129 Tests, (Don't know how to construct a round trip for this so doctest): | |
| 130 >>> # Relative URL within servers svn area | |
| 131 >>> resolvedots( | |
| 132 ... "http://some.svn.server/svn/some_repo/../other_repo") | |
| 133 'http://some.svn.server/svn/other_repo' | |
| 134 >>> # Complex One | |
| 135 >>> resolvedots( | |
| 136 ... "http://some.svn.server/svn/repo/../other/repo/../../other_repo") | |
| 137 'http://some.svn.server/svn/other_repo' | |
| 138 >>> # Another Complex One | |
| 139 >>> resolvedots( | |
| 140 ... "http://some.svn.server/svn/repo/dir/subdir/../../../other_repo/dir") | |
| 141 'http://some.svn.server/svn/other_repo/dir' | |
| 142 >>> # Last Complex One - SVN Allows this & seen it used even if it is BAD! | |
| 143 >>> resolvedots( | |
| 144 ... "http://svn.server/svn/my_repo/dir/subdir/../../other_dir") | |
| 145 'http://svn.server/svn/my_repo/other_dir' | |
| 146 >>> # Outside the SVN Area might be OK | |
| 147 >>> resolvedots( | |
| 148 ... "http://svn.server/svn/some_repo/../../other_svn_repo") | |
| 149 'http://svn.server/other_svn_repo' | |
| 150 >>> # Complex One | |
| 151 >>> resolvedots( | |
| 152 ... "http://some.svn.server/svn/repo/../other/repo/../../other_repo") | |
| 153 'http://some.svn.server/svn/other_repo' | |
| 154 >>> # On another server is not a relative URL should give an exception | |
| 155 >>> resolvedots( | |
| 156 ... "http://some.svn.server/svn/some_repo/../../../other_server") | |
| 157 Traceback (most recent call last): | |
| 158 ... | |
| 159 RelativeSourceError: Relative URL cannot be to another server | |
| 128 """ | 160 """ |
| 129 orig = url.split('/') | 161 orig = url.split('/') |
| 130 fixed = [] | 162 fixed = [] |
| 131 for item in orig: | 163 for item in orig: |
| 132 if item != '..': | 164 if item != '..': |
| 133 fixed.append(item) | 165 fixed.append(item) |
| 134 elif len(fixed) > 2: # Don't allow things to go out of domain | 166 elif len(fixed) > 3: # Don't allow things to go out of domain |
| 135 fixed.pop() | 167 fixed.pop() |
| 136 else: | 168 else: |
| 137 raise RelativeSourceError() | 169 raise RelativeSourceError( |
| 170 'Relative URL cannot be to another server') | |
| 138 return '/'.join(fixed) | 171 return '/'.join(fixed) |
| 139 | 172 |
| 173 | |
| 174 | |
| 140 def resolvesource(ui, svnroot, source): | 175 def resolvesource(ui, svnroot, source): |
| 176 """ Resolve the source as either matching the scheme re or by resolving | |
| 177 relative URLs which start with ^ and my include relative .. references. | |
| 178 | |
| 179 >>> root = 'http://some.svn.server/svn/some_repo' | |
| 180 >>> resolvesource(None, root, 'http://other.svn.server') | |
| 181 'http://other.svn.server' | |
| 182 >>> resolvesource(None, root, 'ssh://other.svn.server') | |
| 183 'ssh://other.svn.server' | |
| 184 >>> resolvesource(None, root, '^/other_repo') | |
| 185 'http://some.svn.server/svn/some_repo/other_repo' | |
| 186 >>> resolvesource(None, root, '^/sub_repo') | |
| 187 'http://some.svn.server/svn/some_repo/sub_repo' | |
| 188 >>> resolvesource(None, root, '^/../other_repo') | |
| 189 'http://some.svn.server/svn/other_repo' | |
| 190 >>> resolvesource(None, root, '^/../../../server/other_repo') | |
| 191 Traceback (most recent call last): | |
| 192 ... | |
| 193 RelativeSourceError: Relative URL cannot be to another server | |
| 194 """ | |
| 141 if re_scheme.search(source): | 195 if re_scheme.search(source): |
| 142 return source | 196 return source |
| 143 if source.startswith('^/'): | 197 if source.startswith('^/'): |
| 144 if svnroot is None: | 198 if svnroot is None: |
| 145 raise RelativeSourceError() | 199 raise RelativeSourceError() |
| 455 def basestate(self): | 509 def basestate(self): |
| 456 # basestate() was introduced by bcb973abcc0b in 2.2 | 510 # basestate() was introduced by bcb973abcc0b in 2.2 |
| 457 if self._state[1] == 'HEAD': | 511 if self._state[1] == 'HEAD': |
| 458 return 'HEAD' | 512 return 'HEAD' |
| 459 return super(svnsubrepo, self).basestate() | 513 return super(svnsubrepo, self).basestate() |
| 514 | |
| 515 if __name__ == "__main__": | |
| 516 import doctest | |
| 517 doctest.testmod() |
