git-graphable 0.4.0__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {git_graphable-0.4.0 → git_graphable-0.5.0}/.github/workflows/ci.yml +1 -1
- git_graphable-0.5.0/.github/workflows/pages.yml +46 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/.gitignore +1 -3
- {git_graphable-0.4.0 → git_graphable-0.5.0}/CHANGELOG.md +9 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/PKG-INFO +32 -4
- {git_graphable-0.4.0 → git_graphable-0.5.0}/README.md +31 -3
- {git_graphable-0.4.0/.github/actions/git-graphable → git_graphable-0.5.0}/action.yml +5 -4
- git_graphable-0.5.0/examples/index_template.html +24 -0
- git_graphable-0.5.0/examples/publish_demos.py +110 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/pyproject.toml +1 -1
- {git_graphable-0.4.0 → git_graphable-0.5.0}/src/git_graphable/commands.py +22 -8
- {git_graphable-0.4.0 → git_graphable-0.5.0}/src/git_graphable/highlighter.py +6 -2
- {git_graphable-0.4.0 → git_graphable-0.5.0}/uv.lock +1 -1
- {git_graphable-0.4.0 → git_graphable-0.5.0}/.gemini/GEMINI.md +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/.gemini/code-ordering.md +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/.github/dependabot.yml +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/.github/workflows/publish.yml +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/.python-version +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/Justfile +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/SECURITY.md +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/STYLING.md +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/USAGE.md +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/examples/EXAMPLES.md +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/examples/generate_demos.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/graph.html +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/report_output/final_report.json +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/report_output/plus_metadata.json +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/report_output/report.html +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/report_output/screenshots/test_interactivity_toggling_chromium__failure.png +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/src/git_graphable/__init__.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/src/git_graphable/bare_cli.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/src/git_graphable/cli.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/src/git_graphable/cli_utils.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/src/git_graphable/core.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/src/git_graphable/default_config.toml +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/src/git_graphable/github.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/src/git_graphable/hygiene.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/src/git_graphable/issues.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/src/git_graphable/models.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/src/git_graphable/parser.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/src/git_graphable/rich_cli.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/src/git_graphable/styler.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/src/git_graphable/templates.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/tests/test_bare_cli.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/tests/test_cli.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/tests/test_cli_utils.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/tests/test_config.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/tests/test_core.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/tests/test_examples_html.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/tests/test_github.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/tests/test_highlighter.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/tests/test_hygiene.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/tests/test_interactive_html.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/tests/test_issues.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/tests/test_models.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/tests/test_parser.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/tests/test_rich_cli.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/tests/test_styler.py +0 -0
- {git_graphable-0.4.0 → git_graphable-0.5.0}/tests/test_ui_interactive.py +0 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: Deploy Demos to Pages
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
pages: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
deploy:
|
|
15
|
+
environment:
|
|
16
|
+
name: github-pages
|
|
17
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- name: Checkout
|
|
21
|
+
uses: actions/checkout@v4
|
|
22
|
+
with:
|
|
23
|
+
fetch-depth: 0
|
|
24
|
+
|
|
25
|
+
- name: Setup uv
|
|
26
|
+
uses: astral-sh/setup-uv@v5
|
|
27
|
+
with:
|
|
28
|
+
enable-cache: true
|
|
29
|
+
|
|
30
|
+
- name: Install dependencies
|
|
31
|
+
run: uv sync --all-extras
|
|
32
|
+
|
|
33
|
+
- name: Generate Demos
|
|
34
|
+
run: uv run python examples/publish_demos.py
|
|
35
|
+
|
|
36
|
+
- name: Setup Pages
|
|
37
|
+
uses: actions/configure-pages@v4
|
|
38
|
+
|
|
39
|
+
- name: Upload artifact
|
|
40
|
+
uses: actions/upload-pages-artifact@v3
|
|
41
|
+
with:
|
|
42
|
+
path: 'demo-site'
|
|
43
|
+
|
|
44
|
+
- name: Deploy to GitHub Pages
|
|
45
|
+
id: deployment
|
|
46
|
+
uses: actions/deploy-pages@v4
|
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.5.0] - 2026-03-06
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **Interactive Demos**: Implemented `examples/publish_demos.py` to generate and host live HTML demos via GitHub Pages.
|
|
9
|
+
- **Marketplace Preparation**: Moved `action.yml` to the root directory for GitHub Marketplace publishing and updated related documentation and CI workflows.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- **Squash Merge Detection**: Resolved a `KeyError` and `CycleError` in the logical merge visualization for squashed pull requests when local branch tips were present.
|
|
13
|
+
|
|
5
14
|
## [0.4.0] - 2026-03-05
|
|
6
15
|
|
|
7
16
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: git-graphable
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: A powerful Git history visualizer and hygiene linter with CI gating.
|
|
5
5
|
Project-URL: Homepage, https://github.com/TheTrueSCU/git-graphable
|
|
6
6
|
Project-URL: Issues, https://github.com/TheTrueSCU/git-graphable/issues
|
|
@@ -21,9 +21,13 @@ A powerful Python tool to convert Git commit history into beautiful, interactive
|
|
|
21
21
|
## Git Plugin Support
|
|
22
22
|
When installed in your PATH, you can use this as a native Git plugin:
|
|
23
23
|
```bash
|
|
24
|
-
git graphable .
|
|
24
|
+
git graphable analyze .
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
## 🚀 Live Interactive Demo
|
|
28
|
+
Check out the tool in action with our **[Live Interactive Demos](https://thetruescu.github.io/git-graphable/)**. Explore different hygiene scenarios and toggle overlays in real-time.
|
|
29
|
+
|
|
30
|
+
|
|
27
31
|
## Features
|
|
28
32
|
|
|
29
33
|
- **Multi-Engine Support**: Export to Mermaid (.mmd), D2 (.d2), Graphviz (.dot), or HTML (.html).
|
|
@@ -66,6 +70,7 @@ uv run git-graphable init
|
|
|
66
70
|
|
|
67
71
|
# Simplify the graph (only show branches/tags)
|
|
68
72
|
uv run git-graphable analyze . --simplify
|
|
73
|
+
```
|
|
69
74
|
|
|
70
75
|
## GitHub Action
|
|
71
76
|
|
|
@@ -81,14 +86,37 @@ jobs:
|
|
|
81
86
|
fetch-depth: 0 # Required to see full history
|
|
82
87
|
|
|
83
88
|
- name: Generate Git Graph Reports
|
|
84
|
-
uses: TheTrueSCU/git-graphable
|
|
89
|
+
uses: TheTrueSCU/git-graphable@v0.5.0
|
|
85
90
|
with:
|
|
86
91
|
production_branch: 'main'
|
|
87
92
|
output_dir: 'reports'
|
|
88
93
|
```
|
|
89
94
|
|
|
95
|
+
### Inputs
|
|
96
|
+
|
|
97
|
+
The following inputs are available for the `git-graphable` action:
|
|
98
|
+
|
|
99
|
+
* **`path`**
|
|
100
|
+
* Description: Path to the git repository
|
|
101
|
+
* Required: `false`
|
|
102
|
+
* Default: `'.'`
|
|
103
|
+
* **`production_branch`**
|
|
104
|
+
* Description: The main production branch (e.g. main, master)
|
|
105
|
+
* Required: `false`
|
|
106
|
+
* Default: `'main'`
|
|
107
|
+
* **`issue_engine`**
|
|
108
|
+
* Description: Issue tracker engine (github or jira)
|
|
109
|
+
* Required: `false`
|
|
110
|
+
* **`github_token`**
|
|
111
|
+
* Description: GitHub token for issue integration
|
|
112
|
+
* Required: `false`
|
|
113
|
+
* Default: `${{ github.token }}`
|
|
114
|
+
* **`output_dir`**
|
|
115
|
+
* Description: Directory to save the generated reports
|
|
116
|
+
* Required: `false`
|
|
117
|
+
* Default: `'git-graph-reports'`
|
|
118
|
+
|
|
90
119
|
The action generates a **simplified Mermaid summary** (for quick review) and a **full interactive HTML graph** (for deep-dive auditing), uploading them as workflow artifacts.
|
|
91
|
-
```
|
|
92
120
|
|
|
93
121
|
## Highlighting Options
|
|
94
122
|
|
|
@@ -5,9 +5,13 @@ A powerful Python tool to convert Git commit history into beautiful, interactive
|
|
|
5
5
|
## Git Plugin Support
|
|
6
6
|
When installed in your PATH, you can use this as a native Git plugin:
|
|
7
7
|
```bash
|
|
8
|
-
git graphable .
|
|
8
|
+
git graphable analyze .
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
## 🚀 Live Interactive Demo
|
|
12
|
+
Check out the tool in action with our **[Live Interactive Demos](https://thetruescu.github.io/git-graphable/)**. Explore different hygiene scenarios and toggle overlays in real-time.
|
|
13
|
+
|
|
14
|
+
|
|
11
15
|
## Features
|
|
12
16
|
|
|
13
17
|
- **Multi-Engine Support**: Export to Mermaid (.mmd), D2 (.d2), Graphviz (.dot), or HTML (.html).
|
|
@@ -50,6 +54,7 @@ uv run git-graphable init
|
|
|
50
54
|
|
|
51
55
|
# Simplify the graph (only show branches/tags)
|
|
52
56
|
uv run git-graphable analyze . --simplify
|
|
57
|
+
```
|
|
53
58
|
|
|
54
59
|
## GitHub Action
|
|
55
60
|
|
|
@@ -65,14 +70,37 @@ jobs:
|
|
|
65
70
|
fetch-depth: 0 # Required to see full history
|
|
66
71
|
|
|
67
72
|
- name: Generate Git Graph Reports
|
|
68
|
-
uses: TheTrueSCU/git-graphable
|
|
73
|
+
uses: TheTrueSCU/git-graphable@v0.5.0
|
|
69
74
|
with:
|
|
70
75
|
production_branch: 'main'
|
|
71
76
|
output_dir: 'reports'
|
|
72
77
|
```
|
|
73
78
|
|
|
79
|
+
### Inputs
|
|
80
|
+
|
|
81
|
+
The following inputs are available for the `git-graphable` action:
|
|
82
|
+
|
|
83
|
+
* **`path`**
|
|
84
|
+
* Description: Path to the git repository
|
|
85
|
+
* Required: `false`
|
|
86
|
+
* Default: `'.'`
|
|
87
|
+
* **`production_branch`**
|
|
88
|
+
* Description: The main production branch (e.g. main, master)
|
|
89
|
+
* Required: `false`
|
|
90
|
+
* Default: `'main'`
|
|
91
|
+
* **`issue_engine`**
|
|
92
|
+
* Description: Issue tracker engine (github or jira)
|
|
93
|
+
* Required: `false`
|
|
94
|
+
* **`github_token`**
|
|
95
|
+
* Description: GitHub token for issue integration
|
|
96
|
+
* Required: `false`
|
|
97
|
+
* Default: `${{ github.token }}`
|
|
98
|
+
* **`output_dir`**
|
|
99
|
+
* Description: Directory to save the generated reports
|
|
100
|
+
* Required: `false`
|
|
101
|
+
* Default: `'git-graph-reports'`
|
|
102
|
+
|
|
74
103
|
The action generates a **simplified Mermaid summary** (for quick review) and a **full interactive HTML graph** (for deep-dive auditing), uploading them as workflow artifacts.
|
|
75
|
-
```
|
|
76
104
|
|
|
77
105
|
## Highlighting Options
|
|
78
106
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
name: 'Git Graphable'
|
|
2
|
-
description: '
|
|
2
|
+
description: 'Analyze and visualize Git history hygiene with interactive graphs and reports.'
|
|
3
3
|
author: 'TheTrueSCU'
|
|
4
4
|
branding:
|
|
5
|
-
icon: '
|
|
6
|
-
color: '
|
|
5
|
+
icon: 'bar-chart'
|
|
6
|
+
color: 'green'
|
|
7
7
|
|
|
8
8
|
inputs:
|
|
9
9
|
path:
|
|
@@ -38,7 +38,8 @@ runs:
|
|
|
38
38
|
shell: bash
|
|
39
39
|
run: |
|
|
40
40
|
# Prefer installing local source if we are in the git-graphable repo
|
|
41
|
-
|
|
41
|
+
# github.action_path points to the root in this case
|
|
42
|
+
ROOT_DIR="${{ github.action_path }}"
|
|
42
43
|
if [ -f "$ROOT_DIR/pyproject.toml" ] && grep -q "name = \"git-graphable\"" "$ROOT_DIR/pyproject.toml"; then
|
|
43
44
|
echo "Installing git-graphable from local source: $ROOT_DIR"
|
|
44
45
|
uv tool install "$ROOT_DIR"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Git Graphable Demos</title>
|
|
5
|
+
<style>
|
|
6
|
+
body { font-family: sans-serif; line-height: 1.6; max-width: 800px; margin: 40px auto; padding: 0 20px; }
|
|
7
|
+
h1 { border-bottom: 2px solid #eee; padding-bottom: 10px; }
|
|
8
|
+
ul { list-style: none; padding: 0; }
|
|
9
|
+
li { margin-bottom: 10px; background: #f9f9f9; padding: 15px; border-radius: 8px; border: 1px solid #ddd; }
|
|
10
|
+
a { text-decoration: none; color: #007bff; font-weight: bold; font-size: 1.2em; }
|
|
11
|
+
a:hover { text-decoration: underline; }
|
|
12
|
+
.badge { display: inline-block; padding: 2px 8px; background: #eee; border-radius: 4px; font-size: 0.8em; margin-left: 10px; color: #666; }
|
|
13
|
+
</style>
|
|
14
|
+
</head>
|
|
15
|
+
<body>
|
|
16
|
+
<h1>Git Graphable Interactive Demos</h1>
|
|
17
|
+
<p>Select a scenario below to explore the interactive Git hygiene visualization.</p>
|
|
18
|
+
<ul>
|
|
19
|
+
$html_links
|
|
20
|
+
</ul>
|
|
21
|
+
<hr>
|
|
22
|
+
<p><a href="https://github.com/TheTrueSCU/git-graphable" style="font-size: 1em;">Back to GitHub Repository</a></p>
|
|
23
|
+
</body>
|
|
24
|
+
</html>
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
import subprocess
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from string import Template
|
|
5
|
+
|
|
6
|
+
EXAMPLES_DIR = Path(__file__).parent
|
|
7
|
+
REPOS_DIR = EXAMPLES_DIR / "repos"
|
|
8
|
+
OUTPUT_DIR = Path("demo-site")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def run_command(cmd):
|
|
12
|
+
print(f"Running: {' '.join(cmd)}")
|
|
13
|
+
subprocess.run(cmd, check=True)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def main():
|
|
17
|
+
# 1. Generate the repo data
|
|
18
|
+
import generate_demos
|
|
19
|
+
|
|
20
|
+
generate_demos.main()
|
|
21
|
+
|
|
22
|
+
# 2. Prepare output directory
|
|
23
|
+
if OUTPUT_DIR.exists():
|
|
24
|
+
shutil.rmtree(OUTPUT_DIR)
|
|
25
|
+
OUTPUT_DIR.mkdir()
|
|
26
|
+
|
|
27
|
+
# 3. Analyze each repo and generate HTML
|
|
28
|
+
repos = [d for d in REPOS_DIR.iterdir() if d.is_dir()]
|
|
29
|
+
|
|
30
|
+
html_links = []
|
|
31
|
+
|
|
32
|
+
for repo in sorted(repos):
|
|
33
|
+
repo_name = repo.name
|
|
34
|
+
output_file = f"{repo_name}.html"
|
|
35
|
+
print(f"Analyzing {repo_name}...")
|
|
36
|
+
|
|
37
|
+
# Build command with relevant flags for the specific demo
|
|
38
|
+
cmd = [
|
|
39
|
+
"uv",
|
|
40
|
+
"run",
|
|
41
|
+
"git-graphable",
|
|
42
|
+
"analyze",
|
|
43
|
+
"--bare",
|
|
44
|
+
str(repo),
|
|
45
|
+
"--engine",
|
|
46
|
+
"html",
|
|
47
|
+
"-o",
|
|
48
|
+
str(OUTPUT_DIR / output_file),
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
# Add flags based on the demo type
|
|
52
|
+
if repo_name == "repo-pristine":
|
|
53
|
+
cmd.extend(["--highlight-authors", "--highlight-critical"])
|
|
54
|
+
elif repo_name == "repo-messy":
|
|
55
|
+
cmd.extend(["--highlight-direct-pushes", "--highlight-stale"])
|
|
56
|
+
elif repo_name == "repo-risk-silo":
|
|
57
|
+
cmd.extend(["--highlight-silos", "--silo-threshold", "20"])
|
|
58
|
+
elif repo_name == "repo-complex-hygiene":
|
|
59
|
+
cmd.extend(["--highlight-back-merges", "--highlight-squashed"])
|
|
60
|
+
elif repo_name == "repo-features":
|
|
61
|
+
cmd.extend(["--highlight-orphans", "--highlight-diverging-from", "main"])
|
|
62
|
+
elif repo_name == "repo-issue-desync":
|
|
63
|
+
cmd.extend(
|
|
64
|
+
[
|
|
65
|
+
"--highlight-issue-inconsistencies",
|
|
66
|
+
"--issue-engine",
|
|
67
|
+
"script",
|
|
68
|
+
"--issue-script",
|
|
69
|
+
"echo CLOSED",
|
|
70
|
+
]
|
|
71
|
+
)
|
|
72
|
+
elif repo_name == "repo-release-desync":
|
|
73
|
+
cmd.extend(
|
|
74
|
+
[
|
|
75
|
+
"--highlight-release-inconsistencies",
|
|
76
|
+
"--issue-engine",
|
|
77
|
+
"script",
|
|
78
|
+
"--issue-script",
|
|
79
|
+
"echo CLOSED",
|
|
80
|
+
]
|
|
81
|
+
)
|
|
82
|
+
elif repo_name == "repo-collab-gap":
|
|
83
|
+
cmd.extend(
|
|
84
|
+
[
|
|
85
|
+
"--highlight-collaboration-gaps",
|
|
86
|
+
"--issue-engine",
|
|
87
|
+
"script",
|
|
88
|
+
"--issue-script",
|
|
89
|
+
"echo OPEN,Bob",
|
|
90
|
+
]
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
run_command(cmd)
|
|
94
|
+
label = repo_name.replace("repo-", "").replace("-", " ").title()
|
|
95
|
+
html_links.append(f'<li><a href="{output_file}">{label}</a></li>')
|
|
96
|
+
|
|
97
|
+
# 4. Create index.html from template
|
|
98
|
+
template_path = EXAMPLES_DIR / "index_template.html"
|
|
99
|
+
if template_path.exists():
|
|
100
|
+
template_str = template_path.read_text()
|
|
101
|
+
t = Template(template_str)
|
|
102
|
+
index_content = t.substitute(html_links="\n ".join(html_links))
|
|
103
|
+
(OUTPUT_DIR / "index.html").write_text(index_content)
|
|
104
|
+
print(f"\nDone! Demo site generated in {OUTPUT_DIR}/")
|
|
105
|
+
else:
|
|
106
|
+
print(f"Error: Template not found at {template_path}")
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
if __name__ == "__main__":
|
|
110
|
+
main()
|
|
@@ -31,14 +31,28 @@ def handle_output(
|
|
|
31
31
|
) -> Optional[str]:
|
|
32
32
|
"""Handles exporting and optionally opening the graph. Returns content if output is '-'."""
|
|
33
33
|
if output == "-":
|
|
34
|
-
#
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
with
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
# If output is '-', create a temporary file, export to it,
|
|
35
|
+
# read its content, and return the content.
|
|
36
|
+
# This assumes export_graph expects a file path and handles the content.
|
|
37
|
+
# The 'as_image' flag from the handle_output call is now respected.
|
|
38
|
+
ext = get_extension(engine, as_image=as_image)
|
|
39
|
+
with tempfile.NamedTemporaryFile(suffix=ext, delete=False) as tf:
|
|
40
|
+
temp_path = tf.name
|
|
41
|
+
|
|
42
|
+
# Export to the temporary file, respecting the as_image flag
|
|
43
|
+
export_graph(graph, temp_path, config, engine, as_image=as_image)
|
|
44
|
+
|
|
45
|
+
# Read the content of the temporary file
|
|
46
|
+
mode = "rb" if as_image else "r"
|
|
47
|
+
encoding = None if as_image else "utf-8"
|
|
48
|
+
|
|
49
|
+
with open(temp_path, mode, encoding=encoding) as f:
|
|
50
|
+
content = f.read()
|
|
51
|
+
|
|
52
|
+
# Clean up the temporary file
|
|
53
|
+
os.remove(temp_path)
|
|
54
|
+
|
|
55
|
+
return content
|
|
42
56
|
|
|
43
57
|
if output:
|
|
44
58
|
# If output path is provided, we use the specified as_image flag or infer from extension
|
|
@@ -331,8 +331,12 @@ def _apply_squash_highlights(
|
|
|
331
331
|
if is_tip:
|
|
332
332
|
tips.append(c)
|
|
333
333
|
for tip in tips:
|
|
334
|
-
|
|
335
|
-
|
|
334
|
+
# For squash merges, the 'logical' edge doesn't exist in Git,
|
|
335
|
+
# so we must create it in the graph.
|
|
336
|
+
# In this graph's convention, child nodes add_dependency(parent).
|
|
337
|
+
# The squash commit is the 'new' parent of the old tip.
|
|
338
|
+
tip.add_dependency(
|
|
339
|
+
squash_commit, **{Tag.EDGE_LOGICAL_MERGE.value: True}
|
|
336
340
|
)
|
|
337
341
|
tip.add_tag(Tag.SQUASHED.value)
|
|
338
342
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|