
Since git-review made it to http://py3ksupport.appspot.com/, why don't support Python 3. Change-Id: I75c28e4887ca79e794553758d671c75740849f97
745 lines
24 KiB
Python
Executable File
745 lines
24 KiB
Python
Executable File
#!/usr/bin/env python
|
|
from __future__ import print_function
|
|
|
|
COPYRIGHT = """\
|
|
Copyright (C) 2011-2012 OpenStack LLC.
|
|
|
|
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 sys
|
|
import urllib
|
|
import json
|
|
|
|
from distutils.version import StrictVersion
|
|
if sys.version < '3':
|
|
from urlparse import urlparse
|
|
import ConfigParser
|
|
else:
|
|
from urllib.parse import urlparse
|
|
import configparser as ConfigParser
|
|
|
|
import datetime
|
|
import os
|
|
import sys
|
|
import time
|
|
import re
|
|
import shlex
|
|
import subprocess
|
|
|
|
version = "1.18"
|
|
|
|
VERBOSE = False
|
|
UPDATE = False
|
|
CONFIGDIR = os.path.expanduser("~/.config/git-review")
|
|
GLOBAL_CONFIG = "/etc/git-review/git-review.conf"
|
|
PYPI_URL = "http://pypi.python.org/pypi/git-review/json"
|
|
PYPI_CACHE_TIME = 60 * 60 * 24 # 24 hours
|
|
|
|
_branch_name = None
|
|
_has_color = None
|
|
|
|
|
|
class colors:
|
|
yellow = '\033[33m'
|
|
green = '\033[92m'
|
|
reset = '\033[0m'
|
|
|
|
|
|
def run_command(cmd, status=False, env={}):
|
|
if VERBOSE:
|
|
print(datetime.datetime.now(), "Running:", cmd)
|
|
cmd_list = shlex.split(str(cmd))
|
|
newenv = os.environ
|
|
newenv.update(env)
|
|
p = subprocess.Popen(cmd_list, stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT, env=newenv)
|
|
(out, nothing) = p.communicate()
|
|
out = out.decode('utf-8')
|
|
if status:
|
|
return (p.returncode, out.strip())
|
|
return out.strip()
|
|
|
|
|
|
def run_command_status(cmd, env={}):
|
|
return run_command(cmd, True, env)
|
|
|
|
|
|
def update_latest_version(version_file_path):
|
|
""" Cache the latest version of git-review for the upgrade check. """
|
|
|
|
if not os.path.exists(CONFIGDIR):
|
|
os.makedirs(CONFIGDIR)
|
|
|
|
if os.path.exists(version_file_path) and not UPDATE:
|
|
if (time.time() - os.path.getmtime(version_file_path)) < 28800:
|
|
return
|
|
|
|
latest_version = version
|
|
try:
|
|
latest_version = json.load(urllib.urlopen(PYPI_URL))['info']['version']
|
|
except:
|
|
pass
|
|
|
|
with open(version_file_path, "w") as version_file:
|
|
version_file.write(latest_version)
|
|
|
|
|
|
def latest_is_newer():
|
|
""" Check if there is a new version of git-review. """
|
|
|
|
# Skip version check if distro package turns it off
|
|
if os.path.exists(GLOBAL_CONFIG):
|
|
config = dict(check=False)
|
|
configParser = ConfigParser.ConfigParser(config)
|
|
configParser.read(GLOBAL_CONFIG)
|
|
if not configParser.getboolean("updates", "check"):
|
|
return False
|
|
|
|
version_file_path = os.path.join(CONFIGDIR, "latest-version")
|
|
update_latest_version(version_file_path)
|
|
|
|
latest_version = None
|
|
with open(version_file_path, "r") as version_file:
|
|
latest_version = StrictVersion(version_file.read())
|
|
if latest_version > StrictVersion(version):
|
|
return True
|
|
return False
|
|
|
|
|
|
def get_hooks_target_file():
|
|
top_dir = run_command('git rev-parse --git-dir')
|
|
hooks_dir = os.path.join(top_dir, "hooks")
|
|
return os.path.join(hooks_dir, "commit-msg")
|
|
|
|
|
|
def set_hooks_commit_msg(remote, target_file):
|
|
""" Install the commit message hook if needed. """
|
|
|
|
# Create the hooks directory if it's not there already
|
|
hooks_dir = os.path.dirname(target_file)
|
|
if not os.path.isdir(hooks_dir):
|
|
os.mkdir(hooks_dir)
|
|
|
|
(hostname, username, port, project_name) = \
|
|
parse_git_show(remote, "Push")
|
|
|
|
if not os.path.exists(target_file) or UPDATE:
|
|
if VERBOSE:
|
|
print("Fetching commit hook from: scp://%s:%s" % (hostname, port))
|
|
scp_cmd = "scp "
|
|
if port is not None:
|
|
scp_cmd += "-P%s " % port
|
|
if username is None:
|
|
scp_cmd += hostname
|
|
else:
|
|
scp_cmd += "%s@%s" % (username, hostname)
|
|
scp_cmd += ":hooks/commit-msg %s" % target_file
|
|
(status, scp_output) = run_command_status(scp_cmd)
|
|
if status != 0:
|
|
print("Problems encountered installing commit-msg hook")
|
|
print(scp_output)
|
|
return False
|
|
|
|
if not os.access(target_file, os.X_OK):
|
|
os.chmod(target_file, os.path.stat.S_IREAD | os.path.stat.S_IEXEC)
|
|
|
|
return True
|
|
|
|
|
|
def test_remote(username, hostname, port, project):
|
|
""" Tests that a possible gerrit remote works """
|
|
|
|
if username is None:
|
|
ssh_cmd = "ssh -x -p%s %s gerrit ls-projects"
|
|
cmd = ssh_cmd % (port, hostname)
|
|
else:
|
|
ssh_cmd = "ssh -x -p%s %s@%s gerrit ls-projects"
|
|
cmd = ssh_cmd % (port, username, hostname)
|
|
(status, ssh_output) = run_command_status(cmd)
|
|
if status == 0:
|
|
if VERBOSE:
|
|
print("%s@%s:%s worked." % (username, hostname, port))
|
|
return True
|
|
else:
|
|
if VERBOSE:
|
|
print("%s@%s:%s did not work." % (username, hostname, port))
|
|
return False
|
|
|
|
|
|
def make_remote_url(username, hostname, port, project):
|
|
""" Builds a gerrit remote URL """
|
|
if username is None:
|
|
return "ssh://%s:%s/%s" % (hostname, port, project)
|
|
else:
|
|
return "ssh://%s@%s:%s/%s" % (username, hostname, port, project)
|
|
|
|
|
|
def add_remote(hostname, port, project, remote):
|
|
""" Adds a gerrit remote. """
|
|
asked_for_username = False
|
|
|
|
username = os.getenv("USERNAME")
|
|
if not username:
|
|
username = run_command('git config --get gitreview.username')
|
|
if not username:
|
|
username = os.getenv("USER")
|
|
if port is None:
|
|
port = 29418
|
|
|
|
remote_url = make_remote_url(username, hostname, port, project)
|
|
if VERBOSE:
|
|
print("No remote set, testing %s" % remote_url)
|
|
if not test_remote(username, hostname, port, project):
|
|
print("Could not connect to gerrit.")
|
|
username = raw_input("Enter your gerrit username: ")
|
|
remote_url = make_remote_url(username, hostname, port, project)
|
|
print("Trying again with %s" % remote_url)
|
|
if not test_remote(username, hostname, port, project):
|
|
raise Exception("Could not connect to gerrit at %s" % remote_url)
|
|
asked_for_username = True
|
|
|
|
print("Creating a git remote called \"%s\" that maps to:" % remote)
|
|
print("\t%s" % remote_url)
|
|
cmd = "git remote add -f %s %s" % (remote, remote_url)
|
|
(status, remote_output) = run_command_status(cmd)
|
|
|
|
if status != 0:
|
|
raise Exception("Error running %s" % cmd)
|
|
|
|
if asked_for_username:
|
|
print()
|
|
print("This repository is now set up for use with git-review.")
|
|
print("You can set the default username for future repositories with:")
|
|
print(' git config --global --add gitreview.username "%s"' % username)
|
|
print()
|
|
|
|
|
|
def parse_git_show(remote, verb):
|
|
fetch_url = ""
|
|
for line in run_command("git remote show -n %s" % remote).split("\n"):
|
|
if line.strip().startswith("%s" % verb):
|
|
fetch_url = line.split()[2]
|
|
|
|
parsed_url = urlparse(fetch_url)
|
|
project_name = parsed_url.path.lstrip("/")
|
|
if project_name.endswith(".git"):
|
|
project_name = project_name[:-4]
|
|
|
|
hostname = parsed_url.netloc
|
|
username = None
|
|
port = parsed_url.port
|
|
|
|
if VERBOSE:
|
|
print("Found origin %s URL:" % verb, fetch_url)
|
|
|
|
# Workaround bug in urlparse on OSX
|
|
if parsed_url.scheme == "ssh" and parsed_url.path[:2] == "//":
|
|
hostname = parsed_url.path[2:].split("/")[0]
|
|
|
|
if "@" in hostname:
|
|
(username, hostname) = hostname.split("@")
|
|
if ":" in hostname:
|
|
(hostname, port) = hostname.split(":")
|
|
|
|
# Is origin an ssh location? Let's pull more info
|
|
if parsed_url.scheme == "ssh" and port == None:
|
|
port = 22
|
|
|
|
return (hostname, username, str(port), project_name)
|
|
|
|
|
|
def git_config_get_value(section, option):
|
|
cmd = "git config --get %s.%s" % (section, option)
|
|
return run_command(cmd).strip()
|
|
|
|
|
|
def check_color_support():
|
|
global _has_color
|
|
if _has_color is None:
|
|
test_command = "git log --color=never --oneline HEAD^1..HEAD"
|
|
(status, output) = run_command_status(test_command)
|
|
if status == 0:
|
|
_has_color = True
|
|
else:
|
|
_has_color = False
|
|
return _has_color
|
|
|
|
|
|
def get_config():
|
|
"""Get the configuration options set in the .gitremote file, if present."""
|
|
"""Returns a hashmap with hostname, port, project and defaultbranch."""
|
|
"""If there is no .gitremote file, default values will be used."""
|
|
config = dict(hostname=False, port='29418', project=False,
|
|
defaultbranch='master', defaultremote="gerrit",
|
|
defaultrebase="1")
|
|
top_dir = run_command('git rev-parse --show-toplevel')
|
|
target_file = os.path.join(top_dir, ".gitreview")
|
|
if os.path.exists(target_file):
|
|
configParser = ConfigParser.ConfigParser(config)
|
|
configParser.read(target_file)
|
|
config['hostname'] = configParser.get("gerrit", "host")
|
|
config['port'] = configParser.get("gerrit", "port")
|
|
config['project'] = configParser.get("gerrit", "project")
|
|
config['defaultbranch'] = configParser.get("gerrit", "defaultbranch")
|
|
if configParser.has_option("gerrit", "defaultremote"):
|
|
config['defaultremote'] = configParser.get("gerrit",
|
|
"defaultremote")
|
|
if configParser.has_option("gerrit", "defaultrebase"):
|
|
config['defaultrebase'] = configParser.getboolean("gerrit",
|
|
"defaultrebase")
|
|
return config
|
|
|
|
|
|
def update_remote(remote):
|
|
cmd = "git remote update %s" % remote
|
|
(status, output) = run_command_status(cmd)
|
|
if VERBOSE:
|
|
print(output)
|
|
if status != 0:
|
|
print("Problem running '%s'" % cmd)
|
|
if not VERBOSE:
|
|
print(output)
|
|
return False
|
|
return True
|
|
|
|
|
|
def check_remote(branch, remote, hostname, port, project):
|
|
"""Check that a Gerrit Git remote repo exists, if not, set one."""
|
|
|
|
has_color = check_color_support()
|
|
if has_color:
|
|
color_never = "--color=never"
|
|
else:
|
|
color_never = ""
|
|
|
|
if remote in run_command("git remote").split("\n"):
|
|
|
|
remotes = run_command("git branch -a %s" % color_never).split("\n")
|
|
for current_remote in remotes:
|
|
if current_remote.strip() == "remotes/%s/%s" % (remote, branch) \
|
|
and not UPDATE:
|
|
return
|
|
# We have the remote, but aren't set up to fetch. Fix it
|
|
if VERBOSE:
|
|
print("Setting up gerrit branch tracking for better rebasing")
|
|
update_remote(remote)
|
|
return
|
|
|
|
if hostname == False or port == False or project == False:
|
|
# This means there was no .gitreview file
|
|
print("No '.gitreview' file found in this repository.")
|
|
print("We don't know where your gerrit is. Please manually create ")
|
|
print("a remote named gerrit and try again.")
|
|
sys.exit(1)
|
|
|
|
# Gerrit remote not present, try to add it
|
|
try:
|
|
add_remote(hostname, port, project, remote)
|
|
except:
|
|
print(sys.exc_info()[2])
|
|
print("We don't know where your gerrit is. Please manually create ")
|
|
print("a remote named \"%s\" and try again." % remote)
|
|
raise
|
|
|
|
|
|
def rebase_changes(branch, remote):
|
|
|
|
remote_branch = "remotes/%s/%s" % (remote, branch)
|
|
|
|
if not update_remote(remote):
|
|
return False
|
|
|
|
cmd = "git rebase -i %s" % remote_branch
|
|
(status, output) = run_command_status(cmd, env=dict(GIT_EDITOR='true'))
|
|
if status != 0:
|
|
print("Errors running %s" % cmd)
|
|
print(output)
|
|
return False
|
|
return True
|
|
|
|
|
|
def get_branch_name(target_branch):
|
|
global _branch_name
|
|
if _branch_name is not None:
|
|
return _branch_name
|
|
_branch_name = None
|
|
has_color = check_color_support()
|
|
if has_color:
|
|
color_never = "--color=never"
|
|
else:
|
|
color_never = ""
|
|
for branch in run_command("git branch %s" % color_never).split("\n"):
|
|
if branch.startswith('*'):
|
|
_branch_name = branch.split()[1].strip()
|
|
if _branch_name == "(no":
|
|
_branch_name = target_branch
|
|
return _branch_name
|
|
|
|
|
|
def assert_one_change(remote, branch, yes, have_hook):
|
|
update_remote(remote)
|
|
branch_name = get_branch_name(branch)
|
|
has_color = check_color_support()
|
|
if has_color:
|
|
color = git_config_get_value("color", "ui").lower()
|
|
if(color == "" or color == "true"):
|
|
color = "auto"
|
|
elif color == "false":
|
|
color = "never"
|
|
elif color == "auto":
|
|
# Python is not a tty, we have to force colors
|
|
color = "always"
|
|
use_color = "--color=%s" % color
|
|
else:
|
|
use_color = ""
|
|
cmd = "git log %s --decorate --oneline %s --not remotes/%s/%s" % \
|
|
(use_color, branch_name, remote, branch)
|
|
(status, output) = run_command_status(cmd)
|
|
if status != 0:
|
|
print("Had trouble running %s" % cmd)
|
|
print(output)
|
|
sys.exit(1)
|
|
output_lines = len(output.split("\n"))
|
|
if output_lines == 1 and not have_hook:
|
|
print("Your change was committed before the commit hook was installed")
|
|
print("Amending the commit to add a gerrit change id")
|
|
run_command("git commit --amend", env=dict(GIT_EDITOR='true'))
|
|
elif output_lines == 0:
|
|
print("No changes between HEAD and %s/%s." % (remote, branch))
|
|
print("Submitting for review would be pointless.")
|
|
sys.exit(1)
|
|
elif output_lines > 1:
|
|
if not yes:
|
|
print("You have more than one commit"
|
|
" that you are about to submit.")
|
|
print("The outstanding commits are:\n\n%s\n" % output)
|
|
print("Is this really what you meant to do?")
|
|
yes_no = raw_input("Type 'yes' to confirm: ")
|
|
if yes_no.lower().strip() != "yes":
|
|
print("Aborting.")
|
|
print("Please rebase/squash your changes and try again")
|
|
sys.exit(1)
|
|
|
|
|
|
def get_topic(target_branch):
|
|
|
|
branch_name = get_branch_name(target_branch)
|
|
|
|
branch_parts = branch_name.split("/")
|
|
if len(branch_parts) >= 3 and branch_parts[0] == "review":
|
|
return "/".join(branch_parts[2:])
|
|
|
|
log_output = run_command("git log HEAD^1..HEAD")
|
|
bug_re = r'\b([Bb]ug|[Ll][Pp])\s*[#:]?\s*(\d+)'
|
|
|
|
match = re.search(bug_re, log_output)
|
|
if match is not None:
|
|
return "bug/%s" % match.group(2)
|
|
|
|
bp_re = r'\b([Bb]lue[Pp]rint|[Bb][Pp])\s*[#:]?\s*([0-9a-zA-Z-_]+)'
|
|
match = re.search(bp_re, log_output)
|
|
if match is not None:
|
|
return "bp/%s" % match.group(2)
|
|
|
|
return branch_name
|
|
|
|
|
|
def list_reviews(remote):
|
|
|
|
(hostname, username, port, project_name) = \
|
|
parse_git_show(remote, "Push")
|
|
|
|
ssh_cmds = ["ssh", "-x"]
|
|
if port is not None:
|
|
ssh_cmds.extend(["-p", port])
|
|
if username is not None:
|
|
ssh_cmds.extend(["-l", username])
|
|
ssh_cmd = " ".join(ssh_cmds)
|
|
|
|
query_string = "--format=JSON project:%s status:open" % project_name
|
|
review_info = None
|
|
(status, output) = run_command_status("%s %s gerrit query %s"
|
|
% (ssh_cmd, hostname, query_string))
|
|
|
|
if status != 0:
|
|
print("Could not fetch review information from gerrit")
|
|
print(output)
|
|
return status
|
|
|
|
for line in output.split("\n"):
|
|
# Warnings from ssh wind up in this output
|
|
if line[0] != "{":
|
|
print(line)
|
|
continue
|
|
try:
|
|
review_info = json.loads(line)
|
|
except:
|
|
if VERBOSE:
|
|
print(output)
|
|
print("Could not parse json query response:", sys.exc_info()[1])
|
|
return 1
|
|
|
|
if 'type' in review_info:
|
|
print("Found %d items for review" % review_info['rowCount'])
|
|
break
|
|
|
|
change = review_info['number']
|
|
branch = review_info['branch']
|
|
subject = review_info['subject']
|
|
if check_color_support():
|
|
change = colors.yellow + change + colors.reset
|
|
branch = colors.green + branch + colors.reset
|
|
print("%s %s %s" % (change, branch, subject))
|
|
|
|
return 0
|
|
|
|
|
|
def download_review(review, masterbranch, remote):
|
|
|
|
(hostname, username, port, project_name) = \
|
|
parse_git_show(remote, "Push")
|
|
|
|
ssh_cmds = ["ssh", "-x"]
|
|
if port is not None:
|
|
ssh_cmds.extend(["-p", port])
|
|
if username is not None:
|
|
ssh_cmds.extend(["-l", username])
|
|
ssh_cmd = " ".join(ssh_cmds)
|
|
|
|
query_string = "--format=JSON --current-patch-set change:%s" % review
|
|
review_info = None
|
|
(status, output) = run_command_status("%s %s gerrit query %s"
|
|
% (ssh_cmd, hostname, query_string))
|
|
|
|
if status != 0:
|
|
print("Could not fetch review information from gerrit")
|
|
print(output)
|
|
return status
|
|
review_jsons = output.split("\n")
|
|
found_review = False
|
|
for review_json in review_jsons:
|
|
try:
|
|
review_info = json.loads(review_json)
|
|
found_review = True
|
|
except:
|
|
pass
|
|
if found_review:
|
|
break
|
|
if not found_review:
|
|
if VERBOSE:
|
|
print(output)
|
|
print("Could not find a gerrit review with id: %s" % review)
|
|
return 1
|
|
|
|
try:
|
|
topic = review_info['topic']
|
|
if topic == masterbranch:
|
|
topic = review
|
|
except KeyError:
|
|
topic = review
|
|
author = re.sub('\W+', '_', review_info['owner']['name']).lower()
|
|
branch_name = "review/%s/%s" % (author, topic)
|
|
revision = review_info['currentPatchSet']['revision']
|
|
refspec = review_info['currentPatchSet']['ref']
|
|
|
|
print("Downloading %s from gerrit into %s" % (refspec, branch_name))
|
|
(status, output) = run_command_status("git fetch %s %s"
|
|
% (remote, refspec))
|
|
if status != 0:
|
|
print(output)
|
|
return status
|
|
|
|
checkout_cmd = "git checkout -b %s FETCH_HEAD" % branch_name
|
|
(status, output) = run_command_status(checkout_cmd)
|
|
if status != 0:
|
|
if re.search("already exists\.?", output):
|
|
print("Branch already exists - reusing")
|
|
checkout_cmd = "git checkout %s" % branch_name
|
|
(status, output) = run_command_status(checkout_cmd)
|
|
if status != 0:
|
|
print(output)
|
|
return status
|
|
reset_cmd = "git reset --hard FETCH_HEAD"
|
|
(status, output) = run_command_status(reset_cmd)
|
|
if status != 0:
|
|
print(output)
|
|
return status
|
|
else:
|
|
print(output)
|
|
return status
|
|
|
|
print("Switched to branch '%s'" % branch_name)
|
|
return 0
|
|
|
|
|
|
def finish_branch(target_branch):
|
|
local_branch = get_branch_name(target_branch)
|
|
if VERBOSE:
|
|
print("Switching back to %s and deleting %s" % (target_branch,
|
|
local_branch))
|
|
checkout_cmd = "git checkout %s" % target_branch
|
|
(status, output) = run_command_status(checkout_cmd)
|
|
if status != 0:
|
|
print(output)
|
|
return status
|
|
print("Switched to branch '%s'" % target_branch)
|
|
close_cmd = "git branch -D %s" % local_branch
|
|
(status, output) = run_command_status(close_cmd)
|
|
if status != 0:
|
|
print(output)
|
|
return status
|
|
print("Deleted branch '%s'" % local_branch)
|
|
return 0
|
|
|
|
|
|
def print_exit_message(status, needs_update):
|
|
|
|
if needs_update:
|
|
print("""
|
|
***********************************************************
|
|
A new version of git-review is available on PyPI. Please
|
|
update your copy with:
|
|
|
|
pip install -U git-review
|
|
|
|
to ensure proper behavior with gerrit. Thanks!
|
|
***********************************************************
|
|
""")
|
|
sys.exit(status)
|
|
|
|
|
|
def main():
|
|
|
|
config = get_config()
|
|
|
|
usage = "git review [OPTIONS] ... [BRANCH]"
|
|
|
|
import argparse
|
|
parser = argparse.ArgumentParser(usage=usage, description=COPYRIGHT)
|
|
|
|
parser.add_argument("-t", "--topic", dest="topic",
|
|
help="Topic to submit branch to")
|
|
parser.add_argument("-D", "--draft", dest="draft", action="store_true",
|
|
help="Submit review as a draft")
|
|
parser.add_argument("-n", "--dry-run", dest="dry", action="store_true",
|
|
help="Don't actually submit the branch for review")
|
|
parser.add_argument("-r", "--remote", dest="remote",
|
|
help="git remote to use for gerrit")
|
|
parser.add_argument("-R", "--no-rebase", dest="rebase",
|
|
action="store_false",
|
|
help="Don't rebase changes before submitting.")
|
|
parser.add_argument("-d", "--download", dest="download",
|
|
help="Download the contents of an existing gerrit "
|
|
"review into a branch")
|
|
parser.add_argument("-u", "--update", dest="update", action="store_true",
|
|
help="Force updates from remote locations")
|
|
parser.add_argument("-s", "--setup", dest="setup", action="store_true",
|
|
help="Just run the repo setup commands but don't "
|
|
"submit anything")
|
|
parser.add_argument("-f", "--finish", dest="finish", action="store_true",
|
|
help="Close down this branch and switch back to "
|
|
"master on successful submission")
|
|
parser.add_argument("-l", "--list", dest="list", action="store_true",
|
|
help="list available reviews for the current project")
|
|
parser.add_argument("-y", "--yes", dest="yes", action="store_true",
|
|
help="Indicate that you do, in fact, understand if "
|
|
"you are submitting more than one patch")
|
|
parser.add_argument("-v", "--verbose", dest="verbose", action="store_true",
|
|
help="Output more information about what's going on")
|
|
parser.add_argument("--license", dest="license", action="store_true",
|
|
help="Print the license and exit")
|
|
parser.add_argument("--version", action="version",
|
|
version='%s version %s' % \
|
|
(os.path.split(sys.argv[0])[-1], version))
|
|
parser.add_argument("branch", nargs="?", default=config['defaultbranch'])
|
|
parser.set_defaults(dry=False,
|
|
draft=False,
|
|
rebase=config['defaultrebase'],
|
|
verbose=False,
|
|
update=False,
|
|
setup=False,
|
|
list=False,
|
|
yes=False,
|
|
remote=config['defaultremote'])
|
|
|
|
options = parser.parse_args()
|
|
|
|
if options.license:
|
|
print(COPYRIGHT)
|
|
sys.exit(0)
|
|
|
|
branch = options.branch
|
|
global VERBOSE
|
|
global UPDATE
|
|
VERBOSE = options.verbose
|
|
UPDATE = options.update
|
|
remote = options.remote
|
|
yes = options.yes
|
|
status = 0
|
|
|
|
needs_update = latest_is_newer()
|
|
check_remote(branch, remote,
|
|
config['hostname'], config['port'], config['project'])
|
|
|
|
if options.download is not None:
|
|
print_exit_message(download_review(options.download, branch, remote),
|
|
needs_update)
|
|
elif options.list:
|
|
print_exit_message(list_reviews(remote), needs_update)
|
|
else:
|
|
topic = options.topic
|
|
if topic is None:
|
|
topic = get_topic(branch)
|
|
if VERBOSE:
|
|
print("Found topic '%s' from parsing changes." % topic)
|
|
|
|
hook_file = get_hooks_target_file()
|
|
|
|
have_hook = os.path.exists(hook_file) and os.access(hook_file, os.X_OK)
|
|
|
|
if not have_hook:
|
|
if not set_hooks_commit_msg(remote, hook_file):
|
|
print_exit_message(1, needs_update)
|
|
|
|
if not options.setup:
|
|
if options.rebase:
|
|
if not rebase_changes(branch, remote):
|
|
print_exit_message(1, needs_update)
|
|
assert_one_change(remote, branch, yes, have_hook)
|
|
|
|
ref = "publish"
|
|
|
|
if options.draft:
|
|
ref = "drafts"
|
|
|
|
cmd = "git push %s HEAD:refs/%s/%s/%s" % (remote, ref, branch,
|
|
topic)
|
|
if options.dry:
|
|
print("Please use the following command " \
|
|
"to send your commits to review:\n")
|
|
print("\t%s\n" % cmd)
|
|
else:
|
|
(status, output) = run_command_status(cmd)
|
|
print(output)
|
|
|
|
if options.finish and not options.dry and status == 0:
|
|
status = finish_branch(branch)
|
|
|
|
print_exit_message(status, needs_update)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|