Make repository creation slightly safer

This commit is contained in:
mvdbeek
2024-05-31 17:42:30 +02:00
parent 1b985e74c1
commit ea6751a149
6 changed files with 35 additions and 45 deletions
+1 -2
View File
@@ -71,14 +71,13 @@ def get_hgrc_path(repo_path):
return os.path.join(repo_path, ".hg", "hgrc")
def create_hgrc_file(app, repository):
def create_hgrc_file(app, repository, repo_path):
# Since we support both http and https, we set `push_ssl` to False to
# override the default (which is True) in the Mercurial API.
# The hg purge extension purges all files and directories not being tracked
# by Mercurial in the current repository. It will remove unknown files and
# empty directories. This is not currently used because it is not supported
# in the Mercurial API.
repo_path = repository.repo_path(app)
hgrc_path = get_hgrc_path(repo_path)
with open(hgrc_path, "w") as fp:
fp.write("[paths]\n")
+4 -6
View File
@@ -5,8 +5,6 @@ import shutil
import threading
from datetime import date
from galaxy.util import unicodify
log = logging.getLogger(__name__)
new_hgweb_config_template = """
@@ -36,8 +34,8 @@ class HgWebConfigManager:
self.in_memory_config.set("paths", lhs, rhs)
# Persist our in-memory configuration.
self.write_config()
except Exception as e:
log.debug("Exception in HgWebConfigManager.add_entry(): %s", unicodify(e))
except Exception:
log.exception("Exception in HgWebConfigManager.add_entry()")
finally:
self.lock.release()
@@ -52,8 +50,8 @@ class HgWebConfigManager:
self.in_memory_config.set("paths", new_lhs, new_rhs)
# Persist our in-memory configuration.
self.write_config()
except Exception as e:
log.debug("Exception in HgWebConfigManager.change_entry(): %s", unicodify(e))
except Exception:
log.exception("Exception in HgWebConfigManager.change_entry()")
finally:
self.lock.release()
+26 -34
View File
@@ -2,6 +2,7 @@ import configparser
import logging
import os
import re
import tempfile
from typing import (
Optional,
Tuple,
@@ -154,23 +155,18 @@ def create_repo_info_dict(
def create_repository_admin_role(app: "ToolShedApp", repository: "Repository"):
"""
Create a new role with name-spaced name based on the repository name and its owner's public user
name. This will ensure that the tole name is unique.
name. This will ensure that the role name is unique.
"""
sa_session = app.model.session
name = get_repository_admin_role_name(str(repository.name), str(repository.user.username))
description = "A user or group member with this role can administer this repository."
role = app.model.Role(name=name, description=description, type=app.model.Role.types.SYSTEM)
sa_session.add(role)
session = sa_session()
with transaction(session):
session.commit()
# Associate the role with the repository owner.
app.model.UserRoleAssociation(repository.user, role)
# Associate the role with the repository.
rra = app.model.RepositoryRoleAssociation(repository, role)
sa_session.add(rra)
with transaction(session):
session.commit()
return role
@@ -180,7 +176,7 @@ def create_repository(
type: str,
description,
long_description,
user_id,
user,
category_ids=None,
remote_repository_url=None,
homepage_url=None,
@@ -196,43 +192,39 @@ def create_repository(
homepage_url=homepage_url,
description=description,
long_description=long_description,
user_id=user_id,
user=user,
)
# Flush to get the id.
sa_session.add(repository)
session = sa_session()
with transaction(session):
session.commit()
# Create an admin role for the repository.
create_repository_admin_role(app, repository)
# Determine the repository's repo_path on disk.
dir = os.path.join(app.config.file_path, *util.directory_hash_id(repository.id))
# Create directory if it does not exist.
if not os.path.exists(dir):
os.makedirs(dir)
# Define repo name inside hashed directory.
repository_path = os.path.join(dir, "repo_%d" % repository.id)
# Create local repository directory.
if not os.path.exists(repository_path):
os.makedirs(repository_path)
# Create the local repository.
init_repository(repo_path=repository_path)
# Add an entry in the hgweb.config file for the local repository.
lhs = f"{app.config.hgweb_repo_prefix}{repository.user.username}/{repository.name}"
app.hgweb_config_manager.add_entry(lhs, repository_path)
# Create a .hg/hgrc file for the local repository.
create_hgrc_file(app, repository)
flush_needed = False
if category_ids:
# Create category associations
for category_id in category_ids:
category = sa_session.query(app.model.Category).get(app.security.decode_id(category_id))
rca = app.model.RepositoryCategoryAssociation(repository, category)
sa_session.add(rca)
flush_needed = True
if flush_needed:
# Create an admin role for the repository.
create_repository_admin_role(app, repository)
# Create a temporary repo_path on disk.
with tempfile.TemporaryDirectory(
dir=app.config.file_path, prefix="f{repository.user.username}-{repository.name}"
) as repository_path:
# Create the local repository.
init_repository(repo_path=repository_path)
# Create a .hg/hgrc file for the local repository.
create_hgrc_file(app, repository, repo_path=repository_path)
# Add an entry in the hgweb.config file for the local repository.
lhs = f"{app.config.hgweb_repo_prefix}{repository.user.username}/{repository.name}"
# Flush to get the id.
session = sa_session()
with transaction(session):
session.commit()
dir = os.path.join(app.config.file_path, *util.directory_hash_id(repository.id))
# Define repo name inside hashed directory.
final_repository_path = os.path.join(dir, "repo_%d" % repository.id)
# Create final repository directory.
if not os.path.exists(final_repository_path):
os.makedirs(final_repository_path)
os.rename(repository_path, final_repository_path)
app.hgweb_config_manager.add_entry(lhs, final_repository_path)
# Update the repository registry.
app.repository_registry.add_entry(repository)
message = f"Repository <b>{escape(str(repository.name))}</b> has been created."
+1 -1
View File
@@ -986,7 +986,7 @@ class RepositoriesController(BaseAPIController):
type=repo_type,
description=synopsis,
long_description=description,
user_id=trans.user.id,
user=trans.user,
category_ids=category_ids,
remote_repository_url=remote_repository_url,
homepage_url=homepage_url,
@@ -759,7 +759,7 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings):
repository_type,
description,
long_description,
user_id=trans.user.id,
user=trans.user,
category_ids=category_ids,
remote_repository_url=remote_repository_url,
homepage_url=homepage_url,
+2 -1
View File
@@ -422,12 +422,13 @@ class Repository(Base, Dictifiable):
]
file_states = Bunch(NORMAL="n", NEEDS_MERGING="m", MARKED_FOR_REMOVAL="r", MARKED_FOR_ADDITION="a", NOT_TRACKED="?")
def __init__(self, private=False, times_downloaded=0, deprecated=False, **kwd):
def __init__(self, private=False, times_downloaded=0, deprecated=False, user=None, **kwd):
super().__init__(**kwd)
self.private = private
self.times_downloaded = times_downloaded
self.deprecated = deprecated
self.name = self.name or "Unnamed repository"
self.user = user
@property
def hg_repo(self):