diff options
Diffstat (limited to 'repo')
-rwxr-xr-x | repo | 103 |
1 files changed, 80 insertions, 23 deletions
@@ -475,13 +475,7 @@ def _Init(args, gitc_init=False): | |||
475 | opt.verbose = opt.output_mode is True | 475 | opt.verbose = opt.output_mode is True |
476 | 476 | ||
477 | url = opt.repo_url or REPO_URL | 477 | url = opt.repo_url or REPO_URL |
478 | branch = opt.repo_rev or REPO_REV | 478 | rev = opt.repo_rev or REPO_REV |
479 | |||
480 | if branch.startswith('refs/heads/'): | ||
481 | branch = branch[len('refs/heads/'):] | ||
482 | if branch.startswith('refs/'): | ||
483 | print("fatal: invalid branch name '%s'" % branch, file=sys.stderr) | ||
484 | raise CloneFailure() | ||
485 | 479 | ||
486 | try: | 480 | try: |
487 | if gitc_init: | 481 | if gitc_init: |
@@ -532,12 +526,15 @@ def _Init(args, gitc_init=False): | |||
532 | dst = os.path.abspath(os.path.join(repodir, S_repo)) | 526 | dst = os.path.abspath(os.path.join(repodir, S_repo)) |
533 | _Clone(url, dst, opt.clone_bundle, opt.quiet, opt.verbose) | 527 | _Clone(url, dst, opt.clone_bundle, opt.quiet, opt.verbose) |
534 | 528 | ||
529 | remote_ref, local_rev = resolve_repo_rev(dst, rev) | ||
530 | if not opt.quiet and not remote_ref.startswith('refs/heads/'): | ||
531 | print('warning: repo is not tracking a remote branch, so it will not ' | ||
532 | 'receive updates', file=sys.stderr) | ||
535 | if do_verify: | 533 | if do_verify: |
536 | rev = _Verify(dst, branch, opt.quiet) | 534 | rev = _Verify(dst, remote_ref, local_rev, opt.quiet) |
537 | else: | 535 | else: |
538 | rev = 'refs/remotes/origin/%s^0' % branch | 536 | rev = local_rev |
539 | 537 | _Checkout(dst, remote_ref, rev, opt.quiet) | |
540 | _Checkout(dst, branch, rev, opt.quiet) | ||
541 | 538 | ||
542 | if not os.path.isfile(os.path.join(dst, 'repo')): | 539 | if not os.path.isfile(os.path.join(dst, 'repo')): |
543 | print("warning: '%s' does not look like a git-repo repository, is " | 540 | print("warning: '%s' does not look like a git-repo repository, is " |
@@ -845,23 +842,83 @@ def _Clone(url, cwd, clone_bundle, quiet, verbose): | |||
845 | _Fetch(url, cwd, 'origin', quiet, verbose) | 842 | _Fetch(url, cwd, 'origin', quiet, verbose) |
846 | 843 | ||
847 | 844 | ||
848 | def _Verify(cwd, branch, quiet): | 845 | def resolve_repo_rev(cwd, committish): |
849 | """Verify the branch has been signed by a tag. | 846 | """Figure out what REPO_REV represents. |
847 | |||
848 | We support: | ||
849 | * refs/heads/xxx: Branch. | ||
850 | * refs/tags/xxx: Tag. | ||
851 | * xxx: Branch or tag or commit. | ||
852 | |||
853 | Args: | ||
854 | cwd: The git checkout to run in. | ||
855 | committish: The REPO_REV argument to resolve. | ||
856 | |||
857 | Returns: | ||
858 | A tuple of (remote ref, commit) as makes sense for the committish. | ||
859 | For branches, this will look like ('refs/heads/stable', <revision>). | ||
860 | For tags, this will look like ('refs/tags/v1.0', <revision>). | ||
861 | For commits, this will be (<revision>, <revision>). | ||
850 | """ | 862 | """ |
851 | try: | 863 | def resolve(committish): |
852 | ret = run_git('describe', 'origin/%s' % branch, cwd=cwd) | 864 | ret = run_git('rev-parse', '--verify', '%s^{commit}' % (committish,), |
853 | cur = ret.stdout.strip() | 865 | cwd=cwd, check=False) |
854 | except CloneFailure: | 866 | return None if ret.returncode else ret.stdout.strip() |
855 | print("fatal: branch '%s' has not been signed" % branch, file=sys.stderr) | 867 | |
856 | raise | 868 | # An explicit branch. |
869 | if committish.startswith('refs/heads/'): | ||
870 | remote_ref = committish | ||
871 | committish = committish[len('refs/heads/'):] | ||
872 | rev = resolve('refs/remotes/origin/%s' % committish) | ||
873 | if rev is None: | ||
874 | print('repo: error: unknown branch "%s"' % (committish,), | ||
875 | file=sys.stderr) | ||
876 | raise CloneFailure() | ||
877 | return (remote_ref, rev) | ||
878 | |||
879 | # An explicit tag. | ||
880 | if committish.startswith('refs/tags/'): | ||
881 | remote_ref = committish | ||
882 | committish = committish[len('refs/tags/'):] | ||
883 | rev = resolve(remote_ref) | ||
884 | if rev is None: | ||
885 | print('repo: error: unknown tag "%s"' % (committish,), | ||
886 | file=sys.stderr) | ||
887 | raise CloneFailure() | ||
888 | return (remote_ref, rev) | ||
889 | |||
890 | # See if it's a short branch name. | ||
891 | rev = resolve('refs/remotes/origin/%s' % committish) | ||
892 | if rev: | ||
893 | return ('refs/heads/%s' % (committish,), rev) | ||
894 | |||
895 | # See if it's a tag. | ||
896 | rev = resolve('refs/tags/%s' % committish) | ||
897 | if rev: | ||
898 | return ('refs/tags/%s' % (committish,), rev) | ||
899 | |||
900 | # See if it's a commit. | ||
901 | rev = resolve(committish) | ||
902 | if rev and rev.lower().startswith(committish.lower()): | ||
903 | return (rev, rev) | ||
904 | |||
905 | # Give up! | ||
906 | print('repo: error: unable to resolve "%s"' % (committish,), file=sys.stderr) | ||
907 | raise CloneFailure() | ||
908 | |||
909 | |||
910 | def _Verify(cwd, remote_ref, rev, quiet): | ||
911 | """Verify the commit has been signed by a tag.""" | ||
912 | ret = run_git('describe', rev, cwd=cwd) | ||
913 | cur = ret.stdout.strip() | ||
857 | 914 | ||
858 | m = re.compile(r'^(.*)-[0-9]{1,}-g[0-9a-f]{1,}$').match(cur) | 915 | m = re.compile(r'^(.*)-[0-9]{1,}-g[0-9a-f]{1,}$').match(cur) |
859 | if m: | 916 | if m: |
860 | cur = m.group(1) | 917 | cur = m.group(1) |
861 | if not quiet: | 918 | if not quiet: |
862 | print(file=sys.stderr) | 919 | print(file=sys.stderr) |
863 | print("info: Ignoring branch '%s'; using tagged release '%s'" | 920 | print("warning: '%s' is not signed; falling back to signed release '%s'" |
864 | % (branch, cur), file=sys.stderr) | 921 | % (remote_ref, cur), file=sys.stderr) |
865 | print(file=sys.stderr) | 922 | print(file=sys.stderr) |
866 | 923 | ||
867 | env = os.environ.copy() | 924 | env = os.environ.copy() |
@@ -870,13 +927,13 @@ def _Verify(cwd, branch, quiet): | |||
870 | return '%s^0' % cur | 927 | return '%s^0' % cur |
871 | 928 | ||
872 | 929 | ||
873 | def _Checkout(cwd, branch, rev, quiet): | 930 | def _Checkout(cwd, remote_ref, rev, quiet): |
874 | """Checkout an upstream branch into the repository and track it. | 931 | """Checkout an upstream branch into the repository and track it. |
875 | """ | 932 | """ |
876 | run_git('update-ref', 'refs/heads/default', rev, cwd=cwd) | 933 | run_git('update-ref', 'refs/heads/default', rev, cwd=cwd) |
877 | 934 | ||
878 | _SetConfig(cwd, 'branch.default.remote', 'origin') | 935 | _SetConfig(cwd, 'branch.default.remote', 'origin') |
879 | _SetConfig(cwd, 'branch.default.merge', 'refs/heads/%s' % branch) | 936 | _SetConfig(cwd, 'branch.default.merge', remote_ref) |
880 | 937 | ||
881 | run_git('symbolic-ref', 'HEAD', 'refs/heads/default', cwd=cwd) | 938 | run_git('symbolic-ref', 'HEAD', 'refs/heads/default', cwd=cwd) |
882 | 939 | ||