mirror of
https://gerrit.googlesource.com/git-repo
synced 2024-12-21 07:16:21 +00:00
32b59565b7
Per discussion in go/repo-error-update updated aggregated and exit errors for sync command. Aggregated errors are errors that result in eventual command failure. Exit errors are errors that result in immediate command failure. Also updated main.py to log aggregated and exit errors to git sessions log Bug: b/293344017 Change-Id: I77a21f14da32fe2e68c16841feb22de72e86a251 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/379614 Reviewed-by: Aravind Vasudevan <aravindvasudev@google.com> Tested-by: Jason Chang <jasonnc@google.com> Commit-Queue: Jason Chang <jasonnc@google.com>
205 lines
7.1 KiB
Python
205 lines
7.1 KiB
Python
# Copyright (C) 2008 The Android Open Source Project
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import re
|
|
import sys
|
|
|
|
from command import Command
|
|
from error import GitError, NoSuchProjectError
|
|
|
|
CHANGE_RE = re.compile(r"^([1-9][0-9]*)(?:[/\.-]([1-9][0-9]*))?$")
|
|
|
|
|
|
class Download(Command):
|
|
COMMON = True
|
|
helpSummary = "Download and checkout a change"
|
|
helpUsage = """
|
|
%prog {[project] change[/patchset]}...
|
|
"""
|
|
helpDescription = """
|
|
The '%prog' command downloads a change from the review system and
|
|
makes it available in your project's local working directory.
|
|
If no project is specified try to use current directory as a project.
|
|
"""
|
|
|
|
def _Options(self, p):
|
|
p.add_option("-b", "--branch", help="create a new branch first")
|
|
p.add_option(
|
|
"-c",
|
|
"--cherry-pick",
|
|
dest="cherrypick",
|
|
action="store_true",
|
|
help="cherry-pick instead of checkout",
|
|
)
|
|
p.add_option(
|
|
"-x",
|
|
"--record-origin",
|
|
action="store_true",
|
|
help="pass -x when cherry-picking",
|
|
)
|
|
p.add_option(
|
|
"-r",
|
|
"--revert",
|
|
dest="revert",
|
|
action="store_true",
|
|
help="revert instead of checkout",
|
|
)
|
|
p.add_option(
|
|
"-f",
|
|
"--ff-only",
|
|
dest="ffonly",
|
|
action="store_true",
|
|
help="force fast-forward merge",
|
|
)
|
|
|
|
def _ParseChangeIds(self, opt, args):
|
|
if not args:
|
|
self.Usage()
|
|
|
|
to_get = []
|
|
project = None
|
|
|
|
for a in args:
|
|
m = CHANGE_RE.match(a)
|
|
if m:
|
|
if not project:
|
|
project = self.GetProjects(".")[0]
|
|
print("Defaulting to cwd project", project.name)
|
|
chg_id = int(m.group(1))
|
|
if m.group(2):
|
|
ps_id = int(m.group(2))
|
|
else:
|
|
ps_id = 1
|
|
refs = "refs/changes/%2.2d/%d/" % (chg_id % 100, chg_id)
|
|
output = project._LsRemote(refs + "*")
|
|
if output:
|
|
regex = refs + r"(\d+)"
|
|
rcomp = re.compile(regex, re.I)
|
|
for line in output.splitlines():
|
|
match = rcomp.search(line)
|
|
if match:
|
|
ps_id = max(int(match.group(1)), ps_id)
|
|
to_get.append((project, chg_id, ps_id))
|
|
else:
|
|
projects = self.GetProjects(
|
|
[a], all_manifests=not opt.this_manifest_only
|
|
)
|
|
if len(projects) > 1:
|
|
# If the cwd is one of the projects, assume they want that.
|
|
try:
|
|
project = self.GetProjects(".")[0]
|
|
except NoSuchProjectError:
|
|
project = None
|
|
if project not in projects:
|
|
print(
|
|
"error: %s matches too many projects; please "
|
|
"re-run inside the project checkout." % (a,),
|
|
file=sys.stderr,
|
|
)
|
|
for project in projects:
|
|
print(
|
|
" %s/ @ %s"
|
|
% (
|
|
project.RelPath(
|
|
local=opt.this_manifest_only
|
|
),
|
|
project.revisionExpr,
|
|
),
|
|
file=sys.stderr,
|
|
)
|
|
raise NoSuchProjectError()
|
|
else:
|
|
project = projects[0]
|
|
print("Defaulting to cwd project", project.name)
|
|
return to_get
|
|
|
|
def ValidateOptions(self, opt, args):
|
|
if opt.record_origin:
|
|
if not opt.cherrypick:
|
|
self.OptionParser.error(
|
|
"-x only makes sense with --cherry-pick"
|
|
)
|
|
|
|
if opt.ffonly:
|
|
self.OptionParser.error(
|
|
"-x and --ff are mutually exclusive options"
|
|
)
|
|
|
|
def Execute(self, opt, args):
|
|
for project, change_id, ps_id in self._ParseChangeIds(opt, args):
|
|
dl = project.DownloadPatchSet(change_id, ps_id)
|
|
if not dl:
|
|
print(
|
|
"[%s] change %d/%d not found"
|
|
% (project.name, change_id, ps_id),
|
|
file=sys.stderr,
|
|
)
|
|
sys.exit(1)
|
|
|
|
if not opt.revert and not dl.commits:
|
|
print(
|
|
"[%s] change %d/%d has already been merged"
|
|
% (project.name, change_id, ps_id),
|
|
file=sys.stderr,
|
|
)
|
|
continue
|
|
|
|
if len(dl.commits) > 1:
|
|
print(
|
|
"[%s] %d/%d depends on %d unmerged changes:"
|
|
% (project.name, change_id, ps_id, len(dl.commits)),
|
|
file=sys.stderr,
|
|
)
|
|
for c in dl.commits:
|
|
print(" %s" % (c), file=sys.stderr)
|
|
|
|
if opt.cherrypick:
|
|
mode = "cherry-pick"
|
|
elif opt.revert:
|
|
mode = "revert"
|
|
elif opt.ffonly:
|
|
mode = "fast-forward merge"
|
|
else:
|
|
mode = "checkout"
|
|
|
|
# We'll combine the branch+checkout operation, but all the rest need
|
|
# a dedicated branch start.
|
|
if opt.branch and mode != "checkout":
|
|
project.StartBranch(opt.branch)
|
|
|
|
try:
|
|
if opt.cherrypick:
|
|
project._CherryPick(
|
|
dl.commit,
|
|
ffonly=opt.ffonly,
|
|
record_origin=opt.record_origin,
|
|
)
|
|
elif opt.revert:
|
|
project._Revert(dl.commit)
|
|
elif opt.ffonly:
|
|
project._FastForward(dl.commit, ffonly=True)
|
|
else:
|
|
if opt.branch:
|
|
project.StartBranch(opt.branch, revision=dl.commit)
|
|
else:
|
|
project._Checkout(dl.commit)
|
|
|
|
except GitError:
|
|
print(
|
|
"[%s] Could not complete the %s of %s"
|
|
% (project.name, mode, dl.commit),
|
|
file=sys.stderr,
|
|
)
|
|
sys.exit(1)
|