48 mod = '' |
48 mod = '' |
49 if len(parts) > 1: |
49 if len(parts) > 1: |
50 mod = '/' + parts[1] |
50 mod = '/' + parts[1] |
51 return parts[0][4:], mod, int(revnum) |
51 return parts[0][4:], mod, int(revnum) |
52 |
52 |
|
53 def quote(s): |
|
54 # As of svn 1.7, many svn calls expect "canonical" paths. In |
|
55 # theory, we should call svn.core.*canonicalize() on all paths |
|
56 # before passing them to the API. Instead, we assume the base url |
|
57 # is canonical and copy the behaviour of svn URL encoding function |
|
58 # so we can extend it safely with new components. The "safe" |
|
59 # characters were taken from the "svn_uri__char_validity" table in |
|
60 # libsvn_subr/path.c. |
|
61 return urllib.quote(s, "!$&'()*+,-./:=@_~") |
|
62 |
53 def geturl(path): |
63 def geturl(path): |
54 try: |
64 try: |
55 return svn.client.url_from_path(svn.core.svn_path_canonicalize(path)) |
65 return svn.client.url_from_path(svn.core.svn_path_canonicalize(path)) |
56 except SubversionException: |
66 except SubversionException: |
|
67 # svn.client.url_from_path() fails with local repositories |
57 pass |
68 pass |
58 if os.path.isdir(path): |
69 if os.path.isdir(path): |
59 path = os.path.normpath(os.path.abspath(path)) |
70 path = os.path.normpath(os.path.abspath(path)) |
60 if os.name == 'nt': |
71 if os.name == 'nt': |
61 path = '/' + util.normpath(path) |
72 path = '/' + util.normpath(path) |
62 # Module URL is later compared with the repository URL returned |
73 # Module URL is later compared with the repository URL returned |
63 # by svn API, which is UTF-8. |
74 # by svn API, which is UTF-8. |
64 path = encoding.tolocal(path) |
75 path = encoding.tolocal(path) |
65 return 'file://%s' % urllib.quote(path) |
76 path = 'file://%s' % quote(path) |
66 return path |
77 return svn.core.svn_path_canonicalize(path) |
67 |
78 |
68 def optrev(number): |
79 def optrev(number): |
69 optrev = svn.core.svn_opt_revision_t() |
80 optrev = svn.core.svn_opt_revision_t() |
70 optrev.kind = svn.core.svn_opt_revision_number |
81 optrev.kind = svn.core.svn_opt_revision_number |
71 optrev.value.number = number |
82 optrev.value.number = number |
304 lastrevs[module] = revnum |
315 lastrevs[module] = revnum |
305 self.lastrevs = lastrevs |
316 self.lastrevs = lastrevs |
306 |
317 |
307 def exists(self, path, optrev): |
318 def exists(self, path, optrev): |
308 try: |
319 try: |
309 svn.client.ls(self.url.rstrip('/') + '/' + urllib.quote(path), |
320 svn.client.ls(self.url.rstrip('/') + '/' + quote(path), |
310 optrev, False, self.ctx) |
321 optrev, False, self.ctx) |
311 return True |
322 return True |
312 except SubversionException: |
323 except SubversionException: |
313 return False |
324 return False |
314 |
325 |
356 self.tags = '%s/%s' % (oldmodule , (self.tags or 'tags')) |
367 self.tags = '%s/%s' % (oldmodule , (self.tags or 'tags')) |
357 |
368 |
358 # Check if branches bring a few more heads to the list |
369 # Check if branches bring a few more heads to the list |
359 if branches: |
370 if branches: |
360 rpath = self.url.strip('/') |
371 rpath = self.url.strip('/') |
361 branchnames = svn.client.ls(rpath + '/' + urllib.quote(branches), |
372 branchnames = svn.client.ls(rpath + '/' + quote(branches), |
362 rev, False, self.ctx) |
373 rev, False, self.ctx) |
363 for branch in branchnames.keys(): |
374 for branch in branchnames.keys(): |
364 module = '%s/%s/%s' % (oldmodule, branches, branch) |
375 module = '%s/%s/%s' % (oldmodule, branches, branch) |
365 if not isdir(module, self.last_changed): |
376 if not isdir(module, self.last_changed): |
366 continue |
377 continue |
392 if parents: |
403 if parents: |
393 files, self.removed, copies = self.expandpaths(rev, paths, parents) |
404 files, self.removed, copies = self.expandpaths(rev, paths, parents) |
394 else: |
405 else: |
395 # Perform a full checkout on roots |
406 # Perform a full checkout on roots |
396 uuid, module, revnum = revsplit(rev) |
407 uuid, module, revnum = revsplit(rev) |
397 entries = svn.client.ls(self.baseurl + urllib.quote(module), |
408 entries = svn.client.ls(self.baseurl + quote(module), |
398 optrev(revnum), True, self.ctx) |
409 optrev(revnum), True, self.ctx) |
399 files = [n for n, e in entries.iteritems() |
410 files = [n for n, e in entries.iteritems() |
400 if e.kind == svn.core.svn_node_file] |
411 if e.kind == svn.core.svn_node_file] |
401 copies = {} |
412 copies = {} |
402 self.removed = set() |
413 self.removed = set() |
593 |
604 |
594 def reparent(self, module): |
605 def reparent(self, module): |
595 """Reparent the svn transport and return the previous parent.""" |
606 """Reparent the svn transport and return the previous parent.""" |
596 if self.prevmodule == module: |
607 if self.prevmodule == module: |
597 return module |
608 return module |
598 svnurl = self.baseurl + urllib.quote(module) |
609 svnurl = self.baseurl + quote(module) |
599 prevmodule = self.prevmodule |
610 prevmodule = self.prevmodule |
600 if prevmodule is None: |
611 if prevmodule is None: |
601 prevmodule = '' |
612 prevmodule = '' |
602 self.ui.debug("reparent to %s\n" % svnurl) |
613 self.ui.debug("reparent to %s\n" % svnurl) |
603 svn.ra.reparent(self.ra, svnurl) |
614 svn.ra.reparent(self.ra, svnurl) |
864 |
875 |
865 def _iterfiles(self, path, revnum): |
876 def _iterfiles(self, path, revnum): |
866 """Enumerate all files in path at revnum, recursively.""" |
877 """Enumerate all files in path at revnum, recursively.""" |
867 path = path.strip('/') |
878 path = path.strip('/') |
868 pool = Pool() |
879 pool = Pool() |
869 rpath = '/'.join([self.baseurl, urllib.quote(path)]).strip('/') |
880 rpath = '/'.join([self.baseurl, quote(path)]).strip('/') |
870 entries = svn.client.ls(rpath, optrev(revnum), True, self.ctx, pool) |
881 entries = svn.client.ls(rpath, optrev(revnum), True, self.ctx, pool) |
871 if path: |
882 if path: |
872 path += '/' |
883 path += '/' |
873 return ((path + p) for p, e in entries.iteritems() |
884 return ((path + p) for p, e in entries.iteritems() |
874 if e.kind == svn.core.svn_node_file) |
885 if e.kind == svn.core.svn_node_file) |