Skip to content

Commit 1cd0e2d

Browse files
committed
shed_init now validates supplied username and owner.
With tests.
1 parent 9a174f9 commit 1cd0e2d

File tree

3 files changed

+81
-36
lines changed

3 files changed

+81
-36
lines changed

planemo/shed/__init__.py

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import hashlib
44
import json
55
import os
6+
import re
67
import tarfile
78
from tempfile import (
89
mkstemp,
@@ -66,6 +67,10 @@
6667
REPO_TYPE_TOOL_DEP = "tool_dependency_definition"
6768
REPO_TYPE_SUITE = "repository_suite_definition"
6869

70+
# TODO: sync this with tool shed impl someday
71+
VALID_REPOSITORYNAME_RE = re.compile("^[a-z0-9\_]+$")
72+
VALID_PUBLICNAME_RE = re.compile("^[a-z0-9\-]+$")
73+
6974
# Generate with python scripts/categories.py
7075
CURRENT_CATEGORIES = [
7176
"Assembly",
@@ -111,7 +116,10 @@ def shed_init(ctx, path, **kwds):
111116
# .shed.yml exists and no --force sent.
112117
return 1
113118

114-
_create_shed_config(ctx, shed_config_path, **kwds)
119+
create_failed = _create_shed_config(ctx, shed_config_path, **kwds)
120+
if create_failed:
121+
return 1
122+
115123
repo_dependencies_path = os.path.join(path, REPO_DEPENDENCIES_CONFIG_NAME)
116124
from_workflow = kwds.get("from_workflow", None)
117125

@@ -427,9 +435,18 @@ def realize_effective_repositories(path, **kwds):
427435

428436
def _create_shed_config(ctx, path, **kwds):
429437
name = kwds.get("name", None) or path_to_repo_name(os.path.dirname(path))
438+
name_invalid = validate_repo_name(name)
439+
if name_invalid:
440+
error(name_invalid)
441+
return 1
442+
430443
owner = kwds.get("owner", None)
431444
if owner is None:
432445
owner = ctx.global_config.get("shed_username", None)
446+
owner_invalid = validate_repo_owner(owner)
447+
if owner_invalid:
448+
error(owner_invalid)
449+
return 1
433450
description = kwds.get("description", None) or name
434451
long_description = kwds.get("long_description", None)
435452
remote_repository_url = kwds.get("remote_repository_url", None)
@@ -768,6 +785,45 @@ def _glob(path, pattern):
768785
def _shed_config_excludes(config):
769786
return config.get('ignore', []) + config.get('exclude', [])
770787

788+
789+
def validate_repo_name(name):
790+
def _build_error(descript):
791+
return "Repository name [%s] invalid. %s" % (name, descript)
792+
793+
msg = None
794+
if len(name) < 2:
795+
msg = _build_error(
796+
"Repository names must be at least 2 characters in length."
797+
)
798+
if len(name) > 80:
799+
msg = _build_error(
800+
"Repository names cannot be more than 80 characters in length."
801+
)
802+
if not VALID_REPOSITORYNAME_RE.match(name):
803+
msg = _build_error(
804+
"Repository names must contain only lower-case letters, "
805+
"numbers and underscore."
806+
)
807+
return msg
808+
809+
810+
def validate_repo_owner(owner):
811+
def _build_error(descript):
812+
return "Owner [%s] invalid. %s" % (owner, descript)
813+
msg = None
814+
if len(owner) < 3:
815+
msg = _build_error("Owner must be at least 3 characters in length")
816+
if len(owner) > 255:
817+
msg = _build_error(
818+
"Owner cannot be more than 255 characters in length"
819+
)
820+
if not(VALID_PUBLICNAME_RE.match(owner)):
821+
msg = _build_error(
822+
"Owner must contain only lower-case letters, numbers and '-'"
823+
)
824+
return msg
825+
826+
771827
__all__ = [
772828
'for_each_repository',
773829
'api_exception_to_message',

planemo/shed_lint.py

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import os
2-
import re
32
import yaml
43
from galaxy.tools.lint import LintContext
54
from galaxy.tools.linters.help import rst_invalid
@@ -10,6 +9,8 @@
109
REPO_TYPE_TOOL_DEP,
1110
REPO_TYPE_SUITE,
1211
CURRENT_CATEGORIES,
12+
validate_repo_owner,
13+
validate_repo_name,
1314
)
1415
from planemo.tool_lint import (
1516
build_lint_args,
@@ -26,9 +27,6 @@
2627
TOOL_DEPENDENCIES_XSD = os.path.join(XSDS_PATH, "tool_dependencies.xsd")
2728
REPO_DEPENDENCIES_XSD = os.path.join(XSDS_PATH, "repository_dependencies.xsd")
2829

29-
# TODO: sync this with tool shed impl someday
30-
VALID_REPOSITORYNAME_RE = re.compile("^[a-z0-9\_]+$")
31-
VALID_PUBLICNAME_RE = re.compile("^[a-z0-9\-]+$")
3230

3331
VALID_REPOSITORY_TYPES = [
3432
REPO_TYPE_UNRESTRICTED,
@@ -152,8 +150,8 @@ def _lint_if_present(key, func, *args):
152150
if msg:
153151
lint_ctx.warn(msg)
154152

155-
_lint_if_present("owner", _validate_repo_owner)
156-
_lint_if_present("name", _validate_repo_name)
153+
_lint_if_present("owner", validate_repo_owner)
154+
_lint_if_present("name", validate_repo_name)
157155
_lint_if_present("type", _validate_repo_type, effective_name)
158156
_lint_if_present("categories", _validate_categories)
159157

@@ -176,29 +174,6 @@ def _validate_repo_type(repo_type, name):
176174
"but repository is listed as unrestricted.")
177175

178176

179-
def _validate_repo_name(name):
180-
msg = None
181-
if len(name) < 2:
182-
msg = "Repository names must be at least 2 characters in length."
183-
if len(name) > 80:
184-
msg = "Repository names cannot be more than 80 characters in length."
185-
if not VALID_REPOSITORYNAME_RE.match(name):
186-
msg = ("Repository names must contain only lower-case letters, "
187-
"numbers and underscore.")
188-
return msg
189-
190-
191-
def _validate_repo_owner(owner):
192-
msg = None
193-
if len(owner) < 3:
194-
msg = "Owner must be at least 3 characters in length"
195-
if len(owner) > 255:
196-
msg = "Owner cannot be more than 255 characters in length"
197-
if not(VALID_PUBLICNAME_RE.match(owner)):
198-
msg = "Owner must contain only lower-case letters, numbers and '-'"
199-
return msg
200-
201-
202177
def _validate_categories(categories):
203178
msg = None
204179
if len(categories) == 0:

tests/test_shed_init.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@ class ShedInitTestCase(CliShedTestCase):
1818

1919
def test_minimal(self):
2020
with self._isolate() as f:
21-
name = os.path.basename(os.path.abspath(f))
22-
self._check_exit_code(["shed_init", "--owner", "iuc"])
21+
self._check_exit_code([
22+
"shed_init", "--owner", "iuc", "--name", "samtools_filter"
23+
])
2324
shed_config_path = os.path.join(f, ".shed.yml")
2425
assert os.path.exists(shed_config_path)
2526
shed_config = yaml.load(open(shed_config_path, "r"))
26-
assert shed_config["name"] == name
27+
assert shed_config["name"] == "samtools_filter"
2728
assert shed_config["owner"] == "iuc"
28-
assert shed_config["description"] == name
29+
assert shed_config["description"] == "samtools_filter"
2930
assert len(shed_config["categories"]) == 0
3031

3132
def test_more_options(self):
@@ -34,7 +35,7 @@ def test_more_options(self):
3435
init_command = [
3536
"shed_init",
3637
"--owner", "devteam",
37-
"--name", "samtools-filter",
38+
"--name", "samtools_filter",
3839
"--description", "A samtools repo",
3940
"--long_description", "A longer description.",
4041
"--remote_repository_url",
@@ -48,7 +49,7 @@ def test_more_options(self):
4849
shed_config_path = os.path.join(f, ".shed.yml")
4950
assert os.path.exists(shed_config_path)
5051
shed_config = yaml.load(open(shed_config_path, "r"))
51-
assert shed_config["name"] == "samtools-filter"
52+
assert shed_config["name"] == "samtools_filter"
5253
assert shed_config["owner"] == "devteam"
5354
assert shed_config["description"] == "A samtools repo"
5455
assert shed_config["long_description"] == "A longer description."
@@ -75,3 +76,16 @@ def test_from_workflow(self):
7576

7677
# lint repository as a way of verifying repository_dependencies
7778
self._check_exit_code(["shed_lint"])
79+
80+
def test_bad_name(self):
81+
with self._isolate():
82+
# has an invalid -
83+
self._check_exit_code([
84+
"shed_init", "--owner", "iuc", "--name", "samtools-filter"
85+
], exit_code=1)
86+
87+
def test_bad_owner(self):
88+
with self._isolate():
89+
self._check_exit_code([
90+
"shed_init", "--owner", "IuC", "--name", "samtools_filter"
91+
], exit_code=1)

0 commit comments

Comments
 (0)