445 return bytes(u) |
445 return bytes(u) |
446 |
446 |
447 |
447 |
448 def list_paths(ui, target_path=None): |
448 def list_paths(ui, target_path=None): |
449 """list all the (name, paths) in the passed ui""" |
449 """list all the (name, paths) in the passed ui""" |
|
450 result = [] |
450 if target_path is None: |
451 if target_path is None: |
451 return sorted(pycompat.iteritems(ui.paths)) |
452 for name, paths in sorted(pycompat.iteritems(ui.paths)): |
|
453 for p in paths: |
|
454 result.append((name, p)) |
|
455 |
452 else: |
456 else: |
453 path = ui.paths.get(target_path) |
457 for path in ui.paths.get(target_path, []): |
454 if path is None: |
458 result.append((target_path, path)) |
455 return [] |
459 return result |
456 else: |
|
457 return [(target_path, path)] |
|
458 |
460 |
459 |
461 |
460 def try_path(ui, url): |
462 def try_path(ui, url): |
461 """try to build a path from a url |
463 """try to build a path from a url |
462 |
464 |
471 |
473 |
472 def get_push_paths(repo, ui, dests): |
474 def get_push_paths(repo, ui, dests): |
473 """yields all the `path` selected as push destination by `dests`""" |
475 """yields all the `path` selected as push destination by `dests`""" |
474 if not dests: |
476 if not dests: |
475 if b'default-push' in ui.paths: |
477 if b'default-push' in ui.paths: |
476 yield ui.paths[b'default-push'] |
478 for p in ui.paths[b'default-push']: |
|
479 yield p |
477 elif b'default' in ui.paths: |
480 elif b'default' in ui.paths: |
478 yield ui.paths[b'default'] |
481 for p in ui.paths[b'default']: |
|
482 yield p |
479 else: |
483 else: |
480 raise error.ConfigError( |
484 raise error.ConfigError( |
481 _(b'default repository not configured!'), |
485 _(b'default repository not configured!'), |
482 hint=_(b"see 'hg help config.paths'"), |
486 hint=_(b"see 'hg help config.paths'"), |
483 ) |
487 ) |
484 else: |
488 else: |
485 for dest in dests: |
489 for dest in dests: |
486 if dest in ui.paths: |
490 if dest in ui.paths: |
487 yield ui.paths[dest] |
491 for p in ui.paths[dest]: |
|
492 yield p |
488 else: |
493 else: |
489 path = try_path(ui, dest) |
494 path = try_path(ui, dest) |
490 if path is None: |
495 if path is None: |
491 msg = _(b'repository %s does not exist') |
496 msg = _(b'repository %s does not exist') |
492 msg %= dest |
497 msg %= dest |
498 """yields all the `(path, branch)` selected as pull source by `sources`""" |
503 """yields all the `(path, branch)` selected as pull source by `sources`""" |
499 if not sources: |
504 if not sources: |
500 sources = [b'default'] |
505 sources = [b'default'] |
501 for source in sources: |
506 for source in sources: |
502 if source in ui.paths: |
507 if source in ui.paths: |
503 url = ui.paths[source].rawloc |
508 for p in ui.paths[source]: |
|
509 yield parseurl(p.rawloc, default_branches) |
504 else: |
510 else: |
505 # Try to resolve as a local path or URI. |
511 # Try to resolve as a local path or URI. |
506 path = try_path(ui, source) |
512 path = try_path(ui, source) |
507 if path is not None: |
513 if path is not None: |
508 url = path.rawloc |
514 url = path.rawloc |
509 else: |
515 else: |
510 url = source |
516 url = source |
511 yield parseurl(url, default_branches) |
517 yield parseurl(url, default_branches) |
512 |
518 |
513 |
519 |
514 def get_unique_push_path(action, repo, ui, dest=None): |
520 def get_unique_push_path(action, repo, ui, dest=None): |
515 """return a unique `path` or abort if multiple are found |
521 """return a unique `path` or abort if multiple are found |
516 |
522 |
524 if dest is None: |
530 if dest is None: |
525 dests = [] |
531 dests = [] |
526 else: |
532 else: |
527 dests = [dest] |
533 dests = [dest] |
528 dests = list(get_push_paths(repo, ui, dests)) |
534 dests = list(get_push_paths(repo, ui, dests)) |
529 assert len(dests) == 1 |
535 if len(dests) != 1: |
|
536 if dest is None: |
|
537 msg = _("default path points to %d urls while %s only supports one") |
|
538 msg %= (len(dests), action) |
|
539 else: |
|
540 msg = _("path points to %d urls while %s only supports one: %s") |
|
541 msg %= (len(dests), action, dest) |
|
542 raise error.Abort(msg) |
530 return dests[0] |
543 return dests[0] |
531 |
544 |
532 |
545 |
533 def get_unique_pull_path(action, repo, ui, source=None, default_branches=()): |
546 def get_unique_pull_path(action, repo, ui, source=None, default_branches=()): |
534 """return a unique `(path, branch)` or abort if multiple are found |
547 """return a unique `(path, branch)` or abort if multiple are found |
538 |
551 |
539 Note that for now, we cannot get multiple destination so this function is "trivial". |
552 Note that for now, we cannot get multiple destination so this function is "trivial". |
540 |
553 |
541 The `action` parameter will be used for the error message. |
554 The `action` parameter will be used for the error message. |
542 """ |
555 """ |
|
556 urls = [] |
543 if source is None: |
557 if source is None: |
544 if b'default' in ui.paths: |
558 if b'default' in ui.paths: |
545 url = ui.paths[b'default'].rawloc |
559 urls.extend(p.rawloc for p in ui.paths[b'default']) |
546 else: |
560 else: |
547 # XXX this is the historical default behavior, but that is not |
561 # XXX this is the historical default behavior, but that is not |
548 # great, consider breaking BC on this. |
562 # great, consider breaking BC on this. |
549 url = b'default' |
563 urls.append(b'default') |
550 else: |
564 else: |
551 if source in ui.paths: |
565 if source in ui.paths: |
552 url = ui.paths[source].rawloc |
566 urls.extend(p.rawloc for p in ui.paths[source]) |
553 else: |
567 else: |
554 # Try to resolve as a local path or URI. |
568 # Try to resolve as a local path or URI. |
555 path = try_path(ui, source) |
569 path = try_path(ui, source) |
556 if path is not None: |
570 if path is not None: |
557 url = path.rawloc |
571 urls.append(path.rawloc) |
558 else: |
572 else: |
559 url = source |
573 urls.append(source) |
560 return parseurl(url, default_branches) |
574 if len(urls) != 1: |
|
575 if source is None: |
|
576 msg = _("default path points to %d urls while %s only supports one") |
|
577 msg %= (len(urls), action) |
|
578 else: |
|
579 msg = _("path points to %d urls while %s only supports one: %s") |
|
580 msg %= (len(urls), action, source) |
|
581 raise error.Abort(msg) |
|
582 return parseurl(urls[0], default_branches) |
561 |
583 |
562 |
584 |
563 def get_clone_path(ui, source, default_branches=()): |
585 def get_clone_path(ui, source, default_branches=()): |
564 """return the `(origsource, path, branch)` selected as clone source""" |
586 """return the `(origsource, path, branch)` selected as clone source""" |
|
587 urls = [] |
565 if source is None: |
588 if source is None: |
566 if b'default' in ui.paths: |
589 if b'default' in ui.paths: |
567 url = ui.paths[b'default'].rawloc |
590 urls.extend(p.rawloc for p in ui.paths[b'default']) |
568 else: |
591 else: |
569 # XXX this is the historical default behavior, but that is not |
592 # XXX this is the historical default behavior, but that is not |
570 # great, consider breaking BC on this. |
593 # great, consider breaking BC on this. |
571 url = b'default' |
594 urls.append(b'default') |
572 else: |
595 else: |
573 if source in ui.paths: |
596 if source in ui.paths: |
574 url = ui.paths[source].rawloc |
597 urls.extend(p.rawloc for p in ui.paths[source]) |
575 else: |
598 else: |
576 # Try to resolve as a local path or URI. |
599 # Try to resolve as a local path or URI. |
577 path = try_path(ui, source) |
600 path = try_path(ui, source) |
578 if path is not None: |
601 if path is not None: |
579 url = path.rawloc |
602 urls.append(path.rawloc) |
580 else: |
603 else: |
581 url = source |
604 urls.append(source) |
|
605 if len(urls) != 1: |
|
606 if source is None: |
|
607 msg = _( |
|
608 "default path points to %d urls while only one is supported" |
|
609 ) |
|
610 msg %= len(urls) |
|
611 else: |
|
612 msg = _("path points to %d urls while only one is supported: %s") |
|
613 msg %= (len(urls), source) |
|
614 raise error.Abort(msg) |
|
615 url = urls[0] |
582 clone_path, branch = parseurl(url, default_branches) |
616 clone_path, branch = parseurl(url, default_branches) |
583 return url, clone_path, branch |
617 return url, clone_path, branch |
584 |
618 |
585 |
619 |
586 def parseurl(path, branches=None): |
620 def parseurl(path, branches=None): |
606 for name, loc in ui.configitems(b'paths', ignoresub=True): |
640 for name, loc in ui.configitems(b'paths', ignoresub=True): |
607 # No location is the same as not existing. |
641 # No location is the same as not existing. |
608 if not loc: |
642 if not loc: |
609 continue |
643 continue |
610 loc, sub_opts = ui.configsuboptions(b'paths', name) |
644 loc, sub_opts = ui.configsuboptions(b'paths', name) |
611 self[name] = path(ui, name, rawloc=loc, suboptions=sub_opts) |
645 self[name] = [path(ui, name, rawloc=loc, suboptions=sub_opts)] |
612 |
646 |
613 for name, p in sorted(self.items()): |
647 for name, old_paths in sorted(self.items()): |
614 self[name] = _chain_path(p, ui, self) |
648 new_paths = [] |
|
649 for p in old_paths: |
|
650 new_paths.extend(_chain_path(p, ui, self)) |
|
651 self[name] = new_paths |
615 |
652 |
616 def getpath(self, ui, name, default=None): |
653 def getpath(self, ui, name, default=None): |
617 """Return a ``path`` from a string, falling back to default. |
654 """Return a ``path`` from a string, falling back to default. |
618 |
655 |
619 ``name`` can be a named path or locations. Locations are filesystem |
656 ``name`` can be a named path or locations. Locations are filesystem |
702 @pathsuboption(b'pushrev', b'pushrev') |
739 @pathsuboption(b'pushrev', b'pushrev') |
703 def pushrevpathoption(ui, path, value): |
740 def pushrevpathoption(ui, path, value): |
704 return value |
741 return value |
705 |
742 |
706 |
743 |
707 def _chain_path(path, ui, paths): |
744 def _chain_path(base_path, ui, paths): |
708 """return the result of "path://" logic applied on a given path""" |
745 """return the result of "path://" logic applied on a given path""" |
709 if path.url.scheme == b'path': |
746 new_paths = [] |
710 assert path.url.path is None |
747 if base_path.url.scheme != b'path': |
711 subpath = paths.get(path.url.host) |
748 new_paths.append(base_path) |
712 if subpath is None: |
749 else: |
|
750 assert base_path.url.path is None |
|
751 sub_paths = paths.get(base_path.url.host) |
|
752 if sub_paths is None: |
713 m = _(b'cannot use `%s`, "%s" is not a known path') |
753 m = _(b'cannot use `%s`, "%s" is not a known path') |
714 m %= (path.rawloc, path.url.host) |
754 m %= (base_path.rawloc, base_path.url.host) |
715 raise error.Abort(m) |
755 raise error.Abort(m) |
716 if subpath.raw_url.scheme == b'path': |
756 for subpath in sub_paths: |
717 m = _(b'cannot use `%s`, "%s" is also defined as a `path://`') |
757 path = base_path.copy() |
718 m %= (path.rawloc, path.url.host) |
758 if subpath.raw_url.scheme == b'path': |
719 raise error.Abort(m) |
759 m = _(b'cannot use `%s`, "%s" is also defined as a `path://`') |
720 path.url = subpath.url |
760 m %= (path.rawloc, path.url.host) |
721 path.rawloc = subpath.rawloc |
761 raise error.Abort(m) |
722 path.loc = subpath.loc |
762 path.url = subpath.url |
723 if path.branch is None: |
763 path.rawloc = subpath.rawloc |
724 path.branch = subpath.branch |
764 path.loc = subpath.loc |
725 else: |
765 if path.branch is None: |
726 base = path.rawloc.rsplit(b'#', 1)[0] |
766 path.branch = subpath.branch |
727 path.rawloc = b'%s#%s' % (base, path.branch) |
767 else: |
728 suboptions = subpath._all_sub_opts.copy() |
768 base = path.rawloc.rsplit(b'#', 1)[0] |
729 suboptions.update(path._own_sub_opts) |
769 path.rawloc = b'%s#%s' % (base, path.branch) |
730 path._apply_suboptions(ui, suboptions) |
770 suboptions = subpath._all_sub_opts.copy() |
731 return path |
771 suboptions.update(path._own_sub_opts) |
|
772 path._apply_suboptions(ui, suboptions) |
|
773 new_paths.append(path) |
|
774 return new_paths |
732 |
775 |
733 |
776 |
734 class path(object): |
777 class path(object): |
735 """Represents an individual path and its configuration.""" |
778 """Represents an individual path and its configuration.""" |
736 |
779 |