CleanUpWiki_v4 - itnett/FTD02H-N GitHub Wiki
Feilmeldingen UnicodeDecodeError: 'charmap' codec can't decode byte 0x90
oppstår fordi Python forsøker å lese en fil som inneholder tegn som ikke støttes av standard Windows-koding (cp1252
). Dette skjer ofte når filene inneholder spesialtegn eller ikke-ASCII-tegn, som kan være tilfellet med noen av markdown-filene i din Wiki-repo.
Løsning
Du kan løse dette ved å spesifisere en mer fleksibel koding når du åpner filene. UTF-8 er en god standard som støtter et bredere spekter av tegnsett.
Her er hvordan du kan oppdatere koden din for å bruke UTF-8-koding når du leser filene:
Oppdatert Python-skript
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', 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.")
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', 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):
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', encoding='utf-8') 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', 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
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
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()
Endringer som er gjort:
encoding='utf-8'
er lagt til iopen()
-funksjonene som leser og skriver filer, for å sikre at filene blir behandlet som UTF-8, som støtter et bredere spekter av tegnsett enn standard Windows-koding (cp1252
).
Kjøring av Skriptet
- Naviger til
C:\WikiMigration
i CMD. - Kjør skriptet igjen:
python wiki_code_migration.py
Dette bør løse UnicodeDecodeError
-feilen og tillate skriptet å behandle alle filer korrekt, uavhengig av spesialtegn.
Ja, vi kan teste om problemet med tillatelser skyldes skrivebeskyttelse eller andre tillatelser ved å bruke en enkel Python "one-liner" i CMD. Dette vil hjelpe oss å bekrefte om løsningen med handle_remove_readonly
fungerer som forventet.
Testing med en enkel "one-liner"
-
Åpne CMD som administrator:
- Dette sikrer at du har de nødvendige tillatelsene til å endre filattributter og slette filer.
-
Naviger til katalogen som inneholder filen:
cd C:\WikiMigration\git\code_dump\.git\objects\pack
-
Kjør følgende Python "one-liner" for å teste sletting av filen med skrivebeskyttelse:
python -c "import os, stat; os.chmod('pack-08be10109a296bd725ba4aaccddaa5ac7633f6b5.idx', stat.S_IWRITE); os.remove('pack-08be10109a296bd725ba4aaccddaa5ac7633f6b5.idx')"
Forklaring av "one-liner":
-
os.chmod('pack-08be10109a296bd725ba4aaccddaa5ac7633f6b5.idx', stat.S_IWRITE)
: Denne linjen endrer tillatelsen på filenpack-08be10109a296bd725ba4aaccddaa5ac7633f6b5.idx
slik at den kan skrives til (og dermed slettes). -
os.remove('pack-08be10109a296bd725ba4aaccddaa5ac7633f6b5.idx')
: Denne linjen forsøker å slette filen etter at tillatelsen er endret.
Forventet resultat:
-
Hvis denne "one-liner" fungerer uten feil, vil filen
pack-08be10109a296bd725ba4aaccddaa5ac7633f6b5.idx
bli slettet, noe som bekrefter at løsningen medhandle_remove_readonly
er riktig. -
Hvis du fortsatt får en
PermissionError
, er problemet sannsynligvis relatert til noe annet, som et program som bruker filen, eller noe som krever videre undersøkelse.
Etter testing:
-
Hvis slettingen fungerer, kan du trygt implementere
handle_remove_readonly
i ditt skript for å håndtere lignende problemer med tillatelser. -
Hvis slettingen mislykkes, bør vi undersøke andre potensielle årsaker til problemet, som f.eks. at filen er i bruk av et annet program.