Просмотр исходного кода

[#1] Configure mirror repositories and dynamic git filter sanitization

This commit adds worldwide GitHub repository references to all guides and implements dynamic origin URL detail extraction and name sanitization in git-ident-filter.py.
Lange François 3 недель назад
Родитель
Сommit
2130fa44fb

+ 9 - 1
INSTALL_WSL.md

@@ -1,4 +1,4 @@
-The current version is #ident "@(#)$Format:LocalFoodAI:INSTALL_WSL.md:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
+The current version is #ident "@(#)$Format:LocalFoodAI_lanfr144:INSTALL_WSL.md:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
 
 
 # 🚀 WSL2 Port-Shifted Installation Guide (Local Food AI)
 # 🚀 WSL2 Port-Shifted Installation Guide (Local Food AI)
 
 
@@ -29,11 +29,19 @@ Ensure you have WSL2 enabled and are using an Ubuntu 24.04 shell instance.
 
 
 ### Step 2: Clone the Git Repository
 ### Step 2: Clone the Git Repository
 Run the following commands inside your WSL Ubuntu home directory to clone the project:
 Run the following commands inside your WSL Ubuntu home directory to clone the project:
+
+**Primary Repository (Internal Network)**:
 ```bash
 ```bash
 git clone https://git.btshub.lu/lanfr/LocalFoodAI_lanfr144.git
 git clone https://git.btshub.lu/lanfr/LocalFoodAI_lanfr144.git
 cd LocalFoodAI_lanfr144
 cd LocalFoodAI_lanfr144
 ```
 ```
 
 
+**Alternative Repository (Worldwide Access - Clone of the Primary)**:
+```bash
+git clone https://github.com/lanfr144/LocalFoodAI_lanfr144.git
+cd LocalFoodAI_lanfr144
+```
+
 ### Step 3: Setup Local Environment Variables
 ### Step 3: Setup Local Environment Variables
 Create the required `.env` file at the root of the repository to feed standard local credentials to the containers:
 Create the required `.env` file at the root of the repository to feed standard local credentials to the containers:
 Configure your database credentials, active network mode, and the target model name in a `.env` file at the root of the repository. A generic template is provided below:
 Configure your database credentials, active network mode, and the target model name in a `.env` file at the root of the repository. A generic template is provided below:


+ 6 - 1
README.md

@@ -1,4 +1,4 @@
-The current version is #ident "@(#)$Format:LocalFoodAI:README.md:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
+The current version is #ident "@(#)$Format:LocalFoodAI_lanfr144:README.md:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
 
 
 # Local Food AI 🍔
 # Local Food AI 🍔
 
 
@@ -38,7 +38,12 @@ This project is fully optimized to run on Windows Subsystem for Linux (WSL2) wit
    Navigate to the repository home directory inside WSL:
    Navigate to the repository home directory inside WSL:
    ```bash
    ```bash
    cd ~
    cd ~
+   # Option A: Clone from the Primary Repository (Internal Network)
    git clone https://git.btshub.lu/lanfr/LocalFoodAI_lanfr144.git
    git clone https://git.btshub.lu/lanfr/LocalFoodAI_lanfr144.git
+   
+   # Option B: Clone from the Alternative Repository (Worldwide Access - Clone)
+   # git clone https://github.com/lanfr144/LocalFoodAI_lanfr144.git
+   
    cd LocalFoodAI_lanfr144
    cd LocalFoodAI_lanfr144
    
    
    # Always ensure you are on the primary main branch:
    # Always ensure you are on the primary main branch:

BIN
Retro Planning.pdf


BIN
docs/Backup_Procedure.pdf


BIN
docs/Data_Ingestion.pdf


BIN
docs/Final_Report.pdf


+ 2 - 2
docs/Installation_Guide.md

@@ -118,8 +118,8 @@ q" | sudo ed /etc/wsl.conf
 ## 4. Repository Clones & Branch Governance
 ## 4. Repository Clones & Branch Governance
 
 
 There are two repositories configured for this project:
 There are two repositories configured for this project:
-- Production Repository: `https://git.btshub.lu/lanfr/LocalFoodAI_lanfr144.git`
-- GitHub Mirror (Clone): `https://github.com/lanfr144/LocalFoodAI_lanfr144`
+- Primary Git Repository: `https://git.btshub.lu/lanfr/LocalFoodAI_lanfr144.git`
+- Alternative Git Repository (Worldwide Access - Clone): `https://github.com/lanfr144/LocalFoodAI_lanfr144.git`
 
 
 Clone the primary repository inside your home directory:
 Clone the primary repository inside your home directory:
 ```bash
 ```bash

BIN
docs/Installation_Guide.pdf


BIN
docs/Operator_Installation_Guide.pdf


BIN
docs/Scrum_Artifacts.pdf


BIN
docs/Scrum_Daily.pdf


BIN
docs/Scrum_Plan.pdf


BIN
docs/Scrum_Retro.pdf


BIN
docs/Scrum_Review.pdf


BIN
docs/Scrum_Wiki.pdf


BIN
docs/Start_Stop_Procedures.pdf


BIN
docs/Technical_Document.pdf


BIN
docs/Test_Cases_Sprint8.pdf


BIN
docs/URL_Formats.pdf


BIN
docs/User_Description.pdf


BIN
docs/User_Guide.pdf


BIN
docs/WSL_Deployment.pdf


BIN
docs/Wiki_Home.pdf


BIN
docs/architecture.pdf


BIN
docs/disaster_recovery_plan.pdf


BIN
docs/distributed_deployment.pdf


BIN
docs/docker_connection.pdf


BIN
docs/project_report.pdf


BIN
docs/retro_planning.pdf


BIN
docs/taiga_audit_report.pdf


BIN
docs/zabbix_monitoring.pdf


+ 4 - 4
generate_docs.py

@@ -1,9 +1,9 @@
-#ident "@(#)$Format:LocalFoodAI:generate_docs.py:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
+#ident "@(#)$Format:LocalFoodAI_lanfr144:generate_docs.py:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
 # $Id$
 # $Id$
 # $Author$
 # $Author$
 # $log$
 # $log$
 import os
 import os
-#ident "@(#)$Format:LocalFoodAI:generate_docs.py:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
+#ident "@(#)$Format:LocalFoodAI_lanfr144:generate_docs.py:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
 import subprocess
 import subprocess
 
 
 docs_dir = "docs"
 docs_dir = "docs"
@@ -278,8 +278,8 @@ q" | sudo ed /etc/wsl.conf
 ## 4. Repository Clones & Branch Governance
 ## 4. Repository Clones & Branch Governance
 
 
 There are two repositories configured for this project:
 There are two repositories configured for this project:
-- Production Repository: `https://git.btshub.lu/lanfr/LocalFoodAI_lanfr144.git`
-- GitHub Mirror (Clone): `https://github.com/lanfr144/LocalFoodAI_lanfr144`
+- Primary Git Repository: `https://git.btshub.lu/lanfr/LocalFoodAI_lanfr144.git`
+- Alternative Git Repository (Worldwide Access - Clone): `https://github.com/lanfr144/LocalFoodAI_lanfr144.git`
 
 
 Clone the primary repository inside your home directory:
 Clone the primary repository inside your home directory:
 ```bash
 ```bash

+ 41 - 45
local_tools/git-ident-filter.py

@@ -1,5 +1,5 @@
 #!/usr/bin/env python
 #!/usr/bin/env python
-#ident "@(#)$Format:LocalFoodAI:git-ident-filter.py:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
+#ident "@(#)$Format:LocalFoodAI_lanfr144:git-ident-filter.py:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
 import sys
 import sys
 import os
 import os
 import subprocess
 import subprocess
@@ -17,23 +17,44 @@ if hasattr(sys.stdin, 'reconfigure'):
 if hasattr(sys.stdout, 'reconfigure'):
 if hasattr(sys.stdout, 'reconfigure'):
     sys.stdout.reconfigure(newline='\n')
     sys.stdout.reconfigure(newline='\n')
 
 
+# -----------------------------------------------------------------------------
 # -----------------------------------------------------------------------------
 # -----------------------------------------------------------------------------
 # STEP 2: PARSE COMMAND LINE ARGUMENTS
 # STEP 2: PARSE COMMAND LINE ARGUMENTS
 # -----------------------------------------------------------------------------
 # -----------------------------------------------------------------------------
-# The Git configuration passes arguments to this script:
-# sys.argv[1] is either 'clean' or 'smudge' (determining execution mode)
-# sys.argv[2] (for smudge mode) is the relative file path of the file being smudged
 mode = sys.argv[1] if len(sys.argv) > 1 else "smudge"
 mode = sys.argv[1] if len(sys.argv) > 1 else "smudge"
 
 
 # -----------------------------------------------------------------------------
 # -----------------------------------------------------------------------------
-# STEP 3: DEFINE METADATA RETRIEVAL FUNCTION
+# STEP 3: HELPERS FOR DYNAMIC DETAILS & SANITIZATION
+# -----------------------------------------------------------------------------
+def sanitize_name(name):
+    """Standardizes variations of Lange Francois to a safe ASCII format, preventing charset decode errors."""
+    if not name:
+        return "Francois Lange"
+    name_lower = name.lower()
+    if "fran" in name_lower or "lange" in name_lower or "lanfr" in name_lower:
+        return "Francois Lange"
+    return name
+
+def get_git_repo_details():
+    """Extracts username and project name dynamically from the origin git remote URL."""
+    try:
+        url = subprocess.check_output(["git", "remote", "get-url", "origin"], stderr=subprocess.DEVNULL).decode().strip()
+        # Parse username and project name (e.g. from https://git.btshub.lu/lanfr/LocalFoodAI_lanfr144.git)
+        match = re.search(r'[:/]([^:/]+)/([^/]+?)(?:\.git)?$', url)
+        if match:
+            username = match.group(1)
+            project_name = match.group(2)
+            return username, project_name
+    except Exception:
+        pass
+    return "lanfr", "LocalFoodAI_lanfr144"
+
+# -----------------------------------------------------------------------------
+# STEP 4: DEFINE METADATA RETRIEVAL FUNCTION
 # -----------------------------------------------------------------------------
 # -----------------------------------------------------------------------------
 def get_git_info(file_path):
 def get_git_info(file_path):
     """Retrieves commit metadata for the specific file using git log, or falls back to system context."""
     """Retrieves commit metadata for the specific file using git log, or falls back to system context."""
     try:
     try:
-        # A. Query git log for the last commit details of the specific file.
-        # We specify the YYYY/MM/DD HH:MM:SS format using '--date=format:...'.
-        # We use a pipe '|' delimiter to separate fields in the output format.
         cmd = [
         cmd = [
             "git", "log", "-1",
             "git", "log", "-1",
             "--date=format:%Y/%m/%d %H:%M:%S",
             "--date=format:%Y/%m/%d %H:%M:%S",
@@ -41,55 +62,42 @@ def get_git_info(file_path):
             "--", file_path
             "--", file_path
         ]
         ]
         
         
-        # Run the git command, capture stdout, ignore stderr, decode bytes to string.
         out = subprocess.check_output(cmd, stderr=subprocess.DEVNULL).decode('utf-8', errors='ignore').strip()
         out = subprocess.check_output(cmd, stderr=subprocess.DEVNULL).decode('utf-8', errors='ignore').strip()
         if out:
         if out:
-            # Split the pipe-delimited string back into an array of fields
             parts = out.split('|')
             parts = out.split('|')
             if len(parts) == 9:
             if len(parts) == 9:
+                parts[0] = sanitize_name(parts[0])
+                parts[3] = sanitize_name(parts[3])
                 return parts
                 return parts
     except Exception:
     except Exception:
-        # If git log fails (e.g., file not tracked yet), proceed to fallback logic below.
         pass
         pass
     
     
-    # B. Fallback: Query local Git configuration if file is not committed yet.
+    author_name = "Francois Lange"
     try:
     try:
-        # Retrieve the user's local git user.name
-        author_name = subprocess.check_output(["git", "config", "user.name"], stderr=subprocess.DEVNULL).decode('utf-8', errors='ignore').strip() or "system"
-        # Retrieve the user's local git user.email
-        author_email = subprocess.check_output(["git", "config", "user.email"], stderr=subprocess.DEVNULL).decode('utf-8', errors='ignore').strip() or "system@mail.com"
+        author_email = subprocess.check_output(["git", "config", "user.email"], stderr=subprocess.DEVNULL).decode('utf-8', errors='ignore').strip() or "lanfr144@school.lu"
     except Exception:
     except Exception:
-        # If Git is not installed or configured, fallback to default system strings.
-        author_name = "system"
-        author_email = "system@mail.com"
+        author_email = "lanfr144@school.lu"
         
         
-    # Get current system date & time formatted consistently
     now_str = datetime.now().strftime("%Y/%m/%d %H:%M:%S")
     now_str = datetime.now().strftime("%Y/%m/%d %H:%M:%S")
-    # Return placeholder list in the same structure as git log output
     return [author_name, author_email, now_str, author_name, author_email, now_str, "Not Committed Yet", "local", "none"]
     return [author_name, author_email, now_str, author_name, author_email, now_str, "Not Committed Yet", "local", "none"]
 
 
 # -----------------------------------------------------------------------------
 # -----------------------------------------------------------------------------
-# STEP 4: EXECUTE SPECIFIED FILTER MODE
+# STEP 5: EXECUTE SPECIFIED FILTER MODE
 # -----------------------------------------------------------------------------
 # -----------------------------------------------------------------------------
 if mode == "clean":
 if mode == "clean":
     # -------------------------------------------------------------------------
     # -------------------------------------------------------------------------
     # CLEAN MODE (Staging phase / git add)
     # CLEAN MODE (Staging phase / git add)
     # -------------------------------------------------------------------------
     # -------------------------------------------------------------------------
-    # Read the file's contents directly from standard input (passed by Git)
     content = sys.stdin.read()
     content = sys.stdin.read()
-    
-    # Get the basename of the file being cleaned
     file_name = os.path.basename(sys.argv[2]) if len(sys.argv) > 2 else "app.py"
     file_name = os.path.basename(sys.argv[2]) if len(sys.argv) > 2 else "app.py"
     
     
-    # Non-greedy substitution to restore standard placeholder format for Git storage.
-    # We construct the search pattern and replacement dynamically to avoid matching our own code.
+    # Get project name dynamically from repo URL
+    _, project_name = get_git_repo_details()
+    
     pattern = r'\$F' + r'ormat:[^\r\n$]+\$'
     pattern = r'\$F' + r'ormat:[^\r\n$]+\$'
-    repl = f"$F" + f"ormat:LocalFoodAI:{file_name}:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
+    repl = f"$F" + f"ormat:{project_name}:{file_name}:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
     
     
-    # Run regular expression search and replace
     cleaned = re.sub(pattern, repl, content)
     cleaned = re.sub(pattern, repl, content)
-    
-    # Write the cleaned output directly to stdout so Git can write it to the index
     sys.stdout.write(cleaned)
     sys.stdout.write(cleaned)
 
 
 else:
 else:
@@ -97,31 +105,19 @@ else:
     # SMUDGE MODE (Checkout / pull phase)
     # SMUDGE MODE (Checkout / pull phase)
     # -------------------------------------------------------------------------
     # -------------------------------------------------------------------------
     try:
     try:
-        # Get absolute path of repository to find project directory name
-        toplevel = subprocess.check_output(["git", "rev-parse", "--show-toplevel"], stderr=subprocess.DEVNULL).decode().strip()
-        project_name = os.path.basename(toplevel)
+        # Get project details dynamically from repo URL
+        username, project_name = get_git_repo_details()
 
 
-        # Get the relative path of the file being smudged (passed as 2nd CLI arg by git configuration)
         file_name = sys.argv[2] if len(sys.argv) > 2 else "unknown_file"
         file_name = sys.argv[2] if len(sys.argv) > 2 else "unknown_file"
-
-        # Read the raw file content sent by Git on stdin
         content = sys.stdin.read()
         content = sys.stdin.read()
-
-        # Query git log metadata or local config fallbacks
         info = get_git_info(file_name)
         info = get_git_info(file_name)
 
 
-        # Format replacement string using dynamic project name and relative file path
-        # This replaces the placeholder metadata fields with actual git variables
         replacement = f"$F" + f"ormat:{project_name}:{os.path.basename(file_name)}:{info[0]}:{info[1]}:{info[2]}:{info[3]}:{info[4]}:{info[5]}:{info[6]}:{info[7]}:{info[8]}$"
         replacement = f"$F" + f"ormat:{project_name}:{os.path.basename(file_name)}:{info[0]}:{info[1]}:{info[2]}:{info[3]}:{info[4]}:{info[5]}:{info[6]}:{info[7]}:{info[8]}$"
 
 
         # Regex replacement targeting the dynamic format placeholders
         # Regex replacement targeting the dynamic format placeholders
-        # Pattern explanation: Matches "$Format:LocalFoodAI:git-ident-filter.py:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
         pattern = r'\$F' + r'ormat:[^:]+:[^:]+:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N\$'
         pattern = r'\$F' + r'ormat:[^:]+:[^:]+:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N\$'
         smudged = re.sub(pattern, replacement, content)
         smudged = re.sub(pattern, replacement, content)
-        
-        # Write smudged file contents to stdout so Git can output the file onto the filesystem
         sys.stdout.write(smudged)
         sys.stdout.write(smudged)
 
 
     except Exception:
     except Exception:
-        # Safety fallback: If execution fails (e.g. outside git repository), write stream unchanged
         sys.stdout.write(sys.stdin.read())
         sys.stdout.write(sys.stdin.read())

+ 92 - 0
scratch/add_mirror_repos.py

@@ -0,0 +1,92 @@
+import os
+
+# 1. Update INSTALL_WSL.md
+file1 = "INSTALL_WSL.md"
+if os.path.exists(file1):
+    with open(file1, "r", encoding="utf-8", errors="replace") as f:
+        content = f.read()
+    
+    old_clone_block = """### Step 2: Clone the Git Repository
+Run the following commands inside your WSL Ubuntu home directory to clone the project:
+```bash
+git clone https://git.btshub.lu/lanfr/LocalFoodAI_lanfr144.git
+cd LocalFoodAI_lanfr144
+```"""
+
+    new_clone_block = """### Step 2: Clone the Git Repository
+Run the following commands inside your WSL Ubuntu home directory to clone the project:
+
+**Primary Repository (Internal Network)**:
+```bash
+git clone https://git.btshub.lu/lanfr/LocalFoodAI_lanfr144.git
+cd LocalFoodAI_lanfr144
+```
+
+**Alternative Repository (Worldwide Access - Clone of the Primary)**:
+```bash
+git clone https://github.com/lanfr144/LocalFoodAI_lanfr144.git
+cd LocalFoodAI_lanfr144
+```"""
+
+    content = content.replace(old_clone_block, new_clone_block)
+    with open(file1, "w", encoding="utf-8") as f:
+        f.write(content)
+    print("Updated INSTALL_WSL.md with mirror repositories.")
+
+# 2. Update generate_docs.py
+file2 = "generate_docs.py"
+if os.path.exists(file2):
+    with open(file2, "r", encoding="utf-8", errors="replace") as f:
+        content = f.read()
+
+    # Update Installation_Guide.md section in generate_docs.py
+    old_install_repos = """There are two repositories configured for this project:
+- Production Repository: `https://git.btshub.lu/lanfr/LocalFoodAI_lanfr144.git`
+- GitHub Mirror (Clone): `https://github.com/lanfr144/LocalFoodAI_lanfr144`"""
+
+    new_install_repos = """There are two repositories configured for this project:
+- Primary Git Repository: `https://git.btshub.lu/lanfr/LocalFoodAI_lanfr144.git`
+- Alternative Git Repository (Worldwide Access - Clone): `https://github.com/lanfr144/LocalFoodAI_lanfr144.git`"""
+
+    content = content.replace(old_install_repos, new_install_repos)
+
+    # Update Technical_Document.md section in generate_docs.py
+    old_tech_repos = """- *Online Mode*: `git clone https://git.btshub.lu/lanfr/LocalFoodAI_lanfr144.git`"""
+    new_tech_repos = """- *Online Mode (Primary)*: `git clone https://git.btshub.lu/lanfr/LocalFoodAI_lanfr144.git`
+   - *Online Mode (Alternative/Worldwide)*: `git clone https://github.com/lanfr144/LocalFoodAI_lanfr144.git`"""
+
+    content = content.replace(old_tech_repos, new_tech_repos)
+
+    with open(file2, "w", encoding="utf-8") as f:
+        f.write(content)
+    print("Updated generate_docs.py with mirror repositories.")
+
+# 3. Update README.md
+file3 = "README.md"
+if os.path.exists(file3):
+    with open(file3, "r", encoding="utf-8", errors="replace") as f:
+        content = f.read()
+
+    old_readme_repos = """2. **Branch Checkout & App Setup (WSL Environment)**:
+   Navigate to the repository home directory inside WSL:
+   ```bash
+   cd ~
+   git clone https://git.btshub.lu/lanfr/LocalFoodAI_lanfr144.git
+   cd LocalFoodAI_lanfr144"""
+
+    new_readme_repos = """2. **Branch Checkout & App Setup (WSL Environment)**:
+   Navigate to the repository home directory inside WSL:
+   ```bash
+   cd ~
+   # Option A: Clone from the Primary Repository (Internal Network)
+   git clone https://git.btshub.lu/lanfr/LocalFoodAI_lanfr144.git
+   
+   # Option B: Clone from the Alternative Repository (Worldwide Access - Clone)
+   # git clone https://github.com/lanfr144/LocalFoodAI_lanfr144.git
+   
+   cd LocalFoodAI_lanfr144"""
+
+    content = content.replace(old_readme_repos, new_readme_repos)
+    with open(file3, "w", encoding="utf-8") as f:
+        f.write(content)
+    print("Updated README.md with mirror repositories.")