#!/usr/bin/env python3 # -*- coding: utf-8 -*- # File: src/scitex_writer/_project/_create.py """ Project creation logic for writer module. Handles creating new writer projects from template. """ from __future__ import annotations import shutil import subprocess from logging import getLogger from pathlib import Path from typing import Optional logger = getLogger(__name__) # Template repository URL TEMPLATE_REPO_URL = "https://github.com/ywatanabe1989/scitex-writer.git" def clone_writer_project( project_dir: str, git_strategy: Optional[str] = "child", branch: Optional[str] = None, tag: Optional[str] = None, ) -> bool: """ Initialize a new writer project directory from scitex-writer template. Args: project_dir: Path to project directory (will be created) git_strategy: Git initialization strategy (optional) - 'child': Create isolated git in project directory (default) - 'parent': Use parent git repository - 'origin': Preserve template's original git history - None or 'none': Disable git initialization branch: Specific branch of the template repository to clone (optional) If None, clones the default branch. Mutually exclusive with tag. tag: Specific tag/release of the template repository to clone (optional) If None, clones the default branch. Mutually exclusive with branch. Returns: True if successful, False otherwise Examples: >>> clone_writer_project("my_paper") >>> clone_writer_project("./papers/my_paper") >>> clone_writer_project("my_paper", git_strategy="parent") >>> clone_writer_project("my_paper", branch="develop") >>> clone_writer_project("my_paper", tag="v1.0.0") """ try: project_path = Path(project_dir) if project_path.exists(): logger.error(f"Directory already exists: {project_path}") return False # Build git clone command cmd = ["git", "clone"] if branch: cmd.extend(["--branch", branch]) elif tag: cmd.extend(["--branch", tag]) cmd.extend([TEMPLATE_REPO_URL, str(project_path)]) # Execute git clone result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode != 0: logger.error(f"Git clone failed: {result.stderr}") return False # Handle git strategy if git_strategy == "none" or git_strategy is None: git_dir = project_path / ".git" if git_dir.exists(): shutil.rmtree(git_dir) elif git_strategy == "child": git_dir = project_path / ".git" if git_dir.exists(): shutil.rmtree(git_dir) subprocess.run(["git", "init"], cwd=str(project_path), capture_output=True) subprocess.run( ["git", "add", "."], cwd=str(project_path), capture_output=True ) subprocess.run( ["git", "commit", "-m", "Initial commit from scitex-writer template"], cwd=str(project_path), capture_output=True, ) # "parent" and "origin" strategies keep the git history as-is logger.info(f"Successfully created writer project at {project_path}") return True except Exception as e: logger.error(f"Failed to initialize writer directory: {e}") return False def ensure_project_exists( project_dir: Path, project_name: str, git_strategy: Optional[str] = "child", branch: Optional[str] = None, tag: Optional[str] = None, ) -> Path: """ Ensure project directory exists, creating it if necessary. Parameters ---------- project_dir : Path Path to project directory project_name : str Name of the project git_strategy : str or None Git initialization strategy branch : str, optional Specific branch of template repository to clone. If None, clones the default branch. Mutually exclusive with tag parameter. tag : str, optional Specific tag/release of template repository to clone. If None, clones the default branch. Mutually exclusive with branch parameter. Returns ------- Path Path to the project directory Raises ------ RuntimeError If project creation fails """ if project_dir.exists(): logger.info(f"Attached to existing project at {project_dir.absolute()}") return project_dir logger.info(f"Creating new project '{project_name}' at {project_dir.absolute()}") # Initialize project directory structure success = clone_writer_project(str(project_dir), git_strategy, branch, tag) if not success: logger.error(f"Failed to initialize project directory for {project_name}") raise RuntimeError(f"Could not create project directory at {project_dir}") # Verify project directory was created if not project_dir.exists(): logger.error(f"Project directory {project_dir} was not created") raise RuntimeError(f"Project directory {project_dir} was not created") logger.info(f"Successfully created project at {project_dir.absolute()}") return project_dir __all__ = ["ensure_project_exists", "clone_writer_project"] # EOF