Structure de dossiers par utilisateur : projects/<propriétaire>/<projet>/
Remplace le rangement plat projects/<slug>/ par une vraie arborescence par compte créateur, sans toucher aux routes existantes (aucune ne déclare de "/" dans son <slug> : le chemin composé "propriétaire_projet" reste un détail interne à db/, décodé par db/games/project_slug.py, seul fichier à modifier si la convention change un jour). - db/game_dir.py, create_game.py, delete_game.py, list_games.py, move_game.py : résolvent/construisent ce chemin composé. Bénéfice direct : deux comptes différents peuvent chacun avoir un projet nommé pareil sans collision (l'unicité ne se vérifie plus que par dossier propriétaire). move_game.py renomme désormais le dossier PROPRIÉTAIRE entier (changement d'email), prêt pour un futur multi-projet. - scripts/migrate_flat_project_slugs.py : migration des projets déjà créés sous l'ancien rangement plat (simulation par défaut, --apply pour exécuter). - routes/auth/profile.py, tests/conftest.py : suppression de compte/jeu de test via db.delete_game (nettoie aussi le dossier propriétaire devenu vide) plutôt qu'un shutil.rmtree direct du seul dossier projet. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
d5a59bdbd8
commit
0f23024882
+34
-14
@@ -1,23 +1,43 @@
|
||||
import os
|
||||
|
||||
from ..constants import PROJECTS_DIR
|
||||
from ..game_dir import game_dir
|
||||
from .project_slug import build_slug, split_slug
|
||||
|
||||
|
||||
def move_game(old_slug, new_slug):
|
||||
"""Renomme le dossier d'un jeu vers un nouveau slug — utilisé quand un
|
||||
def move_game(old_slug, new_owner_folder):
|
||||
"""Renomme le dossier PROPRIÉTAIRE d'un compte — utilisé quand un
|
||||
utilisateur change son adresse email (voir routes/auth/profile.py,
|
||||
project_slug = slugify(email) pour un compte "user") : le dossier
|
||||
physique du jeu doit suivre. Rend le nouveau slug unique de la même
|
||||
façon que create_game() si, par un hasard extrême, il correspond déjà
|
||||
à un dossier existant. Renvoie le slug FINAL (potentiellement suffixé),
|
||||
à enregistrer comme nouveau project_slug."""
|
||||
if old_slug == new_slug:
|
||||
owner_folder = slugify(email) pour un compte "user", voir
|
||||
db/games/project_slug.py) : le dossier physique doit suivre. Renomme
|
||||
le dossier propriétaire ENTIER en un coup (déplace tous les projets de
|
||||
ce compte ensemble — prêt pour un futur multi-projet, même si un seul
|
||||
aujourd'hui), pas juste un projet. Rend le nouveau dossier propriétaire
|
||||
unique de la même façon que create_game() si, par un hasard extrême,
|
||||
il correspond déjà à un dossier existant. Renvoie le nouveau slug
|
||||
composé FINAL (même projet, propriétaire renommé), à enregistrer comme
|
||||
nouveau project_slug."""
|
||||
old_owner_folder, project_part = split_slug(old_slug)
|
||||
if project_part is None:
|
||||
# Slug pas encore migré vers la structure par utilisateur (voir
|
||||
# scripts/migrate_flat_project_slugs.py) — repli sur l'ancien
|
||||
# comportement plat (renomme le dossier du projet lui-même).
|
||||
if old_slug == new_owner_folder:
|
||||
return old_slug
|
||||
base = new_owner_folder
|
||||
n = 2
|
||||
while os.path.isdir(game_dir(base)):
|
||||
base = f"{new_owner_folder}-{n}"
|
||||
n += 1
|
||||
os.rename(game_dir(old_slug), game_dir(base))
|
||||
return base
|
||||
|
||||
if old_owner_folder == new_owner_folder:
|
||||
return old_slug
|
||||
base = new_slug
|
||||
base = new_owner_folder
|
||||
n = 2
|
||||
while os.path.isdir(game_dir(base)):
|
||||
base = f"{new_slug}-{n}"
|
||||
while os.path.isdir(os.path.join(PROJECTS_DIR, base)):
|
||||
base = f"{new_owner_folder}-{n}"
|
||||
n += 1
|
||||
new_slug = base
|
||||
os.rename(game_dir(old_slug), game_dir(new_slug))
|
||||
return new_slug
|
||||
os.rename(os.path.join(PROJECTS_DIR, old_owner_folder), os.path.join(PROJECTS_DIR, base))
|
||||
return build_slug(base, project_part)
|
||||
|
||||
Reference in New Issue
Block a user