#!/usr/bin/env python3 """Naprawa receptur dajacych puste pakiety / padajacych na install. Grupa A: autotools (build: cd ; configure; make) bez zadnej instalacji -> dopinamy 'make DESTDIR="${PKGDIR}" install' na koniec build:. Grupa B: faza package: robi 'make ... install' ale bez cd (faza startuje w katalogu kontenera zrodel) -> wstawiamy cd z fazy build. Uzycie: python3 fix-empty-packages.py [--apply] """ import os import re import sys import yaml APPLY = "--apply" in sys.argv changed = [] skipped = [] def literal_block_end(lines, i): """Zwraca indeks ostatniej linii bloku literalnego zaczynajacego sie w i.""" j = i + 1 while j < len(lines): line = lines[j] if line.strip() == "": j += 1 continue if line[0] in (" ", "\t"): j += 1 continue break return j - 1 # ostatnia linia bloku (mozliwe, ze pusta) for root, dirs, files in os.walk('recipes'): if '.git' in root or 'PAGBUILD.yaml' not in files: continue path = os.path.join(root, 'PAGBUILD.yaml') try: d = yaml.safe_load(open(path, encoding='utf-8')) or {} except Exception as e: skipped.append((path, "yaml-error: %s" % e)) continue build = d.get('build') or '' pkg = d.get('package') or '' if isinstance(build, list): build = '\n'.join(map(str, build)) if isinstance(pkg, list): pkg = '\n'.join(map(str, pkg)) blob = build + "\n" + pkg is_autotools = bool(re.search(r'(^|\n)\s*(\./)?configure\b', build)) has_cd = bool(re.search(r'(^|\n)\s*cd\s+\S+', build)) has_install = bool(re.search( r'\b(meson install|make\s+\S*DESTDIR.*install|make\s+install|\binstall\b' r'|cp\s+-[a-zA-Z]*[rR]|rsync\s|setup\.py\s+install|pip\s+install' r'|cmake\s+--install|ninja\s+-C.*install)', blob)) pkg_make_install = bool(re.search(r'(^|\n)\s*make\s+\S*DESTDIR.*install', pkg)) pkg_has_cd = bool(re.search(r'(^|\n)\s*cd\s+\S+', pkg)) lines = open(path, encoding='utf-8', newline='').read().split('\n') if is_autotools and has_cd and not has_install: # ── Grupa A: dopnij make install do build: ── if APPLY: for i, ln in enumerate(lines): if ln.rstrip() == "build: |": end = literal_block_end(lines, i) # wstaw po ostatniej niepustej linii bloku ins = end while ins > i and lines[ins].strip() == "": ins -= 1 lines.insert(ins + 1, ' make DESTDIR="${PKGDIR}" install') break changed.append(("A", path)) elif pkg_make_install and not pkg_has_cd and has_cd: # ── Grupa B: package robi make install bez cd -> dopisz cd ── # yaml.safe_load zdejmuje wcięcie bloku -> przywracamy je (2 spacje, # standard w tym repo; w razie czego bierzemy z pierwszej linii build:). indent = " " m_ind = re.search(r'(^|\n)([ \t]+)\S', build) if m_ind: indent = m_ind.group(2) cd_line = indent + re.search(r'(^|\n)\s*cd\s+\S+', build).group(0).strip() if APPLY: for i, ln in enumerate(lines): if ln.rstrip() == "package: |": # cd MUSI isc na POCZATEK bloku (przed make install) lines.insert(i + 1, cd_line) break changed.append(("B", path)) if APPLY: open(path, 'w', encoding='utf-8', newline='').write('\n'.join(lines)) print("=== DO POPRAWY: %d ===" % len(changed)) for kind, p in changed: print("[%s] %s" % (kind, p)) print("=== POMINIETE: %d ===" % len(skipped)) for p, why in skipped: print(" -", p, why)