Commit 9eed4238 authored by LaMont Jones's avatar LaMont Jones Committed by LUCI CQ

gerrit: add createchange changeedit publishchangeedit

Add calls to support creating changes, as well as editing and publishing
them in gerrit_client and gerrit_util.

Bug=b:182613582

Change-Id: I0514cf08dce63ab29d99d4485d96fa124006326a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/2800811
Auto-Submit: LaMont Jones <lamontjones@chromium.org>
Reviewed-by: 's avatarDirk Pranke <dpranke@google.com>
Reviewed-by: 's avatarJosip Sokcevic <sokcevic@google.com>
Commit-Queue: LaMont Jones <lamontjones@chromium.org>
parent 9a94a95e
...@@ -153,6 +153,64 @@ def CMDchanges(parser, args): ...@@ -153,6 +153,64 @@ def CMDchanges(parser, args):
write_result(result, opt) write_result(result, opt)
@subcommand.usage('[args ...]')
def CMDcreatechange(parser, args):
parser.add_option('-s', '--subject', help='subject for change')
parser.add_option('-b',
'--branch',
default='main',
help='target branch for change')
parser.add_option(
'-p',
'--param',
dest='params',
action='append',
help='repeatable field value parameter, format: -p key=value')
(opt, args) = parser.parse_args(args)
for p in opt.params:
assert '=' in p, '--param is key=value, not "%s"' % p
result = gerrit_util.CreateChange(
urlparse.urlparse(opt.host).netloc,
opt.project,
branch=opt.branch,
subject=opt.subject,
params=list(tuple(p.split('=', 1)) for p in opt.params),
)
logging.info(result)
write_result(result, opt)
@subcommand.usage('[args ...]')
def CMDchangeedit(parser, args):
parser.add_option('-c', '--change', type=int, help='change number')
parser.add_option('--path', help='path for file')
parser.add_option('--file', help='file to place at |path|')
(opt, args) = parser.parse_args(args)
with open(opt.file) as f:
data = f.read()
result = gerrit_util.ChangeEdit(
urlparse.urlparse(opt.host).netloc, opt.change, opt.path, data)
logging.info(result)
write_result(result, opt)
@subcommand.usage('[args ...]')
def CMDpublishchangeedit(parser, args):
parser.add_option('-c', '--change', type=int, help='change number')
parser.add_option('--notify', help='whether to notify')
(opt, args) = parser.parse_args(args)
result = gerrit_util.PublishChangeEdit(
urlparse.urlparse(opt.host).netloc, opt.change, opt.notify)
logging.info(result)
write_result(result, opt)
@subcommand.usage('') @subcommand.usage('')
def CMDabandon(parser, args): def CMDabandon(parser, args):
parser.add_option('-c', '--change', type=int, help='change number') parser.add_option('-c', '--change', type=int, help='change number')
......
...@@ -737,6 +737,25 @@ def SubmitChange(host, change, wait_for_merge=True): ...@@ -737,6 +737,25 @@ def SubmitChange(host, change, wait_for_merge=True):
return ReadHttpJsonResponse(conn) return ReadHttpJsonResponse(conn)
def PublishChangeEdit(host, change, notify=True):
"""Publish a Gerrit change edit."""
path = 'changes/%s/edit:publish' % change
body = {'notify': 'ALL' if notify else 'NONE'}
conn = CreateHttpConn(host, path, reqtype='POST', body=body)
return ReadHttpJsonResponse(conn, accept_statuses=(204, ))
def ChangeEdit(host, change, path, data):
"""Puts content of a file into a change edit."""
path = 'changes/%s/edit/%s' % (change, urllib.parse.quote(path, ''))
body = {
'binary_content':
'data:text/plain;base64,%s' % base64.b64encode(data.encode('utf-8'))
}
conn = CreateHttpConn(host, path, reqtype='PUT', body=body)
return ReadHttpJsonResponse(conn, accept_statuses=(204, 409))
def HasPendingChangeEdit(host, change): def HasPendingChangeEdit(host, change):
conn = CreateHttpConn(host, 'changes/%s/edit' % change) conn = CreateHttpConn(host, 'changes/%s/edit' % change)
try: try:
...@@ -930,6 +949,29 @@ def ResetReviewLabels(host, change, label, value='0', message=None, ...@@ -930,6 +949,29 @@ def ResetReviewLabels(host, change, label, value='0', message=None,
'a new patchset was uploaded.' % change) 'a new patchset was uploaded.' % change)
def CreateChange(host, project, branch='main', subject='', params=()):
"""
Creates a new change.
Args:
params: A list of additional ChangeInput specifiers, as documented here:
(e.g. ('is_private', 'true') to mark the change private.
https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#change-input
Returns:
ChangeInfo for the new change.
"""
path = 'changes/'
body = {'project': project, 'branch': branch, 'subject': subject}
body.update({k: v for k, v in params})
for key in 'project', 'branch', 'subject':
if not body[key]:
raise GerritError(200, '%s is required' % key.title())
conn = CreateHttpConn(host, path, reqtype='POST', body=body)
return ReadHttpJsonResponse(conn, accept_statuses=[201])
def CreateGerritBranch(host, project, branch, commit): def CreateGerritBranch(host, project, branch, commit):
"""Creates a new branch from given project and commit """Creates a new branch from given project and commit
......
...@@ -13,9 +13,11 @@ import unittest ...@@ -13,9 +13,11 @@ import unittest
if sys.version_info.major == 2: if sys.version_info.major == 2:
from StringIO import StringIO from StringIO import StringIO
import mock import mock
BUILTIN_OPEN = '__builtin__.open'
else: else:
from io import StringIO from io import StringIO
from unittest import mock from unittest import mock
BUILTIN_OPEN = 'builtins.open'
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
...@@ -54,6 +56,38 @@ class TestGerritClient(unittest.TestCase): ...@@ -54,6 +56,38 @@ class TestGerritClient(unittest.TestCase):
start=20, start=20,
o_params=['op1', 'op2']) o_params=['op1', 'op2'])
@mock.patch('gerrit_util.CreateChange', return_value={})
def test_createchange(self, util_mock):
gerrit_client.main([
'createchange', '--host', 'https://example.org/foo', '--project',
'project', '--branch', 'main', '--subject', 'subject', '-p',
'work_in_progress=true'
])
util_mock.assert_called_once_with('example.org',
'project',
branch='main',
subject='subject',
params=[('work_in_progress', 'true')])
@mock.patch(BUILTIN_OPEN, mock.mock_open())
@mock.patch('gerrit_util.ChangeEdit', return_value='')
def test_changeedit(self, util_mock):
open().read.return_value = 'test_data'
gerrit_client.main([
'changeedit', '--host', 'https://example.org/foo', '--change', '1',
'--path', 'path/to/file', '--file', '/my/foo'
])
util_mock.assert_called_once_with('example.org', 1, 'path/to/file',
'test_data')
@mock.patch('gerrit_util.PublishChangeEdit', return_value='')
def test_publishchangeedit(self, util_mock):
gerrit_client.main([
'publishchangeedit', '--host', 'https://example.org/foo', '--change',
'1', '--notify', 'yes'
])
util_mock.assert_called_once_with('example.org', 1, 'yes')
@mock.patch('gerrit_util.AbandonChange', return_value='') @mock.patch('gerrit_util.AbandonChange', return_value='')
def test_abandon(self, util_mock): def test_abandon(self, util_mock):
gerrit_client.main([ gerrit_client.main([
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment