#!/usr/bin/env python3 """ Repackage iotg-rpi4-config .deb for Debian Buster+ compatibility. Changes: - Updates CONFIG path from /boot/config.txt to /boot/firmware/config.txt - Relocates overlays from /boot/overlays/ to /boot/firmware/overlays/ """ import shutil import subprocess import tempfile from pathlib import Path def run_cmd(cmd: list[str], cwd: Path | None = None) -> None: """Run shell command and handle errors.""" result = subprocess.run(cmd, cwd=cwd, capture_output=True, text=True) if result.returncode != 0: raise RuntimeError(f"Command failed: {' '.join(cmd)}\n{result.stderr}") def modify_functions_file(functions_path: Path) -> None: """Update CONFIG path in iotg-rpi4-functions.""" content = functions_path.read_text() # Replace the CONFIG path modified = content.replace( "CONFIG=/boot/config.txt", "CONFIG=/boot/firmware/config.txt" ) # Also update the backup path reference (it uses ${CONFIG} so should be fine) # But let's verify the change was made if modified == content: raise RuntimeError("Failed to modify CONFIG path - pattern not found") functions_path.write_text(modified) print(f"✓ Modified {functions_path.name}") def relocate_overlays(extract_dir: Path) -> None: """Move overlays from /boot/overlays to /boot/firmware/overlays.""" old_path = extract_dir / "boot" / "overlays" / "iotg-rpi4" new_path = extract_dir / "boot" / "firmware" / "overlays" / "iotg-rpi4" if not old_path.exists(): raise RuntimeError(f"Overlay directory not found: {old_path}") # Create new directory structure new_path.parent.mkdir(parents=True, exist_ok=True) # Move the iotg-rpi4 directory shutil.move(str(old_path), str(new_path)) # Remove old empty directories (extract_dir / "boot" / "overlays").rmdir() print(f"✓ Relocated overlays to boot/firmware/overlays/iotg-rpi4/") def repackage_deb(original_deb: Path, output_deb: Path) -> None: """Extract, modify, and repackage the .deb file.""" with tempfile.TemporaryDirectory() as tmpdir: work_dir = Path(tmpdir) extract_dir = work_dir / "package" control_dir = work_dir / "DEBIAN" extract_dir.mkdir() control_dir.mkdir() print(f"Extracting {original_deb.name}...") run_cmd(["dpkg-deb", "-x", str(original_deb), str(extract_dir)]) run_cmd(["dpkg-deb", "-e", str(original_deb), str(control_dir)]) # Modify the functions file functions_file = extract_dir / "usr" / "local" / "bin" / "iotg-rpi4-functions" modify_functions_file(functions_file) # Relocate overlays relocate_overlays(extract_dir) # Update control file version control_file = control_dir / "control" control_content = control_file.read_text() control_content = control_content.replace( "Version: 1.3-1", "Version: 1.3-1buster1" ) control_file.write_text(control_content) print("✓ Updated control file version") # Copy DEBIAN directory into extract_dir shutil.copytree(control_dir, extract_dir / "DEBIAN") # Build new .deb print(f"Building {output_deb.name}...") run_cmd(["dpkg-deb", "-b", str(extract_dir), str(output_deb)]) print(f"\n✓ Successfully created {output_deb}") def main() -> None: """Main entry point.""" script_dir = Path(__file__).parent original_deb = script_dir / "iotg-rpi4-config_1.3-1_all.deb" output_deb = script_dir / "iotg-rpi4-config_1.3-1buster1_all.deb" if not original_deb.exists(): raise FileNotFoundError(f"Original .deb not found: {original_deb}") if output_deb.exists(): print(f"Removing existing {output_deb.name}...") output_deb.unlink() print("Repackaging for Debian Buster+ compatibility\n") repackage_deb(original_deb, output_deb) print("\nChanges made:") print(" • CONFIG=/boot/config.txt → CONFIG=/boot/firmware/config.txt") print(" • Overlays moved from /boot/overlays/ → /boot/firmware/overlays/") print(" • Version updated to 1.3-1buster1") print(f"\nInstall with: sudo dpkg -i {output_deb.name}") if __name__ == "__main__": main()