mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
231 lines
7.7 KiB
Python
231 lines
7.7 KiB
Python
#!/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()
|