Merge changes Ib8bdaa14,I62380485,I6cbedbd2
am: b7f136bed4
Change-Id: I2f39f0c70b27c5143676247fa0a86deb0999a5f4
This commit is contained in:
@@ -72,8 +72,8 @@ These are common queries:
|
|||||||
* `-g` or `--gerrit` specifies the URL of the Gerrit Code Review website.
|
* `-g` or `--gerrit` specifies the URL of the Gerrit Code Review website.
|
||||||
*(required)*
|
*(required)*
|
||||||
|
|
||||||
* `-b` or `--branch` specifies the local topic branch name that will be passed
|
* `-b` or `--branch` specifies the local branch name that will be passed to
|
||||||
to `repo start`.
|
`repo start`.
|
||||||
|
|
||||||
* `-j` or `--parallel` specifies the number of parallel threads while pulling
|
* `-j` or `--parallel` specifies the number of parallel threads while pulling
|
||||||
change lists.
|
change lists.
|
||||||
@@ -81,6 +81,19 @@ These are common queries:
|
|||||||
* `-n` or `--limits` specifies the maximum number of change lists. (default:
|
* `-n` or `--limits` specifies the maximum number of change lists. (default:
|
||||||
1000)
|
1000)
|
||||||
|
|
||||||
|
* `-m` or `--merge` specifies the method to pick the merge commits. (default:
|
||||||
|
`merge-ff-only`)
|
||||||
|
|
||||||
|
* `-p` or `--pick` specifies the method to pick the non-merge commits.
|
||||||
|
(default: `pick`)
|
||||||
|
|
||||||
|
* `pick` maps to `git cherry-pick --allow-empty`
|
||||||
|
* `merge` maps to `git merge --no-edit`
|
||||||
|
* `merge-ff-only` maps to `git merge --no-edit --ff-only`
|
||||||
|
* `merge-no-ff` maps to `git merge --no-edit --no-ff`
|
||||||
|
* `reset` maps to `git reset --hard`
|
||||||
|
* `checkout` maps to `git checkout`
|
||||||
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,11 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
from urllib2 import HTTPBasicAuthHandler, build_opener # PY2
|
from urllib2 import HTTPBasicAuthHandler, build_opener # PY2
|
||||||
|
|
||||||
|
try:
|
||||||
|
from __builtin__ import raw_input as input # PY2
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from shlex import quote as _sh_quote # PY3.3
|
from shlex import quote as _sh_quote # PY3.3
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -96,6 +101,18 @@ else:
|
|||||||
file.buffer.write(data)
|
file.buffer.write(data)
|
||||||
|
|
||||||
|
|
||||||
|
def _confirm(question, default, file=sys.stderr):
|
||||||
|
"""Prompt a yes/no question and convert the answer to a boolean value."""
|
||||||
|
answers = {'': default, 'y': True, 'yes': True, 'n': False, 'no': False}
|
||||||
|
suffix = '[Y/n] ' if default else ' [y/N] '
|
||||||
|
while True:
|
||||||
|
file.write(question + suffix)
|
||||||
|
file.flush()
|
||||||
|
ans = answers.get(input().lower())
|
||||||
|
if ans is not None:
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
class ChangeList(object):
|
class ChangeList(object):
|
||||||
"""A ChangeList to be checked out."""
|
"""A ChangeList to be checked out."""
|
||||||
|
|
||||||
@@ -260,20 +277,33 @@ _MERGE_COMMANDS = {
|
|||||||
'merge-ff-only': ['git', 'merge', '--no-edit', '--ff-only'],
|
'merge-ff-only': ['git', 'merge', '--no-edit', '--ff-only'],
|
||||||
'merge-no-ff': ['git', 'merge', '--no-edit', '--no-ff'],
|
'merge-no-ff': ['git', 'merge', '--no-edit', '--no-ff'],
|
||||||
'reset': ['git', 'reset', '--hard'],
|
'reset': ['git', 'reset', '--hard'],
|
||||||
|
'checkout': ['git', 'checkout'],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def build_pull_commands(change, branch_name, merge_opt):
|
# Git commands for non-merge commits
|
||||||
|
_PICK_COMMANDS = {
|
||||||
|
'pick': ['git', 'cherry-pick', '--allow-empty'],
|
||||||
|
'merge': ['git', 'merge', '--no-edit'],
|
||||||
|
'merge-ff-only': ['git', 'merge', '--no-edit', '--ff-only'],
|
||||||
|
'merge-no-ff': ['git', 'merge', '--no-edit', '--no-ff'],
|
||||||
|
'reset': ['git', 'reset', '--hard'],
|
||||||
|
'checkout': ['git', 'checkout'],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def build_pull_commands(change, branch_name, merge_opt, pick_opt):
|
||||||
"""Build command lines for each change. The command lines will be passed
|
"""Build command lines for each change. The command lines will be passed
|
||||||
to subprocess.run()."""
|
to subprocess.run()."""
|
||||||
|
|
||||||
cmds = []
|
cmds = []
|
||||||
cmds.append(['repo', 'start', branch_name])
|
if branch_name is not None:
|
||||||
|
cmds.append(['repo', 'start', branch_name])
|
||||||
cmds.append(['git', 'fetch', change.fetch_url, change.fetch_ref])
|
cmds.append(['git', 'fetch', change.fetch_url, change.fetch_ref])
|
||||||
if change.is_merge():
|
if change.is_merge():
|
||||||
cmds.append(_MERGE_COMMANDS[merge_opt] + ['FETCH_HEAD'])
|
cmds.append(_MERGE_COMMANDS[merge_opt] + ['FETCH_HEAD'])
|
||||||
else:
|
else:
|
||||||
cmds.append(['git', 'cherry-pick', '--allow-empty', 'FETCH_HEAD'])
|
cmds.append(_PICK_COMMANDS[pick_opt] + ['FETCH_HEAD'])
|
||||||
return cmds
|
return cmds
|
||||||
|
|
||||||
|
|
||||||
@@ -292,7 +322,7 @@ def _sh_quote_commands(cmds):
|
|||||||
def _main_bash(args):
|
def _main_bash(args):
|
||||||
"""Print the bash command to pull the change lists."""
|
"""Print the bash command to pull the change lists."""
|
||||||
|
|
||||||
branch_name = _get_topic_branch_from_args(args)
|
branch_name = _get_local_branch_name_from_args(args)
|
||||||
|
|
||||||
manifest_path = _get_manifest_xml_from_args(args)
|
manifest_path = _get_manifest_xml_from_args(args)
|
||||||
project_dirs = build_project_name_to_directory_dict(manifest_path)
|
project_dirs = build_project_name_to_directory_dict(manifest_path)
|
||||||
@@ -304,7 +334,8 @@ def _main_bash(args):
|
|||||||
for change in changes:
|
for change in changes:
|
||||||
cmds = []
|
cmds = []
|
||||||
cmds.append(['pushd', change.project_dir])
|
cmds.append(['pushd', change.project_dir])
|
||||||
cmds.extend(build_pull_commands(change, branch_name, args.merge))
|
cmds.extend(build_pull_commands(
|
||||||
|
change, branch_name, args.merge, args.pick))
|
||||||
cmds.append(['popd'])
|
cmds.append(['popd'])
|
||||||
print(_sh_quote_commands(cmds))
|
print(_sh_quote_commands(cmds))
|
||||||
|
|
||||||
@@ -315,11 +346,13 @@ def _do_pull_change_lists_for_project(task):
|
|||||||
|
|
||||||
branch_name = task_opts['branch_name']
|
branch_name = task_opts['branch_name']
|
||||||
merge_opt = task_opts['merge_opt']
|
merge_opt = task_opts['merge_opt']
|
||||||
|
pick_opt = task_opts['pick_opt']
|
||||||
|
|
||||||
for i, change in enumerate(changes):
|
for i, change in enumerate(changes):
|
||||||
cwd = change.project_dir
|
cwd = change.project_dir
|
||||||
print(change.commit_sha1[0:10], i + 1, cwd)
|
print(change.commit_sha1[0:10], i + 1, cwd)
|
||||||
for cmd in build_pull_commands(change, branch_name, merge_opt):
|
cmds = build_pull_commands(change, branch_name, merge_opt, pick_opt)
|
||||||
|
for cmd in cmds:
|
||||||
proc = run(cmd, cwd=cwd, stderr=PIPE)
|
proc = run(cmd, cwd=cwd, stderr=PIPE)
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
return (change, changes[i + 1:], cmd, proc.stderr)
|
return (change, changes[i + 1:], cmd, proc.stderr)
|
||||||
@@ -329,7 +362,7 @@ def _do_pull_change_lists_for_project(task):
|
|||||||
def _main_pull(args):
|
def _main_pull(args):
|
||||||
"""Pull the change lists."""
|
"""Pull the change lists."""
|
||||||
|
|
||||||
branch_name = _get_topic_branch_from_args(args)
|
branch_name = _get_local_branch_name_from_args(args)
|
||||||
|
|
||||||
manifest_path = _get_manifest_xml_from_args(args)
|
manifest_path = _get_manifest_xml_from_args(args)
|
||||||
project_dirs = build_project_name_to_directory_dict(manifest_path)
|
project_dirs = build_project_name_to_directory_dict(manifest_path)
|
||||||
@@ -342,6 +375,7 @@ def _main_pull(args):
|
|||||||
task_opts = {
|
task_opts = {
|
||||||
'branch_name': branch_name,
|
'branch_name': branch_name,
|
||||||
'merge_opt': args.merge,
|
'merge_opt': args.merge,
|
||||||
|
'pick_opt': args.pick,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Run the commands to pull the change lists
|
# Run the commands to pull the change lists
|
||||||
@@ -391,12 +425,17 @@ def _parse_args():
|
|||||||
help='Max number of change lists')
|
help='Max number of change lists')
|
||||||
|
|
||||||
parser.add_argument('-m', '--merge',
|
parser.add_argument('-m', '--merge',
|
||||||
choices=_MERGE_COMMANDS.keys(),
|
choices=sorted(_MERGE_COMMANDS.keys()),
|
||||||
default='merge-ff-only',
|
default='merge-ff-only',
|
||||||
help='Method to pull merge commits')
|
help='Method to pull merge commits')
|
||||||
|
|
||||||
|
parser.add_argument('-p', '--pick',
|
||||||
|
choices=sorted(_PICK_COMMANDS.keys()),
|
||||||
|
default='pick',
|
||||||
|
help='Method to pull merge commits')
|
||||||
|
|
||||||
parser.add_argument('-b', '--branch',
|
parser.add_argument('-b', '--branch',
|
||||||
help='Topic branch name to start with')
|
help='Local branch name for `repo start`')
|
||||||
|
|
||||||
parser.add_argument('-j', '--parallel', default=1, type=int,
|
parser.add_argument('-j', '--parallel', default=1, type=int,
|
||||||
help='Number of parallel running commands')
|
help='Number of parallel running commands')
|
||||||
@@ -418,10 +457,11 @@ def _get_change_lists_from_args(args):
|
|||||||
args.limits)
|
args.limits)
|
||||||
|
|
||||||
|
|
||||||
def _get_topic_branch_from_args(args):
|
def _get_local_branch_name_from_args(args):
|
||||||
"""Get the topic branch name from args."""
|
"""Get the local branch name from args."""
|
||||||
if not args.branch:
|
if not args.branch and not _confirm(
|
||||||
print('error: --branch must be specified')
|
'Do you want to continue without local branch name?', False):
|
||||||
|
print('error: `-b` or `--branch` must be specified', file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
return args.branch
|
return args.branch
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user