From 63f3f5726fb872245a78ff5ea8c4904b3d148d78 Mon Sep 17 00:00:00 2001 From: overcuriousity Date: Mon, 23 Jun 2025 08:49:51 +0200 Subject: [PATCH] Create update-manifest.py --- flatpak/scripts/update-manifest.py | 230 +++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 flatpak/scripts/update-manifest.py diff --git a/flatpak/scripts/update-manifest.py b/flatpak/scripts/update-manifest.py new file mode 100644 index 0000000000..c0be6af930 --- /dev/null +++ b/flatpak/scripts/update-manifest.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python3 +""" +Script to automatically update the Flatpak manifest with new versions +of Autopsy and Sleuth Kit. +""" + +import argparse +import re +import sys +import requests +import hashlib +from pathlib import Path +from typing import Dict, Optional + +class ManifestUpdater: + def __init__(self, manifest_path: str): + self.manifest_path = Path(manifest_path) + if not self.manifest_path.exists(): + raise FileNotFoundError(f"Manifest file not found: {manifest_path}") + + def get_github_release_info(self, repo: str, tag: str) -> Dict[str, str]: + """Get release information from GitHub API.""" + url = f"https://api.github.com/repos/{repo}/releases/tags/{tag}" + response = requests.get(url) + + if response.status_code != 200: + raise ValueError(f"Failed to get release info for {repo}:{tag}") + + data = response.json() + return { + 'tag': data['tag_name'], + 'tarball_url': data['tarball_url'], + 'zipball_url': data['zipball_url'], + 'published_at': data['published_at'] + } + + def calculate_archive_sha256(self, url: str) -> str: + """Download and calculate SHA256 hash of an archive.""" + print(f"Downloading and calculating hash for: {url}") + response = requests.get(url, stream=True) + response.raise_for_status() + + sha256_hash = hashlib.sha256() + for chunk in response.iter_content(chunk_size=8192): + sha256_hash.update(chunk) + + return sha256_hash.hexdigest() + + def update_module_version(self, content: str, module_name: str, + new_tag: str, repo_url: str) -> str: + """Update a specific module's version in the manifest.""" + + # Pattern to match the module block + module_pattern = rf'(- name: {re.escape(module_name)}.*?)((?=- name: |\Z))' + + match = re.search(module_pattern, content, re.DOTALL) + if not match: + raise ValueError(f"Module '{module_name}' not found in manifest") + + module_block = match.group(1) + + # Update source-tag + updated_block = re.sub( + r'(\s+source-tag:\s+).*', + rf'\g<1>{new_tag}', + module_block + ) + + # Remove source-branch if it exists (tags take precedence) + updated_block = re.sub( + r'\s+source-branch:.*?\n', + '', + updated_block + ) + + # Update the URL if it's different + if repo_url: + updated_block = re.sub( + r'(\s+source:\s+).*', + rf'\g<1>{repo_url}', + updated_block + ) + + # Replace the module block in the content + return content.replace(module_block, updated_block) + + def update_app_version(self, content: str, version: str) -> str: + """Update the main application version.""" + # Extract version number from tag (e.g., "autopsy-4.22.1" -> "4.22.1") + version_match = re.search(r'(\d+\.\d+\.\d+)', version) + if version_match: + version_number = version_match.group(1) + else: + version_number = version.replace('autopsy-', '').replace('v', '') + + return re.sub( + r'^version:\s+.*', + f'version: {version_number}', + content, + flags=re.MULTILINE + ) + + def update_manifest(self, autopsy_version: Optional[str] = None, + sleuthkit_version: Optional[str] = None) -> bool: + """Update the manifest file with new versions.""" + + # Read current manifest + content = self.manifest_path.read_text() + original_content = content + + # Update Autopsy if specified + if autopsy_version: + print(f"Updating Autopsy to version: {autopsy_version}") + content = self.update_module_version( + content, + 'autopsy', + autopsy_version, + 'https://github.com/sleuthkit/autopsy.git' + ) + content = self.update_app_version(content, autopsy_version) + + # Update Sleuth Kit if specified + if sleuthkit_version: + print(f"Updating Sleuth Kit to version: {sleuthkit_version}") + content = self.update_module_version( + content, + 'sleuthkit', + sleuthkit_version, + 'https://github.com/sleuthkit/sleuthkit.git' + ) + + # Write updated manifest if changes were made + if content != original_content: + # Create backup + backup_path = self.manifest_path.with_suffix('.yml.backup') + backup_path.write_text(original_content) + print(f"Created backup: {backup_path}") + + # Write updated content + self.manifest_path.write_text(content) + print(f"Updated manifest: {self.manifest_path}") + return True + else: + print("No changes needed.") + return False + + def validate_manifest(self) -> bool: + """Basic validation of the manifest file.""" + content = self.manifest_path.read_text() + + # Check for required fields + required_fields = ['app-id:', 'runtime:', 'sdk:', 'modules:'] + for field in required_fields: + if field not in content: + print(f"Error: Required field '{field}' not found in manifest") + return False + + # Check for module structure + if '- name: autopsy' not in content: + print("Error: Autopsy module not found in manifest") + return False + + if '- name: sleuthkit' not in content: + print("Error: Sleuth Kit module not found in manifest") + return False + + print("Manifest validation passed.") + return True + +def main(): + parser = argparse.ArgumentParser( + description='Update Flatpak manifest with new Autopsy/Sleuth Kit versions' + ) + parser.add_argument( + '--manifest', + required=True, + help='Path to the Flatpak manifest file' + ) + parser.add_argument( + '--autopsy-version', + help='New Autopsy version tag (e.g., autopsy-4.22.1)' + ) + parser.add_argument( + '--sleuthkit-version', + help='New Sleuth Kit version tag (e.g., sleuthkit-4.14.0)' + ) + parser.add_argument( + '--validate-only', + action='store_true', + help='Only validate the manifest without updating' + ) + + args = parser.parse_args() + + try: + updater = ManifestUpdater(args.manifest) + + if args.validate_only: + success = updater.validate_manifest() + sys.exit(0 if success else 1) + + if not args.autopsy_version and not args.sleuthkit_version: + print("Error: At least one version must be specified") + sys.exit(1) + + # Validate before updating + if not updater.validate_manifest(): + print("Error: Manifest validation failed") + sys.exit(1) + + # Perform updates + updated = updater.update_manifest( + autopsy_version=args.autopsy_version, + sleuthkit_version=args.sleuthkit_version + ) + + if updated: + print("Manifest updated successfully!") + + # Validate after updating + if not updater.validate_manifest(): + print("Warning: Updated manifest failed validation") + sys.exit(1) + + except Exception as e: + print(f"Error: {e}") + sys.exit(1) + +if __name__ == '__main__': + main()