""" Git Push via dulwich (kein git binary noetig). Liest Token aus .secrets, committed Aenderungen und pusht. Usage: python project-audit/scripts/git-push.py "Commit-Nachricht" python project-audit/scripts/git-push.py (nutzt Standard-Nachricht) """ import os import sys from pathlib import Path from dulwich import porcelain from dulwich.repo import Repo REPO_PATH = Path(__file__).parent.parent # project-audit/ SECRETS_PATH = REPO_PATH / ".secrets" REMOTE_URL = "https://git.tech.rz.db.de/AndreKnie/project-audit.git" def load_token(): """Liest GITLAB_TOKEN_AUDIT aus .secrets Datei.""" if not SECRETS_PATH.exists(): print(f"FEHLER: {SECRETS_PATH} nicht gefunden!") print("Erstelle die Datei mit: GITLAB_TOKEN_AUDIT=dein_token") sys.exit(1) with open(SECRETS_PATH, "r", encoding="utf-8-sig") as f: for line in f: line = line.strip() if line.startswith("GITLAB_TOKEN_AUDIT="): val = line.split("=", 1)[1].strip() if val and val != "HIER_TOKEN_EINTRAGEN": return val print("FEHLER: GITLAB_TOKEN_AUDIT nicht in .secrets gesetzt!") print("Trage deinen Token ein: GITLAB_TOKEN_AUDIT=glpat-xxxxx") sys.exit(1) def get_ignore_patterns(): """Liest .gitignore Patterns.""" patterns = [] gitignore = REPO_PATH / ".gitignore" if gitignore.exists(): with open(gitignore, "r") as f: for line in f: line = line.strip() if line and not line.startswith("#"): patterns.append(line.strip("/")) return patterns def should_ignore(rel_path, patterns): """Prueft ob Datei ignoriert werden soll.""" rel_str = str(rel_path).replace("\\", "/") for p in patterns: if p in rel_str: return True return False def main(): message = " ".join(sys.argv[1:]) if len(sys.argv) > 1 else "Update pathOS Audit" print(f"=== Git Push: {message} ===") print(f" Repo: {REPO_PATH}") print(f" Remote: {REMOTE_URL}") # Token laden token = load_token() print(f" Token: ...{token[-4:]}") # Repo oeffnen if not (REPO_PATH / ".git").exists(): print(" Kein Repo gefunden, initialisiere...") Repo.init(str(REPO_PATH)) # Alle Dateien stagen (neue + geaenderte) print(" Stage Aenderungen...") patterns = get_ignore_patterns() staged = 0 for root, dirs, files in os.walk(REPO_PATH): if ".git" in root: continue for fname in files: full_path = Path(root) / fname rel_path = full_path.relative_to(REPO_PATH) if should_ignore(rel_path, patterns): continue try: porcelain.add(str(REPO_PATH), paths=[str(rel_path)]) staged += 1 except Exception: pass print(f" {staged} Dateien gestaged") # Commit print(f" Commit: {message}") try: porcelain.commit( str(REPO_PATH), message=message.encode("utf-8"), author=b"Andre Knie ", committer=b"Andre Knie " ) except Exception as e: if "nothing to commit" in str(e).lower(): print(" Keine Aenderungen zum Committen.") return print(f" Commit-Fehler: {e}") # Push print(" Push zu origin...") try: porcelain.push( str(REPO_PATH), REMOTE_URL, refspecs=b"refs/heads/master:refs/heads/master", username="AndreKnie", password=token ) print(" PUSH ERFOLGREICH!" ) except Exception as e: print(f" Push-Fehler: {e}") print(" Tipp: Pruefen ob das Remote-Repo existiert und der Token Schreibrechte hat.") if __name__ == "__main__": main()