Aggiunta gestione submoduli

This commit is contained in:
VALLONGOL 2025-12-01 08:29:48 +01:00
parent 5ab2fce4f4
commit 1bbbd09762
6 changed files with 205 additions and 58 deletions

View File

@ -25,5 +25,7 @@
"pyinstaller_gui_git": {},
"geoelevation_git": {},
"dependencyanalizer_git": {},
"dependencyanalyzer_git": {}
"dependencyanalyzer_git": {},
"git_utility_git": {},
"pyucc_git": {}
}

View File

@ -5,7 +5,7 @@
"description": "Generates .ico files from PNG images, fetched via Git.",
"type": "git",
"enabled": true,
"git_url": "http://192.168.100.10:3000/VALLONGOL/CreateIconFromFilesPng",
"git_url": "http://192.168.100.10:3000/VALLONGOL/SXXXXXXX_CreateIconFromFilesPng",
"git_ref": "master",
"run_command": ["python", "create_icon_file.py"],
"has_gui": false,
@ -17,7 +17,7 @@
"description": "GUI Wrapper for PyInstaller, fetched via Git.",
"type": "git",
"enabled": true,
"git_url": "http://192.168.100.10:3000/VALLONGOL/PyInstallerGUIWrapper",
"git_url": "http://192.168.100.10:3000/VALLONGOL/SXXXXXXX_PyInstallerGUIWrapper",
"git_ref": "master",
"run_command": ["python", "-m", "pyinstallerguiwrapper"],
"has_gui": true,
@ -29,7 +29,7 @@
"description": "Get elevation data from network, fetched via Git.",
"type": "git",
"enabled": true,
"git_url": "http://192.168.100.10:3000/VALLONGOL/GeoElevation",
"git_url": "http://192.168.100.10:3000/VALLONGOL/SXXXXXXX_GeoElevation",
"git_ref": "master",
"run_command": ["python", "-m", "geoelevation"],
"has_gui": true,
@ -41,7 +41,7 @@
"description": "Manag. requirements from python project, fetched via Git.",
"type": "git",
"enabled": true,
"git_url": "http://192.168.100.10:3000/VALLONGOL/DependencyAnalyzer",
"git_url": "http://192.168.100.10:3000/VALLONGOL/SXXXXXXX_DependencyAnalyzer",
"git_ref": "master",
"run_command": ["python", "-m", "dependencyanalyzer"],
"has_gui": true,
@ -53,7 +53,7 @@
"description": "Create standard folders for new dev tool, fetched via Git.",
"type": "git",
"enabled": true,
"git_url": "http://192.168.100.10:3000/VALLONGOL/ProjectInitializer",
"git_url": "http://192.168.100.10:3000/VALLONGOL/SXXXXXXX_ProjectInitializer",
"git_ref": "master",
"run_command": ["python", "-m", "projectinitializer"],
"has_gui": true,
@ -65,7 +65,7 @@
"description": "Gui for console application g_reconverter, fetched via Git.",
"type": "git",
"enabled": true,
"git_url": "http://192.168.100.10:3000/VALLONGOL/GUI_g_reconverter",
"git_url": "http://192.168.100.10:3000/VALLONGOL/SXXXXXXX_GUI_g_reconverter",
"git_ref": "master",
"run_command": ["python", "-m", "gui_g_reconverter"],
"has_gui": true,
@ -89,7 +89,7 @@
"description": "Backup suite, fetched via Git.",
"type": "git",
"enabled": true,
"git_url": "http://192.168.100.10:3000/VALLONGOL/BackupTools",
"git_url": "http://192.168.100.10:3000/VALLONGOL/SXXXXXXX_BackupTools",
"git_ref": "master",
"run_command": ["python", "-m", "backuptools"],
"has_gui": true,
@ -101,12 +101,85 @@
"description": "Launcher tool, fetched via Git.",
"type": "git",
"enabled": true,
"git_url": "http://192.168.100.10:3000/VALLONGOL/LauncherTool",
"git_url": "http://192.168.100.10:3000/VALLONGOL/SXXXXXXX_LauncherTool",
"git_ref": "master",
"run_command": ["python", "-m", "launchertool"],
"has_gui": true,
"parameters_definition_file": null
},
{
"id": "py_hasher_git",
"display_name": "PyHasher(Git)",
"description": "PyHasher, fetched via Git.",
"type": "git",
"enabled": true,
"git_url": "http://192.168.100.10:3000/VALLONGOL/SXXXXXXX_PyHasher",
"git_ref": "master",
"run_command": ["python", "-m", "pyhasher"],
"has_gui": true,
"parameters_definition_file": null
},
{
"id": "repo_sync_git",
"display_name": "RepoSync (Git)",
"description": "Reporter sync, fetched via Git.",
"type": "git",
"enabled": true,
"git_url": "http://192.168.100.10:3000/VALLONGOL/SXXXXXXX_RepoSync",
"git_ref": "master",
"run_command": ["python", "-m", "reposync"],
"has_gui": true,
"parameters_definition_file": null
},
{
"id": "profile_analyzer_git",
"display_name": "Profile Analyzer (Git)",
"description": "View profile files, fetched via Git.",
"type": "git",
"enabled": true,
"git_url": "http://192.168.100.10:3000/VALLONGOL/SXXXXXXX_ProfileAnalyzer",
"git_ref": "master",
"run_command": ["python", "-m", "profileanalyzer"],
"has_gui": true,
"parameters_definition_file": null
},
{
"id": "markdown_converter_git",
"display_name": "Markdown Converter (Git)",
"description": "Markdown Converter into pdf and docx, fetched via Git.",
"type": "git",
"enabled": true,
"git_url": "http://192.168.100.10:3000/VALLONGOL/SXXXXXXX_MarkdownConverter",
"git_ref": "master",
"run_command": ["python", "-m", "markdownconverter"],
"has_gui": true,
"parameters_definition_file": null
},
{
"id": "pyucc_git",
"display_name": "Py UCC (Git)",
"description": "Py UCC, fetched via Git.",
"type": "git",
"enabled": true,
"git_url": "http://192.168.100.10:3000/VALLONGOL/SXXXXXXX_PyUCC",
"git_ref": "master",
"run_command": ["python", "-m", "pyucc"],
"has_gui": true,
"parameters_definition_file": null,
"auto_update_submodules": true,
"submodules": [
{
"name": "python-resource-monitor",
"path": "external/python-resource-monitor",
"modules": ["resource_monitor.py"]
},
{
"name": "python-tkinter-logger",
"path": "external/python-tkinter-logger",
"modules": ["tkinter_logger.py"]
}
]
},
{
"id": "dummy_script",
"display_name": "Dummy Script Runner (Local)",

View File

@ -573,6 +573,28 @@ def update_repository(
f"Error in progress callback (post-pull success): {cb_err}",
exc_info=True,
)
# --- Submodule handling (if configured) ---
try:
if getattr(tool_entry, "auto_update_submodules", False) or getattr(
tool_entry, "submodules", None
):
local_path = get_local_repo_path(tool_id, tool_entry.local_dir_name)
try:
from projectutility.core.submodule_manager import ensure_submodules
ok = ensure_submodules(local_path, tool_entry.submodules)
if not ok:
logger.warning(
f"[{tool_id}] Submodule update returned non-ok status."
)
except Exception as e:
logger.exception(
f"[{tool_id}] Failed to run submodule update: {e}"
)
except Exception as e:
logger.exception(f"[{tool_id}] Error checking submodule config: {e}")
return (
True,
f"Repo updated. On branch '{current_branch_name}' tracking '{target_ref}'.",
@ -617,6 +639,27 @@ def update_repository(
logger.info(
f"[{tool_id}] Checkout to detached HEAD at {detached_commit_sha} ('{target_ref}'). Update complete."
)
# Try submodule update for detached HEAD too
try:
if getattr(tool_entry, "auto_update_submodules", False) or getattr(
tool_entry, "submodules", None
):
local_path = get_local_repo_path(tool_id, tool_entry.local_dir_name)
try:
from projectutility.core.submodule_manager import ensure_submodules
ok = ensure_submodules(local_path, tool_entry.submodules)
if not ok:
logger.warning(
f"[{tool_id}] Submodule update returned non-ok status (detached HEAD)."
)
except Exception as e:
logger.exception(
f"[{tool_id}] Failed to run submodule update (detached HEAD): {e}"
)
except Exception:
logger.exception(f"[{tool_id}] Error checking submodule config (detached HEAD)")
return (
True,
f"Repo at '{target_ref}' (Detached HEAD {detached_commit_sha}).",

View File

@ -43,6 +43,9 @@ class ToolRegistryEntry:
local_dir_name: Optional[str] = (
None # Optional custom name for the local directory in 'managed_tools'. Defaults to 'id' if None.
)
# --- Submodule support ---
auto_update_submodules: bool = False # If true, attempt to init/update submodules automatically
submodules: Optional[List[Dict[str, Any]]] = None
# --- Parameter Definition Source ---
# For type='local', this can be an inline list of parameter dicts.

View File

@ -0,0 +1,74 @@
"""projectutility.core.submodule_manager
Utilities to ensure Git submodules are initialized/updated for a tool repo.
This module uses the system `git` command via subprocess to avoid
adding a hard dependency on GitPython for submodule operations.
"""
import logging
import os
import subprocess
from typing import List, Optional, Dict
logger = logging.getLogger(__name__)
def ensure_submodules(
repo_root: str, submodules: Optional[List[Dict[str, str]]] = None, timeout: int = 300
) -> bool:
"""Ensure submodules are initialized and updated for a repository.
Args:
repo_root: absolute path to the repository root (where .git lives).
submodules: optional list of dicts describing submodules. Each dict may
contain a `path` key (relative path inside repo). If None,
this will attempt to update the whole `external` directory
if it exists, otherwise run a global submodule update.
timeout: max seconds to wait for the git command.
Returns:
True if git submodule update completed successfully, False otherwise.
"""
if not os.path.isdir(repo_root):
logger.error("Submodule update: repo_root not found: %s", repo_root)
return False
cmd = ["git", "-C", repo_root, "submodule", "update", "--init", "--recursive"]
# Build path list for git command
if submodules:
paths = []
for entry in submodules:
p = entry.get("path") if isinstance(entry, dict) else None
if p:
paths.append(p)
if paths:
cmd += paths
else:
# Fallback: if repo has 'external' directory, limit to it
external = os.path.join(repo_root, "external")
if os.path.isdir(external):
cmd += ["external"]
logger.info("Running submodule update: %s", " ".join(cmd))
try:
proc = subprocess.run(
cmd, check=True, capture_output=True, text=True, timeout=timeout
)
if proc.stdout:
logger.debug("git submodule stdout: %s", proc.stdout)
if proc.stderr:
logger.debug("git submodule stderr: %s", proc.stderr)
logger.info("Submodule update completed for %s", repo_root)
return True
except subprocess.CalledProcessError as e:
logger.error(
"git submodule update failed for %s: %s", repo_root, e.stderr or str(e)
)
return False
except subprocess.TimeoutExpired:
logger.error("git submodule update timeout for %s", repo_root)
return False
except Exception as e:
logger.exception("Unexpected error while updating submodules for %s: %s", repo_root, e)
return False

View File

@ -164,54 +164,6 @@ except ImportError as e:
)
# Ensure flag is False and constants remain dummies
GIT_ENABLED = False
# Define dummy class if import failed completely
class git_manager:
pass# ridefinito come dummy se fallisce import
# ... (definizione dummy di git_manager)
except Exception as e:
logging.getLogger(__name__).error(
f"Unexpected error importing git_manager: {e}. Git features disabled.",
exc_info=True
)
GIT_ENABLED = False
try:
# Absolute import
from projectutility.core import git_manager
GIT_ENABLED = git_manager.GITPYTHON_AVAILABLE
if GIT_ENABLED:
# Import real constants only if GitPython is available
from projectutility.core.git_manager import (
GIT_STATUS_UP_TO_DATE,
GIT_STATUS_BEHIND,
GIT_STATUS_AHEAD,
GIT_STATUS_DIVERGED,
GIT_STATUS_NOT_CLONED,
GIT_STATUS_ERROR,
GIT_STATUS_CHECKING,
GIT_STATUS_UPDATING,
GIT_STATUS_GITPYTHON_MISSING,
)
logging.getLogger(__name__).info(
"Successfully imported git_manager (GitPython available)."
)
else:
logging.getLogger(__name__).warning(
"Imported git_manager, but GitPython library not found. Git features disabled."
)
# Constants keep their default dummy values defined above
except ImportError as e:
logging.getLogger(__name__).error(
f"Failed to import core.git_manager: {e}. Git features disabled.", exc_info=True
)
# Ensure flag is False and constants remain dummies
GIT_ENABLED = False
# Define dummy class if import failed completely
class git_manager:
GITPYTHON_AVAILABLE = False
@ -238,7 +190,7 @@ except ImportError as e:
except Exception as e:
logging.getLogger(__name__).error(
f"Unexpected error importing git_manager: {e}. Git features disabled.",
exc_info=True,
exc_info=True
)
GIT_ENABLED = False