|
26 | 26 | from .constants import RE_PIP_REV, RE_SCP, RE_USER |
27 | 27 |
|
28 | 28 | RE_PATH = r""" |
29 | | - (?P<hostname>([^/:]+)) |
| 29 | + (?P<hostname>([^/:@]+)) |
30 | 30 | (:(?P<port>\d{1,5}))? |
31 | 31 | (?P<separator>[:,/])? |
32 | 32 | (?P<path> |
|
108 | 108 | ) |
109 | 109 | """ |
110 | 110 |
|
| 111 | +AWS_CODE_COMMIT_DEFAULT_RULES: list[Rule] = [ |
| 112 | + Rule( |
| 113 | + label="aws-code-commit-https", |
| 114 | + description="AWS CodeCommit HTTPS-style", |
| 115 | + pattern=re.compile( |
| 116 | + rf""" |
| 117 | + https://git-codecommit\. |
| 118 | + ((?P<region>[^/]+)\.) |
| 119 | + # Server, e.g. 'github.com'. |
| 120 | + (?P<hostname>([^/:]+)) |
| 121 | + (?P<separator>:)? |
| 122 | + # The server-side path. e.g. 'user/project.git'. Must start with an |
| 123 | + # alphanumeric character so as not to be confusable with a Windows paths |
| 124 | + # like 'C:/foo/bar' or 'C:\foo\bar'. |
| 125 | + (?P<path>(\w[^:.]+))? |
| 126 | + {RE_PIP_REV}? |
| 127 | + """, |
| 128 | + re.VERBOSE, |
| 129 | + ), |
| 130 | + is_explicit=True, |
| 131 | + ), |
| 132 | + Rule( |
| 133 | + label="aws-code-commit-ssh", |
| 134 | + description="AWS CodeCommit SSH-style", |
| 135 | + pattern=re.compile( |
| 136 | + rf""" |
| 137 | + ssh://git-codecommit\. |
| 138 | + ((?P<region>[^/]+)\.) |
| 139 | + # Server, e.g. 'github.com'. |
| 140 | + (?P<hostname>([^/:]+)) |
| 141 | + (?P<separator>:)? |
| 142 | + # The server-side path. e.g. 'user/project.git'. Must start with an |
| 143 | + # alphanumeric character so as not to be confusable with a Windows paths |
| 144 | + # like 'C:/foo/bar' or 'C:\foo\bar'. |
| 145 | + (?P<path>(\w[^:.]+))? |
| 146 | + {RE_PIP_REV}? |
| 147 | + """, |
| 148 | + re.VERBOSE, |
| 149 | + ), |
| 150 | + is_explicit=True, |
| 151 | + ), |
| 152 | + Rule( |
| 153 | + label="aws-code-commit-https-grc", |
| 154 | + description="AWS CodeCommit git repository", |
| 155 | + pattern=re.compile( |
| 156 | + rf""" |
| 157 | + codecommit:// |
| 158 | + {RE_PATH} |
| 159 | + {RE_PIP_REV}? |
| 160 | + """, |
| 161 | + re.VERBOSE, |
| 162 | + ), |
| 163 | + is_explicit=True, |
| 164 | + weight=0, |
| 165 | + ), |
| 166 | + Rule( |
| 167 | + label="aws-code-commit-https-grc-with-region", |
| 168 | + description="AWS CodeCommit git repository with region", |
| 169 | + pattern=re.compile( |
| 170 | + rf""" |
| 171 | + codecommit:: |
| 172 | + (?P<region>[^/]+) |
| 173 | + :// |
| 174 | + {RE_PATH} |
| 175 | + {RE_PIP_REV}? |
| 176 | + """, |
| 177 | + re.VERBOSE, |
| 178 | + ), |
| 179 | + is_explicit=True, |
| 180 | + weight=0, |
| 181 | + ), |
| 182 | +] |
| 183 | +"""AWS CodeCommit-style git URLs. |
| 184 | +
|
| 185 | +Examples of CodeCommit-style git URLs (via AWS):: |
| 186 | +
|
| 187 | + codecommit://MyDemoRepo |
| 188 | + codecommit://`CodeCommitProfile`@MyDemoRepo |
| 189 | + codecommit::ap-northeast-1://MyDemoRepo |
| 190 | +
|
| 191 | +Notes |
| 192 | +----- |
| 193 | +
|
| 194 | +- https://aws.amazon.com/codecommit/ |
| 195 | +- https://docs.aws.amazon.com/codecommit/ |
| 196 | +- https://docs.aws.amazon.com/codecommit/latest/userguide/setting-up-git-remote-codecommit.html#:~:text=For%20example%2C%20to%20clone%20a%20repository%20named |
| 197 | +""" |
| 198 | + |
| 199 | + |
111 | 200 | PIP_DEFAULT_RULES: list[Rule] = [ |
112 | 201 | Rule( |
113 | 202 | label="pip-url", |
@@ -363,6 +452,141 @@ def to_url(self) -> str: |
363 | 452 | return "".join(part for part in parts if isinstance(part, str)) |
364 | 453 |
|
365 | 454 |
|
| 455 | +@dataclasses.dataclass(repr=False) |
| 456 | +class GitAWSCodeCommitURL( |
| 457 | + GitBaseURL, |
| 458 | + URLProtocol, |
| 459 | + SkipDefaultFieldsReprMixin, |
| 460 | +): |
| 461 | + """Supports AWS CodeCommit git URLs.""" |
| 462 | + |
| 463 | + # AWS CodeCommit Region |
| 464 | + region: Optional[str] = None |
| 465 | + # commit-ish (rev): tag, branch, ref |
| 466 | + rev: Optional[str] = None |
| 467 | + |
| 468 | + rule_map = RuleMap(_rule_map={m.label: m for m in AWS_CODE_COMMIT_DEFAULT_RULES}) |
| 469 | + |
| 470 | + def to_url(self) -> str: |
| 471 | + """Export AWS CodeCommit-compliant URL. |
| 472 | +
|
| 473 | + Examples |
| 474 | + -------- |
| 475 | + HTTPS (GRC, a.k.a. git-remote-codecommit) URL: |
| 476 | +
|
| 477 | + >>> git_url = GitAWSCodeCommitURL( |
| 478 | + ... url='codecommit://test' |
| 479 | + ... ) |
| 480 | +
|
| 481 | + >>> git_url |
| 482 | + GitAWSCodeCommitURL(url=codecommit://test, |
| 483 | + hostname=test, |
| 484 | + rule=aws-code-commit-https-grc) |
| 485 | +
|
| 486 | + >>> git_url = GitAWSCodeCommitURL( |
| 487 | + ... url='codecommit::us-east-1://test' |
| 488 | + ... ) |
| 489 | +
|
| 490 | + >>> git_url |
| 491 | + GitAWSCodeCommitURL(url=codecommit::us-east-1://test, |
| 492 | + hostname=test, |
| 493 | + rule=aws-code-commit-https-grc-with-region, |
| 494 | + region=us-east-1) |
| 495 | +
|
| 496 | + >>> git_url.path = 'libvcs/vcspull' |
| 497 | +
|
| 498 | + >>> git_url.to_url() |
| 499 | + 'codecommit::us-east-1://libvcs/vcspull' |
| 500 | +
|
| 501 | + It also accepts revisions, e.g. branch, tag, ref: |
| 502 | +
|
| 503 | + >>> git_url = GitAWSCodeCommitURL( |
| 504 | + ... url='codecommit::us-east-1://test@v0.10.0' |
| 505 | + ... ) |
| 506 | +
|
| 507 | + >>> git_url |
| 508 | + GitAWSCodeCommitURL(url=codecommit::us-east-1://test@v0.10.0, |
| 509 | + hostname=test, |
| 510 | + rule=aws-code-commit-https-grc-with-region, |
| 511 | + region=us-east-1, |
| 512 | + rev=v0.10.0) |
| 513 | +
|
| 514 | + >>> git_url.path = 'libvcs/vcspull' |
| 515 | +
|
| 516 | + >>> git_url.to_url() |
| 517 | + 'codecommit::us-east-1://libvcs/vcspull@v0.10.0' |
| 518 | + """ |
| 519 | + url = super().to_url() |
| 520 | + |
| 521 | + """Return an AWS CodeCommit-compatible URL.""" |
| 522 | + |
| 523 | + if isinstance(self.rule, str) and self.rule.startswith( |
| 524 | + "aws-code-commit-https-grc", |
| 525 | + ): |
| 526 | + if self.region: |
| 527 | + url = f"codecommit::{self.region}://{self.path}" |
| 528 | + elif self.user: |
| 529 | + url = f"codecommit://{self.user}@{self.path}" |
| 530 | + else: |
| 531 | + url = f"codecommit://{self.path}" |
| 532 | + |
| 533 | + if self.rev: |
| 534 | + url = f"{url}@{self.rev}" |
| 535 | + return url |
| 536 | + |
| 537 | + @classmethod |
| 538 | + def is_valid(cls, url: str, is_explicit: Optional[bool] = None) -> bool: |
| 539 | + """Whether URL is compatible with AWS CodeCommit Git's VCS URL pattern or not. |
| 540 | +
|
| 541 | + Examples |
| 542 | + -------- |
| 543 | + Will **not** match normal ``git(1)`` URLs, use :meth:`GitURL.is_valid` for that. |
| 544 | +
|
| 545 | + >>> GitAWSCodeCommitURL.is_valid(url='https://github.com/vcs-python/libvcs.git') |
| 546 | + False |
| 547 | +
|
| 548 | + >>> GitAWSCodeCommitURL.is_valid(url='git@github.com:vcs-python/libvcs.git') |
| 549 | + False |
| 550 | +
|
| 551 | + AWS CodeCommit HTTPS URL: |
| 552 | +
|
| 553 | + >>> GitAWSCodeCommitURL.is_valid( |
| 554 | + ... url='https://git-codecommit.us-east-1.amazonaws.com/v1/repos/test', |
| 555 | + ... ) |
| 556 | + True |
| 557 | +
|
| 558 | + AWS CodeCommit HTTPS (GRC) URLs: |
| 559 | +
|
| 560 | + >>> GitAWSCodeCommitURL.is_valid(url='codecommit::ap-northeast-1://MyDemoRepo') |
| 561 | + True |
| 562 | +
|
| 563 | + >>> GitAWSCodeCommitURL.is_valid(url='codecommit://MyDemoRepo') |
| 564 | + True |
| 565 | +
|
| 566 | + AWS CodeCommit SSH URL: |
| 567 | +
|
| 568 | + >>> GitAWSCodeCommitURL.is_valid( |
| 569 | + ... url='ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/test', |
| 570 | + ... ) |
| 571 | + True |
| 572 | +
|
| 573 | + >>> GitAWSCodeCommitURL.is_valid(url='notaurl') |
| 574 | + False |
| 575 | +
|
| 576 | + **Explicit VCS detection** |
| 577 | +
|
| 578 | + AWS CodeCommit-style URLs are prefixed with the VCS name in front, so its |
| 579 | + `rule_map` can unambiguously narrow the type of VCS: |
| 580 | +
|
| 581 | + >>> GitAWSCodeCommitURL.is_valid( |
| 582 | + ... url='ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/test', |
| 583 | + ... is_explicit=True, |
| 584 | + ... ) |
| 585 | + True |
| 586 | + """ |
| 587 | + return super().is_valid(url=url, is_explicit=is_explicit) |
| 588 | + |
| 589 | + |
366 | 590 | @dataclasses.dataclass(repr=False) |
367 | 591 | class GitPipURL( |
368 | 592 | GitBaseURL, |
|
0 commit comments