WikiMigrationScript_ChangeLog - itnett/FTD02H-N GitHub Wiki
Det er flott at vi har kommet i mål med migreringen av koden fra wiki til GitHub! La oss nå gå gjennom skriptet og prosessen steg for steg. Jeg vil forklare hver funksjon, utfordringene vi møtte, og hvordan vi løste dem, slik at du får en dypere forståelse av både Python-koden og hvordan Git fungerer.
1. Opprettelse av skriptet og konfigurasjonsfilen
input.yml
Konfigurasjonsfilen input.yml
brukes til å spesifisere viktige variabler som skriptet trenger for å fungere. Her definerer vi URL-ene for det gamle wiki-repositoriet, målkatalogene for koden, og hvor koden skal legges inn i GitHub.
wiki_repo_url: "https://github.com/itnett/FTD02H-N.wiki.git"
dump_directory: "C:\\WikiMigration\\git\\code_dump"
code_repo_url: "https://github.com/itnett/FTD02N"
code_repo_directory: "C:\\WikiMigration\\git\\code_repo"
wiki_repo_url
: URL til det gamle wiki-repositoriet som skal klones.dump_directory
: Katalogen hvor wiki-repoet klones midlertidig.code_repo_url
: URL til koden sitt GitHub-repo.code_repo_directory
: Katalogen hvor skriptene fra wiki-repoet skal lagres.
2. Logging og feilhåndtering
Vi setter opp logging slik at alle handlinger og feil i skriptet blir logget til en fil. Dette er nyttig for å kunne spore hva som skjer under kjøringen, spesielt når vi støter på feil.
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())
log(message)
: Logger en generell melding.log_exception(e)
: Logger en unntaksmelding og stacktrace for debugging.
3. Laste inn konfigurasjonen
Her laster vi inn konfigurasjonsfilen og validerer den for å sikre at alle nødvendige nøkler er til stede og at ingen av dem er tomme.
def load_input_config(file_path):
try:
with open(file_path, 'r', encoding='utf-8') 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.")
load_input_config(file_path)
: Leser inn konfigurasjonsfilen og validerer innholdet.validate_config(config)
: Sjekker at alle nødvendige nøkler er til stede og at de ikke er tomme.
4. Håndtering av skrivebeskyttede filer
For å sikre at vi kan slette skrivebeskyttede filer, implementerer vi en funksjon som endrer filtilgang før sletting.
def handle_remove_readonly(func, path, exc):
excvalue = exc[1]
if func in (os.rmdir, os.remove, os.unlink) and excvalue.errno == errno.EACCES:
os.chmod(path, stat.S_IRWXU)
func(path)
else:
raise
handle_remove_readonly(func, path, exc)
: Endrer filtilgang til skrivebeskyttet modus før sletting hvis nødvendig.
5. Kloning av wiki-repositoriet
Skriptet kloner wiki-repositoriet til en midlertidig katalog.
def clone_wiki_repo(wiki_repo_url, target_directory):
try:
if os.path.exists(target_directory):
shutil.rmtree(target_directory, onerror=handle_remove_readonly)
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
- Utfordring: Skrivebeskyttede filer førte til feil under sletting av kataloger. Dette ble løst ved å bruke
handle_remove_readonly
. - Løsning: Etter at funksjonen
handle_remove_readonly
ble implementert, ble problemet med å slette skrivebeskyttede filer løst.
6. Behandle wiki-filer og trekke ut kode
Denne funksjonen går gjennom alle markdown-filene i wiki-repositoriet, finner kodeblokker, trekker dem ut, og lagrer dem i riktig katalog. Samtidig oppdateres wiki-filene med lenker til den nye koden i GitHub-repositoriet.
def sanitize_filename(filename):
filename = re.sub(r'[<>:"/\\|?*]', '_', filename)
filename = filename[:100] # Begrens lengden til 100 tegn
return filename
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', encoding='utf-8') 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):
sanitized_file = sanitize_filename(f"{os.path.splitext(file)[0]}_snippet_{idx+1}.{lang}")
code_filepath = os.path.join(code_repo_dir, sanitized_file)
with open(code_filepath, 'w', encoding='utf-8') as code_file:
code_file.write(code.strip())
github_link = f"[{sanitized_file}]({code_repo_url}/blob/main/{sanitized_file})"
updated_content = updated_content.replace(f"```{lang}\n{code}```", github_link)
with open(wiki_filepath, 'w', encoding='utf-8') 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
- Utfordring: Lange filnavn og spesialtegn forårsaket problemer.
- Løsning: Implementerte funksjonen
sanitize_filename
som fjerner uønskede tegn og begrenser filnavnene til 100 tegn.
7. Oppdatere changelog
For å holde styr på endringer, oppdateres en changelog-fil med alle endringer som gjøres.
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', encoding='utf-8') 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
update_changelog(code_repo_dir, log_message)
: Legger til en ny linje iCHANGELOG.md
med en beskrivelse av hva som ble endret.
8. Git-operasjoner
Til slutt gjør vi Git-operasjoner som å initiere et nytt repo (om nødvendig), legge til filer i staging, og comitte endringer.
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
init_commit_code_repo(code_repo_dir, commit_message)
: Initialiserer Git-repoet, legger til filer i staging, og comitter med en melding.
9. **Oppsummering av
endringer**
Endringer og forbedringer gjort under utviklingen:
- Versjon 1.1 til 1.6: Håndterte problemer med skrivebeskyttede filer, feil i Git-kloning, lange filnavn, og spesialtegn i filnavn.
- Versjon 1.6: Optimalisering av filnavn og sikker håndtering av skrivebeskyttede filer. Lagt til logging for bedre feilsøking.
Dette skriptet gir deg nå en robust løsning for å migrere kode fra wiki til GitHub på en ryddig måte, med fullstendig logging og feilrapportering. Hvis du trenger mer hjelp med Git eller Python, kan jeg gjerne gi deg videre opplæring eller veiledning.