Skip to content

Commit ad4df0a

Browse files
authored
Add --exclude option to transfer submit (#527)
* add exclude option to globus transfer * add exclude option tests Co-authored-by: Aaron Schaer <[email protected]>
1 parent 6bac404 commit ad4df0a

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

Diff for: globus_cli/commands/transfer.py

+33
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,18 @@
193193
"during the transfer."
194194
),
195195
)
196+
@click.option(
197+
"--exclude",
198+
multiple=True,
199+
default=None,
200+
show_default=True,
201+
help=(
202+
"Exclude files and directories found with names that match the given "
203+
"pattern in recursive transfers. Pattern may include * ? or [] for "
204+
"unix style globbing. Give this option multiple times to exclude "
205+
"multiple patterns."
206+
),
207+
)
196208
@click.argument(
197209
"source", metavar="SOURCE_ENDPOINT_ID[:SOURCE_PATH]", type=ENDPOINT_PLUS_OPTPATH
198210
)
@@ -213,6 +225,7 @@ def transfer_command(
213225
external_checksum,
214226
skip_source_errors,
215227
fail_on_quota_errors,
228+
exclude,
216229
label,
217230
preserve_mtime,
218231
verify_checksum,
@@ -339,6 +352,14 @@ def transfer_command(
339352
kwargs.update(perf_opts)
340353
kwargs.update(notify)
341354

355+
def _make_exclude_rule(name_pattern):
356+
return {"DATA_TYPE": "filter_rule", "method": "exclude", "name": name_pattern}
357+
358+
if exclude:
359+
filter_rules = [_make_exclude_rule(s) for s in exclude]
360+
else:
361+
filter_rules = None
362+
342363
client = get_client()
343364
transfer_data = TransferData(
344365
client,
@@ -355,6 +376,7 @@ def transfer_command(
355376
skip_activation_check=skip_activation_check,
356377
skip_source_errors=skip_source_errors,
357378
fail_on_quota_errors=fail_on_quota_errors,
379+
filter_rules=filter_rules,
358380
**kwargs
359381
)
360382

@@ -374,6 +396,7 @@ def process_batch_line(dest_path, source_path, recursive, external_checksum):
374396
raise click.UsageError(
375397
"--recursive and --external-checksum are mutually exclusive"
376398
)
399+
377400
transfer_data.add_item(
378401
str(source_path),
379402
str(dest_path),
@@ -398,6 +421,16 @@ def process_batch_line(dest_path, source_path, recursive, external_checksum):
398421
recursive=recursive,
399422
)
400423

424+
for item in transfer_data["DATA"]:
425+
if item["recursive"]:
426+
has_recursive_items = True
427+
break
428+
else:
429+
has_recursive_items = False
430+
431+
if exclude and not has_recursive_items:
432+
raise click.UsageError("--exclude can only be used with --recursive transfers")
433+
401434
if dry_run:
402435
formatted_print(
403436
transfer_data,

Diff for: tests/functional/test_task_submit.py

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import json
2+
3+
4+
def test_exclude(run_line, load_api_fixtures, go_ep1_id, go_ep2_id):
5+
"""
6+
Submits two --exclude options on a transfer, confirms they show up
7+
in --dry-run output
8+
"""
9+
# put a submission ID and autoactivate response in place
10+
load_api_fixtures("get_submission_id.yaml")
11+
load_api_fixtures("transfer_activate_success.yaml")
12+
13+
result = run_line(
14+
"globus transfer -F json --dry-run -r "
15+
"--exclude *.txt --exclude *.pdf "
16+
"{}:/ {}:/".format(go_ep1_id, go_ep1_id)
17+
)
18+
19+
expected_filter_rules = [
20+
{"DATA_TYPE": "filter_rule", "method": "exclude", "name": "*.txt"},
21+
{"DATA_TYPE": "filter_rule", "method": "exclude", "name": "*.pdf"},
22+
]
23+
24+
json_output = json.loads(result.output)
25+
assert json_output["filter_rules"] == expected_filter_rules
26+
27+
28+
def test_exlude_recursive(run_line, load_api_fixtures, go_ep1_id, go_ep2_id):
29+
"""
30+
Confirms using --exclude on non recursive transfers raises errors
31+
"""
32+
# would be better if this could fail before we make any api calls, but
33+
# we want to build the transfer_data object before we parse batch input
34+
load_api_fixtures("get_submission_id.yaml")
35+
36+
expected_error = "--exclude can only be used with --recursive transfers"
37+
38+
# single
39+
result = run_line(
40+
"globus transfer --exclude *.txt " "{}:/ {}:/".format(go_ep1_id, go_ep1_id),
41+
assert_exit_code=2,
42+
)
43+
assert expected_error in result.stderr
44+
45+
# batch
46+
batch_input = "abc /def\n"
47+
result = run_line(
48+
"globus transfer --exclude *.txt --batch "
49+
"{}:/ {}:/".format(go_ep1_id, go_ep1_id),
50+
stdin=batch_input,
51+
assert_exit_code=2,
52+
)
53+
assert expected_error in result.stderr

0 commit comments

Comments
 (0)