A powerful tool for deep manifest comparison via Gerrit & Gitiles API
diffmanifests is a sophisticated CLI tool designed to reveal deeper differences between manifest files by leveraging the Gerrit and Gitiles APIs. It provides comprehensive change tracking, hashtag support, and detailed commit analysis for efficient manifest version management.
- 🔍 Deep Comparison: Analyze differences between manifest versions with precision
- 🏷️ Hashtag Integration: Full support for Gerrit hashtags and categorization
- 📊 Visual Reporting: Generate detailed JSON reports with comprehensive commit information
- 🔄 API-Powered: Seamlessly integrates with Gerrit and Gitiles REST APIs
- ⚡ Easy to Use: Simple command-line interface with clear configuration
- Requirements
- Installation
- Quick Start
- Configuration
- Features
- Output Format
- Examples
- Development
- License
- References
- Python: >= 3.7
- Dependencies:
colorama- Terminal color outputopenpyxl- Excel file handlingrequests- HTTP libraryxmltodict- XML parsing
pip install diffmanifestspip install diffmanifests --upgradegit clone https://github.com/craftslab/diffmanifests.git
cd diffmanifests
pip install -e .diffmanifests \
--config-file config.json \
--manifest1-file manifest1.xml \
--manifest2-file manifest2.xml \
--output-file output.json| Argument | Description | Required |
|---|---|---|
--config-file |
Path to configuration JSON file | ✅ |
--manifest1-file |
Path to first manifest XML file (older version) | ✅ |
--manifest2-file |
Path to second manifest XML file (newer version) | ✅ |
--output-file |
Path to output file for results (supports .json, .txt, .xlsx formats) |
✅ |
Configuration parameters can be set in a JSON file. See the config directory for examples.
Create a config.json file with the following structure:
{
"gerrit": {
"url": "https://your-gerrit-instance.com",
"user": "your-username",
"pass": "your-password-or-token"
},
"gitiles": {
"url": "https://your-gitiles-instance.com",
"user": "your-username",
"pass": "your-password-or-token",
"retry": 3,
"timeout": 30
}
}| Parameter | Type | Description |
|---|---|---|
url |
string | Gerrit instance URL |
user |
string | Authentication username |
pass |
string | Authentication password or API token |
| Parameter | Type | Description | Default |
|---|---|---|---|
url |
string | Gitiles instance URL | - |
user |
string | Authentication username | - |
pass |
string | Authentication password or API token | - |
retry |
integer | Number of retry attempts for failed requests | 1 |
timeout |
integer | Request timeout in seconds (-1 for no timeout) | -1 |
Compare two manifest versions to identify changes between commits. The tool analyzes differences using a three-way comparison model:
Comparison Logic:
- Diagram A: Changes from commit 1 to commit 2
- Diagram B: Alternative change paths
- Diagram C: Merge scenarios
Comprehensive support for Gerrit hashtags through REST API v3.12.1, enabling better change tracking and categorization.
✅ Automatic hashtag extraction from Gerrit changes
✅ Enhanced categorization and filtering capabilities
✅ Seamless Gerrit workflow integration
✅ Graceful fallback for changes without hashtags
| Hashtags | Use Case |
|---|---|
["feature", "ui", "enhancement"] |
New UI features |
["bugfix", "critical"] |
Critical bug fixes |
["security", "cve"] |
Security-related changes |
["refactor", "cleanup"] |
Code refactoring |
[] |
Changes without hashtags |
The tool supports three output formats determined by the file extension:
.json- Structured JSON format for programmatic processing.txt- Human-readable plain text format.xlsx- Excel spreadsheet format for analysis and reporting
{
"author": "Developer Name <[email protected]>",
"branch": "master",
"change": "https://gerrit.example.com/c/12345",
"commit": "abc123def456789...",
"committer": "Developer Name <[email protected]>",
"date": "2025-08-20 12:00:00 +0000",
"diff": "ADD COMMIT",
"hashtags": ["security", "cve", "bugfix"],
"message": "Fix security vulnerability CVE-2025-1234",
"repo": "platform/frameworks/base",
"topic": "security-fix",
"url": "https://android.googlesource.com/platform/frameworks/base/+/abc123def456789"
}| Field | Type | Description |
|---|---|---|
author |
string | Original commit author |
branch |
string | Target branch name |
change |
string | Gerrit change URL |
commit |
string | Git commit SHA |
committer |
string | Person who committed the change |
date |
string | Commit timestamp |
diff |
string | Type of change (ADD COMMIT, REMOVE COMMIT, etc.) |
hashtags |
array | List of associated hashtags |
message |
string | Commit message |
repo |
string | Repository path |
topic |
string | Gerrit topic name |
url |
string | Gitiles commit URL |
diffmanifests \
--config-file ./config/config.json \
--manifest1-file ./data/android-11.xml \
--manifest2-file ./data/android-12.xml \
--output-file ./results/diff-output.jsonAlternative Output Formats:
# Plain text format
diffmanifests \
--config-file ./config/config.json \
--manifest1-file ./data/android-11.xml \
--manifest2-file ./data/android-12.xml \
--output-file ./results/diff-output.txt
# Excel format
diffmanifests \
--config-file ./config/config.json \
--manifest1-file ./data/android-11.xml \
--manifest2-file ./data/android-12.xml \
--output-file ./results/diff-output.xlsx# config.json
{
"gerrit": {
"url": "https://android-review.googlesource.com",
"user": "developer",
"pass": "your-token"
},
"gitiles": {
"url": "https://android.googlesource.com",
"user": "developer",
"pass": "your-token",
"retry": 5,
"timeout": 60
}
}
# Run comparison
diffmanifests \
--config-file config.json \
--manifest1-file old-manifest.xml \
--manifest2-file new-manifest.xml \
--output-file changes.jsonimport json
# Load the output
with open('output.json', 'r') as f:
changes = json.load(f)
# Filter security-related changes
security_changes = [
c for c in changes
if 'security' in c.get('hashtags', []) or 'cve' in c.get('hashtags', [])
]
print(f"Found {len(security_changes)} security-related changes")# Clone the repository
git clone https://github.com/craftslab/diffmanifests.git
cd diffmanifests
# Install development dependencies
pip install -e .[dev]
# Run tests
pytest tests/
# Run tests with coverage
coverage run -m pytest tests/
coverage report# Run all tests
pytest
# Run specific test module
pytest tests/differ/test_differ.py
# Run with verbose output
pytest -v
# Run with coverage report
pytest --cov=diffmanifests tests/Located in the script/ directory:
clean.sh- Clean build artifacts and cache filesdist.sh- Build distribution packagesinstall.sh- Install the package locallyrun.sh- Run the tool with test datatest.sh- Execute test suite
This project is licensed under the Apache License 2.0.
See LICENSE for full details.
- Gerrit REST API Documentation
- Gerrit ChangeInfo Entity
- git-repo/subcmds/diffmanifests
- Gitiles API Documentation
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Issues: GitHub Issues
- Email: [email protected]
- PyPI: diffmanifests on PyPI
Made with ❤️ by craftslab
⭐ Star this repository if you find it helpful!
