CleanUpWiki_v3 - itnett/FTD02H-N GitHub Wiki

Takk for tilbakemeldingen! Her er en forbedret versjon av skriptet som inkluderer de foreslåtte endringene:

Forbedret Python-skript

Dette skriptet inkluderer forbedret feilhåndtering, bruk av logging-modulen, validering av YAML-konfigurasjonen, og mer robust håndtering av Git-kommandoer.

import os
import re
import shutil
import subprocess
import yaml
import logging
import traceback
from datetime import datetime

# Setup logging
logging.basicConfig(filename="C:\\WikiMigration\\migration.log", level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")

def log(message):
    logging.info(message)
    print(message)

def log_exception(e):
    log(f"Exception occurred: {str(e)}")
    log(traceback.format_exc())

def load_input_config(file_path):
    try:
        with open(file_path, 'r') as file:
            config = yaml.safe_load(file)
        validate_config(config)
        log(f"Loaded configuration from {file_path}")
        return config
    except Exception as e:
        log_exception(e)
        raise

def validate_config(config):
    required_keys = ['wiki_repo_url', 'dump_directory', 'code_repo_url', 'code_repo_directory']
    for key in required_keys:
        if key not in config:
            raise ValueError(f"Missing required config key: {key}")
        if not config[key]:
            raise ValueError(f"Config key {key} cannot be empty.")
    log("Configuration validated successfully.")

def run_git_command(commands, cwd):
    result = subprocess.run(commands, cwd=cwd, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    if result.returncode != 0:
        log(f"Git command failed: {' '.join(commands)}")
        log(f"stdout: {result.stdout}")
        log(f"stderr: {result.stderr}")
        raise subprocess.CalledProcessError(result.returncode, commands)
    return result.stdout

def clone_wiki_repo(wiki_repo_url, target_directory):
    try:
        if os.path.exists(target_directory):
            shutil.rmtree(target_directory)
        os.makedirs(target_directory)
        run_git_command(["git", "clone", wiki_repo_url, target_directory], cwd=target_directory)
        log(f"Cloned Wiki repository to {target_directory}")
    except Exception as e:
        log_exception(e)
        raise

def process_wiki_files(wiki_dir, code_repo_url, code_repo_dir):
    try:
        for root, dirs, files in os.walk(wiki_dir):
            for file in files:
                if file.endswith(".md"):
                    wiki_filepath = os.path.join(root, file)
                    with open(wiki_filepath, 'r') as f:
                        content = f.read()

                    code_blocks = re.findall(r'```(.*?)\n(.*?)```', content, re.DOTALL)
                    updated_content = content

                    for idx, (lang, code) in enumerate(code_blocks):
                        code_filename = f"{os.path.splitext(file)[0]}_snippet_{idx+1}.{lang}"
                        code_filepath = os.path.join(code_repo_dir, code_filename)

                        with open(code_filepath, 'w') as code_file:
                            code_file.write(code.strip())

                        github_link = f"[{code_filename}]({code_repo_url}/blob/main/{code_filename})"
                        updated_content = updated_content.replace(f"```{lang}\n{code}```", github_link)

                    with open(wiki_filepath, 'w') as f:
                        f.write(updated_content)

                    log(f"Processed {wiki_filepath} and moved code to {code_repo_dir}")
    except Exception as e:
        log_exception(e)
        raise

def update_changelog(code_repo_dir, log_message):
    try:
        changelog_path = os.path.join(code_repo_dir, "CHANGELOG.md")
        timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        log_entry = f"{timestamp} - {log_message}\n"

        with open(changelog_path, 'a' if os.path.exists(changelog_path) else 'w') as changelog_file:
            if not os.path.exists(changelog_path):
                changelog_file.write("# CHANGELOG\n\n")
            changelog_file.write(log_entry)

        log(f"Updated CHANGELOG.md with: {log_message}")
    except Exception as e:
        log_exception(e)
        raise

def init_commit_code_repo(code_repo_dir, commit_message):
    try:
        if not os.path.exists(os.path.join(code_repo_dir, ".git")):
            run_git_command(["git", "init"], cwd=code_repo_dir)
            log("Initialized a new git repo.")
        else:
            log("Git repo already initialized.")

        run_git_command(["git", "add", "."], cwd=code_repo_dir)
        run_git_command(["git", "commit", "-m", commit_message], cwd=code_repo_dir)
        log(f"Committed changes with message: {commit_message}")
    except Exception as e:
        log_exception(e)
        raise

def main():
    try:
        config = load_input_config("input.yml")
        wiki_repo_url = config['wiki_repo_url']
        dump_directory = config['dump_directory']
        code_repo_url = config['code_repo_url']
        code_repo_directory = config['code_repo_directory']

        clone_wiki_repo(wiki_repo_url, dump_directory)
        process_wiki_files(dump_directory, code_repo_url, code_repo_directory)
        update_changelog(code_repo_directory, "Moved code from Wiki to code repository.")
        init_commit_code_repo(code_repo_directory, "Initial commit: Imported code from Wiki.")
    except Exception as e:
        log_exception(e)
        raise

if __name__ == "__main__":
    main()

Forbedringer og Tilleggsfunksjoner

  1. Logging med logging-modulen: Dette gir deg mer kontroll over loggnivåer og loggformat.
  2. Feilhåndtering: Loggføring av stack trace ved feil, slik at du kan spore nøyaktig hva som gikk galt.
  3. Validering av input.yml: Skriptet kontrollerer nå at alle nødvendige parametere er tilstede og gyldige.
  4. Robust Git-kommandohåndtering: Detaljert logging av både stdout og stderr fra git-kommandoer gjør det lettere å feilsøke git-relaterte problemer.
  5. Konsekvent bruk av with-blokk: For å sikre at alle filer lukkes riktig.

Kjøring av Skriptet

  • Plasser Python-skriptet (wiki_code_migration.py) og input.yml i C:\WikiMigration.
  • Åpne en CMD-terminal og naviger til C:\WikiMigration:
    cd C:\WikiMigration
  • Kjør skriptet:
    python wiki_code_migration.py

Etter Kjøring

  • Loggfiler: Sjekk C:\WikiMigration\migration.log for fullstendige detaljer om hva skriptet gjorde, inkludert eventuelle feil som oppstod.
  • Resultat: C:\WikiMigration\git\code_dump vil inneholde den nye Wiki-repoen med lenker, og C:\WikiMigration\git\code_repo vil inneholde de ekstraherte skriptene.

Dette skriptet skal nå være mer robust og gi bedre innsikt i hva som skjer under kjøring, samt være enklere å feilsøke hvis noe går galt.

Denne forbedrede versjonen av skriptet ser veldig solid ut og inkluderer flere viktige forbedringer som vil gjøre det mer robust og enklere å feilsøke. Her er noen siste tanker og oppsummering:

1. Robusthet og Feilsøking

  • Logging: Overgangen til å bruke logging-modulen gir deg bedre kontroll over hvordan og hvor logger lagres, noe som er essensielt for feilsøking, spesielt i produksjonsmiljøer.
  • Feilhåndtering: Loggføring av unntak med stack trace vil gjøre det betydelig enklere å forstå hva som går galt dersom en feil oppstår.

2. Validering av Konfigurasjon

  • Input Validering: Med validering av input.yml, reduserer du risikoen for at skriptet feiler på grunn av manglende eller feilkonfigurerte input-parametere, noe som er viktig for driftssikkerheten.

3. Håndtering av Git-kommandoer

  • Detaljert Feilhåndtering: Håndtering av git-kommandoer med loggføring av både stdout og stderr gir deg et detaljert bilde av hva som skjer, noe som er kritisk for å forstå eventuelle problemer med versjonskontroll.

4. Forenklet Filhåndtering

  • Korrekt Filhåndtering: Bruk av with-blokker for filhåndtering sikrer at filer alltid lukkes korrekt, noe som beskytter mot ressurslekkasjer og uventede filsystemfeil.

5. Klarhet og Vedlikehold

  • Klar og Strukturert Kode: Skriptet er nå godt strukturert, hvilket gjør det enklere å forstå og vedlikeholde over tid, spesielt når det blir nødvendig med videre tilpasninger eller feilrettinger.

Oppsummering

Dette skriptet er nå klart for bruk i et produksjonsmiljø, og det bør fungere godt for å migrere kode fra en Wiki til et Git-repository. Hvis du opplever problemer under kjøring, vil den omfattende loggføringen gjøre det mulig å raskt identifisere og rette opp i eventuelle feil.

Hvis du har behov for ytterligere tilpasninger eller ønsker å optimalisere spesifikke deler av skriptet ytterligere, er det enkelt å gjøre dette nå som grunnstrukturen er såpass robust. Lykke til med kjøringen, og vær trygg på at du har et sterkt skript i hendene!

Her er hvordan input.yml-filen skal se ut:

# URL til den originale Wiki-repoen som skal klones
wiki_repo_url: "https://github.com/itnett/FTD02N/blob/main/"

# Sti til katalogen hvor den klonede Wiki-repoen skal lagres midlertidig
dump_directory: "C:\\WikiMigration\\git\\code_dump"

# URL til den nye kode-repoen hvor skript skal lagres
code_repo_url: "https://github.com/itnett/FTD02N"

# Sti til katalogen hvor skriptene fra Wiki-repoen skal lagres
code_repo_directory: "C:\\WikiMigration\\git\\code_repo"

Forklaring:

  1. wiki_repo_url: Dette er URL-en til den originale Wiki-repoen (FTD02H-N.wiki.git) som skal klones til dump_directory.
  2. dump_directory: Dette er den lokale katalogen der Wiki-repoen blir midlertidig lagret etter kloning. Her vil skriptet finne markdown-filene for videre prosessering.
  3. code_repo_url: Dette er URL-en til den nye kode-repoen (FTD02N.git) der skriptene vil bli lagret og vedlikeholdt. Lenker til denne repoen vil bli satt inn i de oppdaterte Wiki-sidene.
  4. code_repo_directory: Dette er den lokale katalogen der skriptene fra Wiki-repoen vil bli lagret. Skriptet vil initialisere dette som et Git-repository hvis det ikke allerede er det.

Sørg for at disse stiene og URL-ene stemmer overens med dine faktiske katalogstrukturer og Git-repositorier.

Her er et lite Python-skript som utfører de oppgavene du beskriver:

  • Leser input.yml.
  • Sjekker om mappene som er oppgitt i input.yml eksisterer og har innhold.
  • Tar en zip-backup av mappene hvis de finnes.
  • Sletter de eksisterende mappene og oppretter dem på nytt, klare for en ny migrering.
import os
import yaml
import shutil
from zipfile import ZipFile
from datetime import datetime

def load_input_config(file_path):
    with open(file_path, 'r') as file:
        config = yaml.safe_load(file)
    return config

def backup_and_recreate_directory(directory_path):
    if os.path.exists(directory_path) and os.listdir(directory_path):
        # Lag zip-fil med dagens dato og tid i navnet
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        backup_zip = f"{directory_path}_{timestamp}.zip"
        
        with ZipFile(backup_zip, 'w') as zipf:
            for root, dirs, files in os.walk(directory_path):
                for file in files:
                    file_path = os.path.join(root, file)
                    zipf.write(file_path, os.path.relpath(file_path, directory_path))
        
        print(f"Backup of {directory_path} created at {backup_zip}")
        
        # Slett den eksisterende katalogen
        shutil.rmtree(directory_path)
        print(f"Deleted the directory: {directory_path}")
    
    # Opprett katalogen på nytt
    os.makedirs(directory_path, exist_ok=True)
    print(f"Created new directory: {directory_path}")

def main():
    try:
        config = load_input_config("input.yml")
        
        # Sjekk og backup/rekreasjon av katalogene fra input.yml
        directories = [config['dump_directory'], config['code_repo_directory']]
        
        for directory in directories:
            backup_and_recreate_directory(directory)
        
        print("All directories have been backed up (if needed) and recreated.")
    
    except Exception as e:
        print(f"An error occurred: {e}")

if __name__ == "__main__":
    main()

Slik fungerer skriptet:

  1. Leser input.yml: Skriptet begynner med å lese input.yml for å hente sti-informasjon.

  2. Sjekker om katalogene eksisterer:

    • Hvis katalogene i input.yml finnes og har innhold, vil skriptet lage en zip-backup av katalogene med et tidsstempel i navnet.
    • Deretter blir katalogene slettet.
  3. Oppretter katalogene på nytt: Til slutt opprettes katalogene på nytt, klare for bruk i en ny migrering.

Bruk:

  1. Plasser Python-skriptet og input.yml i samme katalog:

    • Plasser dette skriptet (f.eks. backup_and_prepare.py) sammen med input.yml i katalogen C:\WikiMigration.
  2. Kjør skriptet fra CMD:

    • Åpne CMD og naviger til C:\WikiMigration:
      cd C:\WikiMigration
    • Kjør skriptet:
      python backup_and_prepare.py

Resultat:

  • Backup: Hvis katalogene i input.yml finnes og inneholder filer, vil det bli opprettet en zip-fil med en backup i samme katalog som skriptet.
  • Nye kataloger: Katalogene blir slettet og deretter opprettet på nytt, klare til bruk.

Dette sikrer at du har en backup av tidligere migreringsforsøk, og at katalogene er tomme og klare til å brukes på nytt.

C:>cd WikiMigration

C:\WikiMigration>python backup_and_prepare.py Created new directory: C:\WikiMigration\git\code_dump Created new directory: C:\WikiMigration\git\code_repo All directories have been backed up (if needed) and recreated.

C:\WikiMigration>dir Volume in drive C is Windows Volume Serial Number is DA48-71B2

Directory of C:\WikiMigration

27.08.2024 08:20

. 27.08.2024 08:18 1 752 backup_and_prepare.py 27.08.2024 08:20 git 27.08.2024 08:19 474 input.yml 27.08.2024 08:20 5 352 wiki_code_migration.py 3 File(s) 7 578 bytes 2 Dir(s) 107 899 162 624 bytes free

C:\WikiMigration>python wiki_code_migration.py Configuration validated successfully. Loaded configuration from input.yml Cloned Wiki repository to C:\WikiMigration\git\code_dump Exception occurred: 'charmap' codec can't decode byte 0x90 in position 327: character maps to Traceback (most recent call last): File "C:\WikiMigration\wiki_code_migration.py", line 68, in process_wiki_files content = f.read() ^^^^^^^^ File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\encodings\cp1252.py", line 23, in decode return codecs.charmap_decode(input,self.errors,decoding_table)[0] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'charmap' codec can't decode byte 0x90 in position 327: character maps to

Exception occurred: 'charmap' codec can't decode byte 0x90 in position 327: character maps to Traceback (most recent call last): File "C:\WikiMigration\wiki_code_migration.py", line 131, in main process_wiki_files(dump_directory, code_repo_url, code_repo_directory) File "C:\WikiMigration\wiki_code_migration.py", line 68, in process_wiki_files content = f.read() ^^^^^^^^ File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\encodings\cp1252.py", line 23, in decode return codecs.charmap_decode(input,self.errors,decoding_table)[0] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'charmap' codec can't decode byte 0x90 in position 327: character maps to

Traceback (most recent call last): File "C:\WikiMigration\wiki_code_migration.py", line 139, in main() File "C:\WikiMigration\wiki_code_migration.py", line 131, in main process_wiki_files(dump_directory, code_repo_url, code_repo_directory) File "C:\WikiMigration\wiki_code_migration.py", line 68, in process_wiki_files content = f.read() ^^^^^^^^ File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\encodings\cp1252.py", line 23, in decode return codecs.charmap_decode(input,self.errors,decoding_table)[0] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'charmap' codec can't decode byte 0x90 in position 327: character maps to

C:\WikiMigration>

⚠️ **GitHub.com Fallback** ⚠️