This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git
The following commit(s) were added to refs/heads/master by this push:
new 3ba29f389 another fix for clone task validation: move validation down
into init_as_clone and do file path and URL validation separately based on
which is used
3ba29f389 is described below
commit 3ba29f3890047baa75d027998a2c58481b8be6b2
Author: Dave Brondsema <[email protected]>
AuthorDate: Tue May 19 11:23:13 2026 -0400
another fix for clone task validation: move validation down into
init_as_clone and do file path and URL validation separately based on which is
used
---
Allura/allura/model/repository.py | 27 ++++++++++++++++------
Allura/allura/tasks/repo_tasks.py | 3 ---
.../forgegit/tests/functional/test_controllers.py | 4 +++-
ForgeSVN/forgesvn/tests/model/test_repository.py | 10 ++++----
ForgeSVN/forgesvn/tests/test_tasks.py | 3 +--
5 files changed, 29 insertions(+), 18 deletions(-)
diff --git a/Allura/allura/model/repository.py
b/Allura/allura/model/repository.py
index b39ca28f1..d61828755 100644
--- a/Allura/allura/model/repository.py
+++ b/Allura/allura/model/repository.py
@@ -18,6 +18,7 @@
import json
import os
import stat
+import sys
from operator import itemgetter
import mimetypes
import logging
@@ -53,13 +54,14 @@
from allura.lib import helpers as h
from allura.lib import utils
+from allura.lib import validators as v
from allura.lib.security import has_access
from .artifact import Artifact, VersionedArtifact
from .auth import User
from .timeline import ActivityObject
from .monq_model import MonQTask
-from .project import AppConfig
+from .project import AppConfig, Project
from .session import main_doc_session
from .session import repository_orm_session
@@ -388,11 +390,11 @@ def activity_name(self):
return 'repo %s' % self.name
@classmethod
- def default_fs_path(cls, project, tool):
+ def default_fs_path(cls, project: Project | None, tool: str):
repos_root = tg.config.get('scm.repos.root', '/')
# if a user-project, the repository path on disk needs to use the
actual shortname
# the nice url might have invalid chars
- return os.path.join(repos_root, tool,
project.url(use_userproject_shortname=True)[1:])
+ return os.path.join(repos_root, tool,
project.url(use_userproject_shortname=True)[1:] if project else '')
@classmethod
def default_url_path(cls, project, tool):
@@ -538,11 +540,22 @@ def set_default_branch(self, name):
def paged_diffs(self, commit_id, start=0, end=None,
onlyChangedFiles=False):
return self._impl.paged_diffs(commit_id, start, end, onlyChangedFiles)
- def init_as_clone(self, source_path, source_name, source_url):
+ def init_as_clone(self, source_path, source_name, source_url,
bypass_path_check_for_tests=False):
self.upstream_repo.name = source_name
self.upstream_repo.url = source_url
session(self).flush(self)
- source = source_path if source_path else source_url
+ if source_path:
+ repos_root = self.default_fs_path(project=None, tool=self.tool)
+ if not source_path.startswith(repos_root) and not
bypass_path_check_for_tests:
+ err = 'Invalid source path'
+ if asbool(tg.config['debug']) or 'pytest' in sys.modules:
+ err += f': {source_path} must start with {repos_root}'
+ raise ValueError(err)
+ source = source_path
+ else:
+ # could be git:// svn+ssh:// many things for scheme, so
enforce_schemes=None
+ v.NonPrivateUrl(enforce_schemes=None).to_python(source_url)
+ source = source_url
self._impl.clone_from(source)
log.info('... %r cloned', self)
g.post_event('repo_cloned', source_url, source_path)
@@ -1111,8 +1124,8 @@ class __mongometa__:
repo = None
def __init__(self, **kw):
- for k, v in kw.items():
- setattr(self, k, v)
+ for k, val in kw.items():
+ setattr(self, k, val)
@property
def activity_name(self):
diff --git a/Allura/allura/tasks/repo_tasks.py
b/Allura/allura/tasks/repo_tasks.py
index 6b61bfde7..7838c5c53 100644
--- a/Allura/allura/tasks/repo_tasks.py
+++ b/Allura/allura/tasks/repo_tasks.py
@@ -39,9 +39,6 @@ def init(**kwargs):
def clone(cloned_from_path, cloned_from_name, cloned_from_url):
from allura import model as M
try:
- # could be git:// svn+ssh:// many things for scheme
- v.NonPrivateUrl(enforce_schemes=None).to_python(cloned_from_url)
-
c.app.repo.init_as_clone(
cloned_from_path,
cloned_from_name,
diff --git a/ForgeGit/forgegit/tests/functional/test_controllers.py
b/ForgeGit/forgegit/tests/functional/test_controllers.py
index 750d7f2d3..4b83848aa 100644
--- a/ForgeGit/forgegit/tests/functional/test_controllers.py
+++ b/ForgeGit/forgegit/tests/functional/test_controllers.py
@@ -635,7 +635,9 @@ def setup_method(self, method):
c.app.repo.init_as_clone(
cloned_from.full_fs_path,
cloned_from.app.config.script_name(),
- cloned_from.full_fs_path)
+ cloned_from.full_fs_path,
+ bypass_path_check_for_tests=True,
+ )
# Add commit to a forked repo, thus merge requests will not be
empty
# clone repo to tmp location first (can't add commit to bare repos
# directly)
diff --git a/ForgeSVN/forgesvn/tests/model/test_repository.py
b/ForgeSVN/forgesvn/tests/model/test_repository.py
index 7d218a755..cf3fdfddc 100644
--- a/ForgeSVN/forgesvn/tests/model/test_repository.py
+++ b/ForgeSVN/forgesvn/tests/model/test_repository.py
@@ -740,11 +740,11 @@ def test_url_for_commit(self):
@mock.patch('allura.model.repository.g.post_event')
def test_init_as_clone(self, post_event):
- self.repo.init_as_clone('srcpath', 'srcname', 'srcurl')
+ self.repo.init_as_clone(tg.config['scm.repos.root'] + '/svn/srcpath',
'srcname', 'srcurl')
assert self.repo.upstream_repo.name == 'srcname'
assert self.repo.upstream_repo.url == 'srcurl'
- self.repo._impl.clone_from.assert_called_with('srcpath')
- post_event.assert_called_once_with('repo_cloned', 'srcurl', 'srcpath')
+ self.repo._impl.clone_from.assert_called_with('/tmp/svn/srcpath')
+ post_event.assert_called_once_with('repo_cloned', 'srcurl',
'/tmp/svn/srcpath')
def test_latest(self):
ci = mock.Mock()
@@ -830,7 +830,7 @@ def test_refresh_private(self):
self.repo.refresh()
def test_push_upstream_context(self):
- self.repo.init_as_clone('srcpath', '/p/test/svn/', '/p/test/svn/')
+ self.repo.init_as_clone(tg.config['scm.repos.root'] + '/svn/srcpath',
'/p/test/svn/', '/p/test/svn/')
old_app_instance = M.Project.app_instance
try:
M.Project.app_instance = mock.Mock(return_value=ming.base.Object(
@@ -841,7 +841,7 @@ def test_push_upstream_context(self):
M.Project.app_instance = old_app_instance
def test_pending_upstream_merges(self):
- self.repo.init_as_clone('srcpath', '/p/test/svn/', '/p/test/svn/')
+ self.repo.init_as_clone(tg.config['scm.repos.root'] + '/svn/srcpath',
'/p/test/svn/', '/p/test/svn/')
old_app_instance = M.Project.app_instance
try:
M.Project.app_instance = mock.Mock(return_value=ming.base.Object(
diff --git a/ForgeSVN/forgesvn/tests/test_tasks.py
b/ForgeSVN/forgesvn/tests/test_tasks.py
index 93e4827c2..cd5fb0bf2 100644
--- a/ForgeSVN/forgesvn/tests/test_tasks.py
+++ b/ForgeSVN/forgesvn/tests/test_tasks.py
@@ -66,8 +66,7 @@ def test_clone(self):
assert ns + 1 == M.Notification.query.find().count()
def test_clone_internal(self):
- ns = M.Notification.query.find().count()
- with mock.patch.object(c.app.repo, 'init_as_clone', autospec=True) as
f:
+ with mock.patch.object(c.app.repo._impl, 'clone_from', autospec=True)
as f:
repo_tasks.clone('foo', 'bar', 'http://localhost/baz')
M.main_orm_session.flush()
f.assert_not_called()