better scm path normalization

This commit is contained in:
Mike McLean 2026-05-12 17:20:34 -04:00 committed by Tomas Kopecek
commit bec209c437
2 changed files with 32 additions and 2 deletions

View file

@ -262,7 +262,8 @@ class SCM(object):
def get_info(self, keys=None):
if keys is None:
keys = ["url", "scheme", "user", "host", "repository", "module", "revision", "scmtype"]
keys = ["url", "scheme", "user", "host", "repository", "module",
"revision", "scmtype", "has_escapes", "is_normalized"]
return dslice(vars(self), keys)
def _parse_url(self, allow_password=False):
@ -308,7 +309,16 @@ class SCM(object):
raise koji.GenericError(
'Unable to parse SCM URL: %s . Could not find the path element.' % self.url)
path = os.path.normpath(path)
# normalize path
_path = urllib.parse.unquote(path) # e.g. for /%3e%3e/
self.has_escapes = (_path != path)
n_path = os.path.normpath(_path)
self.is_normalized = (n_path == _path)
# re-escape if we need to and underlying scm also uses urls
if self.has_escapes and not scheme.startswith('cvs'):
path = urllib.parse.quote(n_path)
else:
path = n_path
# path and query should not end with /
path = path.rstrip('/')

View file

@ -16,6 +16,10 @@ policy = {
match scm_host goodserver :: allow none
match scm_host badserver :: deny
match scm_host maybeserver && match scm_repository /badpath/* :: deny
match scm_host maybeserver2 :: {
match scm_repository /goodpath/* :: allow
all :: deny
}
all :: allow
''',
'two': '''
@ -133,10 +137,13 @@ class TestSCM(unittest.TestCase):
!badserver:*
!maybeserver:/badpath/*
maybeserver:*:no
maybeserver2:/goodpath/*:no
!maybeserver2:*
'''
good = [
"git://goodserver/path1#1234",
"git+ssh://maybeserver/path1#1234",
"git+ssh://maybeserver2/goodpath/my-repo#1234",
]
bad = [
"cvs://badserver/projects/42#ref",
@ -149,6 +156,11 @@ class TestSCM(unittest.TestCase):
"git://maybeserver/goodpath/../badpath/project#1234",
"git://maybeserver/goodpath/..//badpath/project#1234",
"git://maybeserver/..//badpath/project#1234",
"git+ssh://maybeserver2/not-good-path/my-repo#1234",
"git+ssh://maybeserver2/badpath/my-repo#1234",
"git+ssh://maybeserver2/goodpath/../badpath/my-repo#1234",
"git+https://maybeserver2/goodpath/../badpath/my-repo#1234",
"git+https://maybeserver2/goodpath/%2e%2e/badpath/my-repo#1234",
]
for url in good:
scm = SCM(url)
@ -259,6 +271,7 @@ class TestSCM(unittest.TestCase):
good = [
"git://goodserver/path1#1234",
"git+ssh://maybeserver/path1#1234",
"git+ssh://maybeserver2/goodpath/my-repo#1234",
]
bad = [
"cvs://badserver/projects/42#ref",
@ -271,6 +284,13 @@ class TestSCM(unittest.TestCase):
"git://maybeserver/goodpath/../badpath/project#1234",
"git://maybeserver/goodpath/..//badpath/project#1234",
"git://maybeserver/..//badpath/project#1234",
"git+ssh://maybeserver2/not-good-path/my-repo#1234",
"git+ssh://maybeserver2/badpath/my-repo#1234",
"git+ssh://maybeserver2/goodpath/../badpath/my-repo#1234",
"git+https://maybeserver2/goodpath/%2e%2e/badpath/my-repo#1234",
"git+https://maybeserver2/goodpath/.%2e/badpath/my-repo#1234",
"git+https://maybeserver2/goodpath/%2E.%2fbadpath/my-repo#1234",
"git+https://maybeserver2/goodpath/%2E%2E/badpath/my-repo#1234",
]
session = mock.MagicMock()
session.evalPolicy.side_effect = FakePolicy(policy['one']).evalPolicy