Skip to content

Commit 87e6152

Browse files
committed
Add 'bundle update' command
Signed-off-by: Stephen Finucane <stephen@that.guru>
1 parent 563e167 commit 87e6152

File tree

5 files changed

+112
-2
lines changed

5 files changed

+112
-2
lines changed

git_pw/api.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from typing import List # noqa
2525
from typing import Optional # noqa
2626
from typing import Tuple # noqa
27+
from typing import Union # noqa
2728

2829
Filters = List[Tuple[str, str]]
2930

@@ -309,7 +310,7 @@ def create(resource_type, data):
309310

310311

311312
def update(resource_type, resource_id, data):
312-
# type: (str, int, dict) -> dict
313+
# type: (str, Union[int, str], dict) -> dict
313314
"""Update a specific API resource.
314315
315316
PATCH /{resource}/{resourceID}/

git_pw/bundle.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,3 +198,45 @@ def create_cmd(name, patch_ids, public, fmt):
198198
bundle = api.create('bundles', data)
199199

200200
_show_bundle(bundle, fmt)
201+
202+
203+
@click.command(name='update')
204+
@click.option('--name')
205+
@click.option('--patch', 'patch_ids', type=click.INT, multiple=True,
206+
help='Add the specified patch(es) to the bundle.')
207+
@click.option('--public/--private', default=None,
208+
help='Allow other users to view this bundle. If private, only '
209+
'you will be able to see this bundle.')
210+
@click.argument('bundle_id')
211+
@api.validate_minimum_version(
212+
(1, 2), 'Updating bundles is only supported from API version 1.2',
213+
)
214+
@utils.format_options
215+
def update_cmd(bundle_id, name, patch_ids, public, fmt):
216+
"""Update a bundle.
217+
218+
Update a bundle on the Patchwork instance. If PATCH_IDs are specified, this
219+
will overwrite all patches in the bundle. Use 'bundle add' and 'bundle
220+
remove' to add or remove patches.
221+
222+
Requires API version 1.2 or greater.
223+
"""
224+
LOG.debug(
225+
'Updating bundle: id=%s, name=%s, patches=%s, public=%s',
226+
bundle_id, name, patch_ids, public,
227+
)
228+
229+
data = []
230+
231+
for key, value in [('name', name), ('public', public)]:
232+
if value is None:
233+
continue
234+
235+
data.append((key, value))
236+
237+
if patch_ids: # special case patches to ignore the empty set
238+
data.append(('patches', patch_ids))
239+
240+
bundle = api.update('bundles', bundle_id, data)
241+
242+
_show_bundle(bundle, fmt)

git_pw/shell.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,5 @@ def bundle():
123123
bundle.add_command(bundle_cmds.show_cmd)
124124
bundle.add_command(bundle_cmds.download_cmd)
125125
bundle.add_command(bundle_cmds.create_cmd)
126+
bundle.add_command(bundle_cmds.update_cmd)
126127
bundle.add_command(bundle_cmds.list_cmd)

releasenotes/notes/bundle-crud-47aadae6eb7a20ad.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ features:
44
The following ``bundle`` commands have been added:
55
66
- ``bundle create``
7+
- ``bundle update``
78
89
Together, these allow for creation, modification and deletion of bundles.
910
Bundles are custom, user-defined groups of patches that can be used to keep

tests/test_bundle.py

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,17 @@ def _get_bundle(**kwargs):
145145
'project': {
146146
'name': 'bar',
147147
},
148-
'patches': [],
148+
'patches': [
149+
{
150+
'id': 42,
151+
'date': '2017-01-01 00:00:00',
152+
'web_url': 'https://example.com/project/foo/patch/123/',
153+
'msgid': '<hello@example.com>',
154+
'list_archive_url': None,
155+
'name': 'Test',
156+
'mbox': 'https://example.com/project/foo/patch/123/mbox/',
157+
},
158+
],
149159
'public': True,
150160
}
151161

@@ -360,3 +370,58 @@ def test_create_api_v1_1(
360370

361371
assert result.exit_code == 1, result
362372
assert mock_log.error.called
373+
374+
375+
@mock.patch('git_pw.api.version', return_value=(1, 2))
376+
@mock.patch('git_pw.api.update')
377+
@mock.patch('git_pw.api.detail')
378+
@mock.patch('git_pw.utils.echo_via_pager')
379+
class UpdateTestCase(unittest.TestCase):
380+
381+
@staticmethod
382+
def _get_bundle(**kwargs):
383+
return ShowTestCase._get_bundle(**kwargs)
384+
385+
def test_update(self, mock_echo, mock_detail, mock_update, mock_version):
386+
"""Validate standard behavior."""
387+
388+
mock_update.return_value = self._get_bundle()
389+
390+
runner = CLIRunner()
391+
result = runner.invoke(
392+
bundle.update_cmd,
393+
['1', '--name', 'hello', '--patch', '1', '--patch', '2'],
394+
)
395+
396+
assert result.exit_code == 0, result
397+
mock_detail.assert_not_called()
398+
mock_update.assert_called_once_with(
399+
'bundles', '1', [('name', 'hello'), ('patches', (1, 2))]
400+
)
401+
402+
def test_update_with_public(
403+
self, mock_echo, mock_detail, mock_update, mock_version,
404+
):
405+
"""Validate behavior with --public option."""
406+
407+
mock_update.return_value = self._get_bundle()
408+
409+
runner = CLIRunner()
410+
result = runner.invoke(bundle.update_cmd, ['1', '--public'])
411+
412+
assert result.exit_code == 0, result
413+
mock_detail.assert_not_called()
414+
mock_update.assert_called_once_with('bundles', '1', [('public', True)])
415+
416+
@mock.patch('git_pw.api.LOG')
417+
def test_update_api_v1_1(
418+
self, mock_log, mock_echo, mock_detail, mock_update, mock_version,
419+
):
420+
421+
mock_version.return_value = (1, 1)
422+
423+
runner = CLIRunner()
424+
result = runner.invoke(bundle.update_cmd, ['1', '--name', 'hello'])
425+
426+
assert result.exit_code == 1, result
427+
assert mock_log.error.called

0 commit comments

Comments
 (0)