mirror of
https://github.com/migatu/vtt_work.git
synced 2026-07-14 13:34:42 +00:00
aa
This commit is contained in:
@@ -71,18 +71,37 @@ def copy_contents(src_dir: str, dst_dir: str):
|
|||||||
def git_has_staged_changes(repo: str) -> bool:
|
def git_has_staged_changes(repo: str) -> bool:
|
||||||
# Po "git add -A" sprawdzamy, czy coś jest w indexie
|
# Po "git add -A" sprawdzamy, czy coś jest w indexie
|
||||||
res = subprocess.run(["git", "diff", "--cached", "--quiet"], cwd=repo)
|
res = subprocess.run(["git", "diff", "--cached", "--quiet"], cwd=repo)
|
||||||
return res.returncode == 1 # 1 = są zmiany; 0 = brak; inne = błąd (ignorujemy tutaj)
|
return res.returncode == 1 # 1 = są zmiany; 0 = brak
|
||||||
|
|
||||||
def git_is_clean(repo: str) -> bool:
|
def git_is_clean(repo: str) -> bool:
|
||||||
res = run(["git", "status", "--porcelain"], cwd=repo, capture=True, check=False)
|
res = run(["git", "status", "--porcelain"], cwd=repo, capture=True, check=False)
|
||||||
return res.stdout.strip() == ""
|
return res.stdout.strip() == ""
|
||||||
|
|
||||||
|
def ensure_subdir(repo_root: str, subdir: str) -> str:
|
||||||
|
"""Zwraca absolutną ścieżkę docelowego podkatalogu w repo, tworząc go jeśli trzeba.
|
||||||
|
Zabezpiecza przed wychodzeniem poza repo (..)."""
|
||||||
|
target = repo_root
|
||||||
|
if subdir:
|
||||||
|
target = os.path.abspath(os.path.join(repo_root, subdir))
|
||||||
|
repo_root_abs = os.path.abspath(repo_root)
|
||||||
|
# Bezpieczeństwo: podkatalog musi być wewnątrz repo
|
||||||
|
if os.path.commonpath([target, repo_root_abs]) != repo_root_abs:
|
||||||
|
eprint(f"[BŁĄD] Niedozwolona ścieżka podkatalogu: {subdir}")
|
||||||
|
sys.exit(1)
|
||||||
|
os.makedirs(target, exist_ok=True)
|
||||||
|
return target
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description="Import archiwów ZIP do repozytorium git (od najstarszego), z commitami po każdym ZIPie."
|
description="Import archiwów ZIP do repozytorium git (od najstarszego), z commitami po każdym ZIPie."
|
||||||
)
|
)
|
||||||
parser.add_argument("--zip-dir", required=True, help="Katalog z plikami .zip")
|
parser.add_argument("--zip-dir", required=True, help="Katalog z plikami .zip")
|
||||||
parser.add_argument("--repo", required=True, help="Katalog repozytorium git (cel)")
|
parser.add_argument("--repo", required=True, help="Katalog repozytorium git (cel)")
|
||||||
|
parser.add_argument(
|
||||||
|
"--subdir",
|
||||||
|
default="",
|
||||||
|
help="Opcjonalny podkatalog w repo, do którego mają trafić pliki (utworzony jeśli nie istnieje).",
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--allow-dirty",
|
"--allow-dirty",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
@@ -97,6 +116,7 @@ def main():
|
|||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
zip_dir = os.path.abspath(args.zip_dir)
|
zip_dir = os.path.abspath(args.zip_dir)
|
||||||
repo = os.path.abspath(args.repo)
|
repo = os.path.abspath(args.repo)
|
||||||
|
subdir = args.subdir.strip()
|
||||||
|
|
||||||
if not os.path.isdir(zip_dir):
|
if not os.path.isdir(zip_dir):
|
||||||
eprint(f"[BŁĄD] Nie ma katalogu: {zip_dir}")
|
eprint(f"[BŁĄD] Nie ma katalogu: {zip_dir}")
|
||||||
@@ -108,6 +128,8 @@ def main():
|
|||||||
eprint(f"[BŁĄD] {repo} nie wygląda na repozytorium git (brak .git).")
|
eprint(f"[BŁĄD] {repo} nie wygląda na repozytorium git (brak .git).")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
target_dir = ensure_subdir(repo, subdir) # gdzie właściwie kopiujemy zawartość ZIPów
|
||||||
|
|
||||||
if not args.allow_dirty and not git_is_clean(repo):
|
if not args.allow_dirty and not git_is_clean(repo):
|
||||||
eprint("[BŁĄD] Repo nie jest czyste. Użyj --allow-dirty, jeśli chcesz mimo to kontynuować.")
|
eprint("[BŁĄD] Repo nie jest czyste. Użyj --allow-dirty, jeśli chcesz mimo to kontynuować.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@@ -117,7 +139,10 @@ def main():
|
|||||||
print("[INFO] Brak plików .zip do przetworzenia.")
|
print("[INFO] Brak plików .zip do przetworzenia.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
rel_target = os.path.relpath(target_dir, repo)
|
||||||
|
print(f"[INFO] Cel importu: {target_dir} (rel: {rel_target})")
|
||||||
print(f"[INFO] Znaleziono {len(zips)} archiwów .zip do przetworzenia (od najstarszego do najnowszego).")
|
print(f"[INFO] Znaleziono {len(zips)} archiwów .zip do przetworzenia (od najstarszego do najnowszego).")
|
||||||
|
|
||||||
for i, zip_path in enumerate(zips, start=1):
|
for i, zip_path in enumerate(zips, start=1):
|
||||||
zip_name = os.path.basename(zip_path)
|
zip_name = os.path.basename(zip_path)
|
||||||
mtime = datetime.fromtimestamp(os.path.getmtime(zip_path), tz=timezone.utc)
|
mtime = datetime.fromtimestamp(os.path.getmtime(zip_path), tz=timezone.utc)
|
||||||
@@ -126,10 +151,10 @@ def main():
|
|||||||
print(f"\n=== [{i}/{len(zips)}] {zip_name} (mtime: {mtime_iso}) ===")
|
print(f"\n=== [{i}/{len(zips)}] {zip_name} (mtime: {mtime_iso}) ===")
|
||||||
|
|
||||||
if args.dry_run:
|
if args.dry_run:
|
||||||
print(f"[DRY-RUN] Rozpakowałbym {zip_name} i zrobił commit.")
|
print(f"[DRY-RUN] Rozpakowałbym {zip_name} do '{rel_target}' i zrobił commit.")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Rozpakuj najpierw do katalogu tymczasowego
|
# Rozpakuj do katalogu tymczasowego (stage)
|
||||||
stage_dir = tempfile.mkdtemp(prefix="zipstage_")
|
stage_dir = tempfile.mkdtemp(prefix="zipstage_")
|
||||||
try:
|
try:
|
||||||
with zipfile.ZipFile(zip_path, "r") as zf:
|
with zipfile.ZipFile(zip_path, "r") as zf:
|
||||||
@@ -139,32 +164,30 @@ def main():
|
|||||||
shutil.rmtree(stage_dir, ignore_errors=True)
|
shutil.rmtree(stage_dir, ignore_errors=True)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# BONUS: wykrywanie rekursywne struktury katalogów z module.json
|
# BONUS: wykrywanie rekursywne module.json
|
||||||
stage_root_mjson = os.path.join(stage_dir, "module.json")
|
stage_root_mjson = os.path.join(stage_dir, "module.json")
|
||||||
|
effective_root = None
|
||||||
if os.path.isfile(stage_root_mjson):
|
if os.path.isfile(stage_root_mjson):
|
||||||
# idealnie: module.json już w korzeniu paczki
|
|
||||||
effective_root = stage_dir
|
effective_root = stage_dir
|
||||||
print("[OK] Wykryto module.json w korzeniu archiwum.")
|
print("[OK] Wykryto module.json w korzeniu archiwum.")
|
||||||
else:
|
else:
|
||||||
matches = find_module_json(stage_dir)
|
matches = find_module_json(stage_dir)
|
||||||
if len(matches) == 1:
|
if len(matches) == 1:
|
||||||
# jednoznaczny kandydat -> uznaj katalog z module.json za korzeń i skopiuj stamtąd
|
|
||||||
effective_root = os.path.dirname(matches[0])
|
effective_root = os.path.dirname(matches[0])
|
||||||
rel = os.path.relpath(effective_root, stage_dir)
|
rel = os.path.relpath(effective_root, stage_dir)
|
||||||
print(f"[BONUS] Wykryto zagnieżdżenie: module.json w '{rel}'. "
|
print(f"[BONUS] Wykryto zagnieżdżenie: module.json w '{rel}'. "
|
||||||
f"Kopiuję zawartość tego katalogu do repozytorium.")
|
f"Kopiuję zawartość tego katalogu do '{rel_target}'.")
|
||||||
else:
|
else:
|
||||||
# 0 lub >1 -> pauza i instrukcja ręczna
|
print("[UWAGA] Nie wykryto jednoznacznie położenia module.json (0 lub wiele wystąpień).")
|
||||||
print("[UWAGA] Nie wykryto jednoznacznie położenia module.json "
|
|
||||||
"(0 lub wiele wystąpień).")
|
|
||||||
if matches:
|
if matches:
|
||||||
print("Kandydaci:")
|
print("Kandydaci:")
|
||||||
for p in matches:
|
for p in matches:
|
||||||
print(f" - {os.path.relpath(p, stage_dir)}")
|
print(f" - {os.path.relpath(p, stage_dir)}")
|
||||||
print("\nProszę **ręcznie** przenieść/rozpakować pliki z poniższego katalogu tymczasowego")
|
print("\nProszę **ręcznie** przenieść/rozpakować pliki z poniższego katalogu tymczasowego")
|
||||||
print(f"do właściwego miejsca w repo: {repo}")
|
print(f"do właściwego miejsca w repo: {target_dir}")
|
||||||
print(f"Katalog tymczasowy: {stage_dir}")
|
print(f"Katalog tymczasowy: {stage_dir}")
|
||||||
print("Cel: po ułożeniu plików, w repo ma być poprawny układ projektu (typowo: module.json w korzeniu).")
|
print("Cel: po ułożeniu plików, w docelowym podkatalogu powinna być poprawna struktura (typowo: module.json w korzeniu).")
|
||||||
|
choice = ""
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
choice = input("Po wykonaniu zmian naciśnij [Enter], aby kontynuować, "
|
choice = input("Po wykonaniu zmian naciśnij [Enter], aby kontynuować, "
|
||||||
@@ -176,29 +199,24 @@ def main():
|
|||||||
if choice == "q":
|
if choice == "q":
|
||||||
print("Kończę działanie na życzenie użytkownika.")
|
print("Kończę działanie na życzenie użytkownika.")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
if choice == "s":
|
if choice in ("", "s"):
|
||||||
print("Pomijam to archiwum.")
|
|
||||||
shutil.rmtree(stage_dir, ignore_errors=True)
|
|
||||||
effective_root = None
|
|
||||||
break
|
break
|
||||||
# Enter -> spróbujmy zrobić commit tego, co jest w repo
|
|
||||||
effective_root = None # nic nie kopiujemy automatycznie
|
|
||||||
break
|
|
||||||
|
|
||||||
# jeśli pominięto
|
if choice == "s":
|
||||||
if effective_root is None and choice == "s":
|
print("Pomijam to archiwum.")
|
||||||
|
shutil.rmtree(stage_dir, ignore_errors=True)
|
||||||
continue
|
continue
|
||||||
|
# Enter -> nic nie kopiujemy automatycznie, zakładamy że użytkownik przeniósł co trzeba
|
||||||
|
|
||||||
# Jeśli mamy effective_root (auto), kopiujemy zawartość do repo
|
# Jeśli mamy effective_root (auto), kopiujemy zawartość do docelowego podkatalogu
|
||||||
if effective_root:
|
if effective_root:
|
||||||
copy_contents(effective_root, repo)
|
copy_contents(effective_root, target_dir)
|
||||||
|
|
||||||
# Git add + commit (jeśli są zmiany)
|
# Git add + commit (jeśli są zmiany) – commit z korzenia repo
|
||||||
run(["git", "add", "-A"], cwd=repo)
|
run(["git", "add", "-A"], cwd=repo)
|
||||||
if git_has_staged_changes(repo):
|
if git_has_staged_changes(repo):
|
||||||
msg = f"Import {zip_name} ({mtime_iso})"
|
msg = f"Import {zip_name} do {rel_target} ({mtime_iso})"
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
# Ustaw datę commita na mtime pliku ZIP (ładny, historyczny timeline)
|
|
||||||
env["GIT_AUTHOR_DATE"] = mtime_iso
|
env["GIT_AUTHOR_DATE"] = mtime_iso
|
||||||
env["GIT_COMMITTER_DATE"] = mtime_iso
|
env["GIT_COMMITTER_DATE"] = mtime_iso
|
||||||
run(["git", "commit", "-m", msg], cwd=repo, env=env)
|
run(["git", "commit", "-m", msg], cwd=repo, env=env)
|
||||||
@@ -210,6 +228,7 @@ def main():
|
|||||||
shutil.rmtree(stage_dir, ignore_errors=True)
|
shutil.rmtree(stage_dir, ignore_errors=True)
|
||||||
|
|
||||||
print("\n[ZAKOŃCZONE] Przetwarzanie archiwów .zip zakończone.")
|
print("\n[ZAKOŃCZONE] Przetwarzanie archiwów .zip zakończone.")
|
||||||
|
print(f"[INFO] Pliki zostały umieszczone w: {target_dir}")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user