diff options
| author | Gavin Mak <gavinmak@google.com> | 2023-03-11 06:46:20 +0000 |
|---|---|---|
| committer | LUCI <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-03-22 17:46:28 +0000 |
| commit | ea2e330e43c182dc16b0111ebc69ee5a71ee4ce1 (patch) | |
| tree | dc33ba0e56825b3e007d0589891756724725a465 /subcmds/download.py | |
| parent | 1604cf255f8c1786a23388db6d5277ac7949a24a (diff) | |
| download | git-repo-ea2e330e43c182dc16b0111ebc69ee5a71ee4ce1.tar.gz | |
Format codebase with black and check formatting in CQ
Apply rules set by https://gerrit-review.googlesource.com/c/git-repo/+/362954/ across the codebase and fix any lingering errors caught
by flake8. Also check black formatting in run_tests (and CQ).
Bug: b/267675342
Change-Id: I972d77649dac351150dcfeb1cd1ad0ea2efc1956
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/363474
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
Diffstat (limited to 'subcmds/download.py')
| -rw-r--r-- | subcmds/download.py | 304 |
1 files changed, 174 insertions, 130 deletions
diff --git a/subcmds/download.py b/subcmds/download.py index 15824843..d81d1f8c 100644 --- a/subcmds/download.py +++ b/subcmds/download.py | |||
| @@ -18,143 +18,187 @@ import sys | |||
| 18 | from command import Command | 18 | from command import Command |
| 19 | from error import GitError, NoSuchProjectError | 19 | from error import GitError, NoSuchProjectError |
| 20 | 20 | ||
| 21 | CHANGE_RE = re.compile(r'^([1-9][0-9]*)(?:[/\.-]([1-9][0-9]*))?$') | 21 | CHANGE_RE = re.compile(r"^([1-9][0-9]*)(?:[/\.-]([1-9][0-9]*))?$") |
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | class Download(Command): | 24 | class Download(Command): |
| 25 | COMMON = True | 25 | COMMON = True |
| 26 | helpSummary = "Download and checkout a change" | 26 | helpSummary = "Download and checkout a change" |
| 27 | helpUsage = """ | 27 | helpUsage = """ |
| 28 | %prog {[project] change[/patchset]}... | 28 | %prog {[project] change[/patchset]}... |
| 29 | """ | 29 | """ |
| 30 | helpDescription = """ | 30 | helpDescription = """ |
| 31 | The '%prog' command downloads a change from the review system and | 31 | The '%prog' command downloads a change from the review system and |
| 32 | makes it available in your project's local working directory. | 32 | makes it available in your project's local working directory. |
| 33 | If no project is specified try to use current directory as a project. | 33 | If no project is specified try to use current directory as a project. |
| 34 | """ | 34 | """ |
| 35 | 35 | ||
| 36 | def _Options(self, p): | 36 | def _Options(self, p): |
| 37 | p.add_option('-b', '--branch', | 37 | p.add_option("-b", "--branch", help="create a new branch first") |
| 38 | help='create a new branch first') | 38 | p.add_option( |
| 39 | p.add_option('-c', '--cherry-pick', | 39 | "-c", |
| 40 | dest='cherrypick', action='store_true', | 40 | "--cherry-pick", |
| 41 | help="cherry-pick instead of checkout") | 41 | dest="cherrypick", |
| 42 | p.add_option('-x', '--record-origin', action='store_true', | 42 | action="store_true", |
| 43 | help='pass -x when cherry-picking') | 43 | help="cherry-pick instead of checkout", |
| 44 | p.add_option('-r', '--revert', | 44 | ) |
| 45 | dest='revert', action='store_true', | 45 | p.add_option( |
| 46 | help="revert instead of checkout") | 46 | "-x", |
| 47 | p.add_option('-f', '--ff-only', | 47 | "--record-origin", |
| 48 | dest='ffonly', action='store_true', | 48 | action="store_true", |
| 49 | help="force fast-forward merge") | 49 | help="pass -x when cherry-picking", |
| 50 | 50 | ) | |
| 51 | def _ParseChangeIds(self, opt, args): | 51 | p.add_option( |
| 52 | if not args: | 52 | "-r", |
| 53 | self.Usage() | 53 | "--revert", |
| 54 | 54 | dest="revert", | |
| 55 | to_get = [] | 55 | action="store_true", |
| 56 | project = None | 56 | help="revert instead of checkout", |
| 57 | 57 | ) | |
| 58 | for a in args: | 58 | p.add_option( |
| 59 | m = CHANGE_RE.match(a) | 59 | "-f", |
| 60 | if m: | 60 | "--ff-only", |
| 61 | if not project: | 61 | dest="ffonly", |
| 62 | project = self.GetProjects(".")[0] | 62 | action="store_true", |
| 63 | print('Defaulting to cwd project', project.name) | 63 | help="force fast-forward merge", |
| 64 | chg_id = int(m.group(1)) | 64 | ) |
| 65 | if m.group(2): | 65 | |
| 66 | ps_id = int(m.group(2)) | 66 | def _ParseChangeIds(self, opt, args): |
| 67 | else: | 67 | if not args: |
| 68 | ps_id = 1 | 68 | self.Usage() |
| 69 | refs = 'refs/changes/%2.2d/%d/' % (chg_id % 100, chg_id) | 69 | |
| 70 | output = project._LsRemote(refs + '*') | 70 | to_get = [] |
| 71 | if output: | 71 | project = None |
| 72 | regex = refs + r'(\d+)' | 72 | |
| 73 | rcomp = re.compile(regex, re.I) | 73 | for a in args: |
| 74 | for line in output.splitlines(): | 74 | m = CHANGE_RE.match(a) |
| 75 | match = rcomp.search(line) | 75 | if m: |
| 76 | if match: | 76 | if not project: |
| 77 | ps_id = max(int(match.group(1)), ps_id) | 77 | project = self.GetProjects(".")[0] |
| 78 | to_get.append((project, chg_id, ps_id)) | 78 | print("Defaulting to cwd project", project.name) |
| 79 | else: | 79 | chg_id = int(m.group(1)) |
| 80 | projects = self.GetProjects([a], all_manifests=not opt.this_manifest_only) | 80 | if m.group(2): |
| 81 | if len(projects) > 1: | 81 | ps_id = int(m.group(2)) |
| 82 | # If the cwd is one of the projects, assume they want that. | 82 | else: |
| 83 | try: | 83 | ps_id = 1 |
| 84 | project = self.GetProjects('.')[0] | 84 | refs = "refs/changes/%2.2d/%d/" % (chg_id % 100, chg_id) |
| 85 | except NoSuchProjectError: | 85 | output = project._LsRemote(refs + "*") |
| 86 | project = None | 86 | if output: |
| 87 | if project not in projects: | 87 | regex = refs + r"(\d+)" |
| 88 | print('error: %s matches too many projects; please re-run inside ' | 88 | rcomp = re.compile(regex, re.I) |
| 89 | 'the project checkout.' % (a,), file=sys.stderr) | 89 | for line in output.splitlines(): |
| 90 | for project in projects: | 90 | match = rcomp.search(line) |
| 91 | print(' %s/ @ %s' % (project.RelPath(local=opt.this_manifest_only), | 91 | if match: |
| 92 | project.revisionExpr), file=sys.stderr) | 92 | ps_id = max(int(match.group(1)), ps_id) |
| 93 | sys.exit(1) | 93 | to_get.append((project, chg_id, ps_id)) |
| 94 | else: | 94 | else: |
| 95 | project = projects[0] | 95 | projects = self.GetProjects( |
| 96 | print('Defaulting to cwd project', project.name) | 96 | [a], all_manifests=not opt.this_manifest_only |
| 97 | return to_get | 97 | ) |
| 98 | 98 | if len(projects) > 1: | |
| 99 | def ValidateOptions(self, opt, args): | 99 | # If the cwd is one of the projects, assume they want that. |
| 100 | if opt.record_origin: | 100 | try: |
| 101 | if not opt.cherrypick: | 101 | project = self.GetProjects(".")[0] |
| 102 | self.OptionParser.error('-x only makes sense with --cherry-pick') | 102 | except NoSuchProjectError: |
| 103 | 103 | project = None | |
| 104 | if opt.ffonly: | 104 | if project not in projects: |
| 105 | self.OptionParser.error('-x and --ff are mutually exclusive options') | 105 | print( |
| 106 | 106 | "error: %s matches too many projects; please " | |
| 107 | def Execute(self, opt, args): | 107 | "re-run inside the project checkout." % (a,), |
| 108 | for project, change_id, ps_id in self._ParseChangeIds(opt, args): | 108 | file=sys.stderr, |
| 109 | dl = project.DownloadPatchSet(change_id, ps_id) | 109 | ) |
| 110 | if not dl: | 110 | for project in projects: |
| 111 | print('[%s] change %d/%d not found' | 111 | print( |
| 112 | % (project.name, change_id, ps_id), | 112 | " %s/ @ %s" |
| 113 | file=sys.stderr) | 113 | % ( |
| 114 | sys.exit(1) | 114 | project.RelPath( |
| 115 | 115 | local=opt.this_manifest_only | |
| 116 | if not opt.revert and not dl.commits: | 116 | ), |
| 117 | print('[%s] change %d/%d has already been merged' | 117 | project.revisionExpr, |
| 118 | % (project.name, change_id, ps_id), | 118 | ), |
| 119 | file=sys.stderr) | 119 | file=sys.stderr, |
| 120 | continue | 120 | ) |
| 121 | 121 | sys.exit(1) | |
| 122 | if len(dl.commits) > 1: | 122 | else: |
| 123 | print('[%s] %d/%d depends on %d unmerged changes:' | 123 | project = projects[0] |
| 124 | % (project.name, change_id, ps_id, len(dl.commits)), | 124 | print("Defaulting to cwd project", project.name) |
| 125 | file=sys.stderr) | 125 | return to_get |
| 126 | for c in dl.commits: | 126 | |
| 127 | print(' %s' % (c), file=sys.stderr) | 127 | def ValidateOptions(self, opt, args): |
| 128 | 128 | if opt.record_origin: | |
| 129 | if opt.cherrypick: | 129 | if not opt.cherrypick: |
| 130 | mode = 'cherry-pick' | 130 | self.OptionParser.error( |
| 131 | elif opt.revert: | 131 | "-x only makes sense with --cherry-pick" |
| 132 | mode = 'revert' | 132 | ) |
| 133 | elif opt.ffonly: | 133 | |
| 134 | mode = 'fast-forward merge' | 134 | if opt.ffonly: |
| 135 | else: | 135 | self.OptionParser.error( |
| 136 | mode = 'checkout' | 136 | "-x and --ff are mutually exclusive options" |
| 137 | 137 | ) | |
| 138 | # We'll combine the branch+checkout operation, but all the rest need a | 138 | |
| 139 | # dedicated branch start. | 139 | def Execute(self, opt, args): |
| 140 | if opt.branch and mode != 'checkout': | 140 | for project, change_id, ps_id in self._ParseChangeIds(opt, args): |
| 141 | project.StartBranch(opt.branch) | 141 | dl = project.DownloadPatchSet(change_id, ps_id) |
| 142 | 142 | if not dl: | |
| 143 | try: | 143 | print( |
| 144 | if opt.cherrypick: | 144 | "[%s] change %d/%d not found" |
| 145 | project._CherryPick(dl.commit, ffonly=opt.ffonly, | 145 | % (project.name, change_id, ps_id), |
| 146 | record_origin=opt.record_origin) | 146 | file=sys.stderr, |
| 147 | elif opt.revert: | 147 | ) |
| 148 | project._Revert(dl.commit) | 148 | sys.exit(1) |
| 149 | elif opt.ffonly: | 149 | |
| 150 | project._FastForward(dl.commit, ffonly=True) | 150 | if not opt.revert and not dl.commits: |
| 151 | else: | 151 | print( |
| 152 | if opt.branch: | 152 | "[%s] change %d/%d has already been merged" |
| 153 | project.StartBranch(opt.branch, revision=dl.commit) | 153 | % (project.name, change_id, ps_id), |
| 154 | else: | 154 | file=sys.stderr, |
| 155 | project._Checkout(dl.commit) | 155 | ) |
| 156 | 156 | continue | |
| 157 | except GitError: | 157 | |
| 158 | print('[%s] Could not complete the %s of %s' | 158 | if len(dl.commits) > 1: |
| 159 | % (project.name, mode, dl.commit), file=sys.stderr) | 159 | print( |
| 160 | sys.exit(1) | 160 | "[%s] %d/%d depends on %d unmerged changes:" |
| 161 | % (project.name, change_id, ps_id, len(dl.commits)), | ||
| 162 | file=sys.stderr, | ||
| 163 | ) | ||
| 164 | for c in dl.commits: | ||
| 165 | print(" %s" % (c), file=sys.stderr) | ||
| 166 | |||
| 167 | if opt.cherrypick: | ||
| 168 | mode = "cherry-pick" | ||
| 169 | elif opt.revert: | ||
| 170 | mode = "revert" | ||
| 171 | elif opt.ffonly: | ||
| 172 | mode = "fast-forward merge" | ||
| 173 | else: | ||
| 174 | mode = "checkout" | ||
| 175 | |||
| 176 | # We'll combine the branch+checkout operation, but all the rest need | ||
| 177 | # a dedicated branch start. | ||
| 178 | if opt.branch and mode != "checkout": | ||
| 179 | project.StartBranch(opt.branch) | ||
| 180 | |||
| 181 | try: | ||
| 182 | if opt.cherrypick: | ||
| 183 | project._CherryPick( | ||
| 184 | dl.commit, | ||
| 185 | ffonly=opt.ffonly, | ||
| 186 | record_origin=opt.record_origin, | ||
| 187 | ) | ||
| 188 | elif opt.revert: | ||
| 189 | project._Revert(dl.commit) | ||
| 190 | elif opt.ffonly: | ||
| 191 | project._FastForward(dl.commit, ffonly=True) | ||
| 192 | else: | ||
| 193 | if opt.branch: | ||
| 194 | project.StartBranch(opt.branch, revision=dl.commit) | ||
| 195 | else: | ||
| 196 | project._Checkout(dl.commit) | ||
| 197 | |||
| 198 | except GitError: | ||
| 199 | print( | ||
| 200 | "[%s] Could not complete the %s of %s" | ||
| 201 | % (project.name, mode, dl.commit), | ||
| 202 | file=sys.stderr, | ||
| 203 | ) | ||
| 204 | sys.exit(1) | ||
