diff --git a/src/snek/__main__.py b/src/snek/__main__.py index c4996aa..198ea1e 100644 --- a/src/snek/__main__.py +++ b/src/snek/__main__.py @@ -1,11 +1,14 @@ import argparse - +import uvloop from aiohttp import web - +import asyncio from snek.app import Application def main(): + + asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) + parser = argparse.ArgumentParser(description="Run the web application.") parser.add_argument( "--port", diff --git a/src/snek/app.py b/src/snek/app.py index 605934a..0b5e14b 100644 --- a/src/snek/app.py +++ b/src/snek/app.py @@ -39,6 +39,10 @@ from snek.view.logout import LogoutView from snek.view.register import RegisterView from snek.view.rpc import RPCView from snek.view.search_user import SearchUserView +from snek.view.settings.repositories import RepositoriesIndexView +from snek.view.settings.repositories import RepositoriesCreateView +from snek.view.settings.repositories import RepositoriesUpdateView +from snek.view.settings.repositories import RepositoriesDeleteView from snek.view.settings.index import SettingsIndexView from snek.view.settings.profile import SettingsProfileView from snek.view.stats import StatsView @@ -175,6 +179,10 @@ class Application(BaseApplication): self.router.add_view("/drive/{drive}.json", DriveView) self.router.add_view("/stats.json", StatsView) self.router.add_view("/user/{user}.html", UserView) + self.router.add_view("/settings/repositories/index.html", RepositoriesIndexView) + self.router.add_view("/settings/repositories/create.html", RepositoriesCreateView) + self.router.add_view("/settings/repositories/repository/{name}/update.html", RepositoriesUpdateView) + self.router.add_view("/settings/repositories/respository/{name}/delete.html", RepositoriesDeleteView) self.webdav = WebdavApplication(self) self.add_subapp("/webdav", self.webdav) diff --git a/src/snek/mapper/__init__.py b/src/snek/mapper/__init__.py index 2d4b12c..ab7904f 100644 --- a/src/snek/mapper/__init__.py +++ b/src/snek/mapper/__init__.py @@ -8,6 +8,7 @@ from snek.mapper.drive_item import DriveItemMapper from snek.mapper.notification import NotificationMapper from snek.mapper.user import UserMapper from snek.mapper.user_property import UserPropertyMapper +from snek.mapper.repository import RepositoryMapper from snek.system.object import Object @@ -23,6 +24,7 @@ def get_mappers(app=None): "drive_item": DriveItemMapper(app=app), "drive": DriveMapper(app=app), "user_property": UserPropertyMapper(app=app), + "repository": RepositoryMapper(app=app), } ) diff --git a/src/snek/mapper/repository.py b/src/snek/mapper/repository.py new file mode 100644 index 0000000..1ac10d4 --- /dev/null +++ b/src/snek/mapper/repository.py @@ -0,0 +1,7 @@ +from snek.model.repository import RepositoryModel +from snek.system.mapper import BaseMapper + + +class RepositoryMapper(BaseMapper): + model_class = RepositoryModel + table_name = "repository" diff --git a/src/snek/model/__init__.py b/src/snek/model/__init__.py index a1009a5..6399c89 100644 --- a/src/snek/model/__init__.py +++ b/src/snek/model/__init__.py @@ -10,6 +10,7 @@ from snek.model.drive_item import DriveItemModel from snek.model.notification import NotificationModel from snek.model.user import UserModel from snek.model.user_property import UserPropertyModel +from snek.model.repository import RepositoryModel from snek.system.object import Object @@ -25,6 +26,7 @@ def get_models(): "drive": DriveModel, "notification": NotificationModel, "user_property": UserPropertyModel, + "repository": RepositoryModel, } ) diff --git a/src/snek/model/repository.py b/src/snek/model/repository.py new file mode 100644 index 0000000..598cbb2 --- /dev/null +++ b/src/snek/model/repository.py @@ -0,0 +1,14 @@ +from snek.model.user import UserModel +from snek.system.model import BaseModel, ModelField + + +class RepositoryModel(BaseModel): + + user_uid = ModelField(name="user_uid", required=True, kind=str) + + name = ModelField(name="name", required=True, kind=str) + + is_private = ModelField(name="is_private", required=False, kind=bool) + + + diff --git a/src/snek/service/__init__.py b/src/snek/service/__init__.py index 3ec4592..be356dc 100644 --- a/src/snek/service/__init__.py +++ b/src/snek/service/__init__.py @@ -11,6 +11,7 @@ from snek.service.socket import SocketService from snek.service.user import UserService from snek.service.user_property import UserPropertyService from snek.service.util import UtilService +from snek.service.repository import RepositoryService from snek.system.object import Object @@ -29,6 +30,7 @@ def get_services(app): "drive": DriveService(app=app), "drive_item": DriveItemService(app=app), "user_property": UserPropertyService(app=app), + "repository": RepositoryService(app=app), } ) diff --git a/src/snek/service/repository.py b/src/snek/service/repository.py new file mode 100644 index 0000000..f7694d7 --- /dev/null +++ b/src/snek/service/repository.py @@ -0,0 +1,39 @@ +from snek.system.service import BaseService +import asyncio + +class RepositoryService(BaseService): + mapper_name = "repository" + + async def exists(self, user_uid, name, **kwargs): + kwargs["user_uid"] = user_uid + kwargs["name"] = name + return await self.exists(**kwargs) + + async def init(self, user_uid, name): + repository_path = await self.services.user.get_repository_path(user_uid) + if not repository_path.exists(): + repository_path.mkdir(parents=True) + repository_path = repository_path.joinpath(name) + command = ['git', 'init', '--bare', repository_path] + process = await asyncio.subprocess.create_subprocess_exec( + *command, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE + ) + stdout, stderr = await process.communicate() + if process.returncode == 0: + print(f"Bare Git repository created at: {repo_path}") + else: + print(f"Error creating repository: {stderr.decode().strip()}") + + async def create(self, user_uid, name,is_private=False): + if await self.exists(user_uid=user_uid, name=name): + return False + + + + model = await self.new() + model["user_uid"] = user_uid + model["name"] = name + model["is_private"] = is_private + return await self.save(model) diff --git a/src/snek/service/user.py b/src/snek/service/user.py index fb66ddb..7ca0711 100644 --- a/src/snek/service/user.py +++ b/src/snek/service/user.py @@ -42,6 +42,12 @@ class UserService(BaseService): def get_admin_uids(self): return self.mapper.get_admin_uids() + async def get_repository_path(self, user_uid): + path = pathlib.Path(f"./drive/repositories/{user_uid}") + if not path.exists(): + return None + return path + async def get_static_path(self, user_uid): path = pathlib.Path(f"./drive/{user_uid}/snek/static") if not path.exists(): diff --git a/src/snek/templates/settings/repositories/create.html b/src/snek/templates/settings/repositories/create.html new file mode 100644 index 0000000..cfef080 --- /dev/null +++ b/src/snek/templates/settings/repositories/create.html @@ -0,0 +1,59 @@ +{% extends 'settings/index.html' %} + +{% block header_text %}
Are you sure you want to delete the following repository?
+