From c876aa6a7c2d16de4f4b7ee578c25b0552f146fc Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Wed, 3 Dec 2025 11:05:24 -0800 Subject: [PATCH] Improve compact git commit log history --- aocsync.py | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 148 insertions(+), 2 deletions(-) diff --git a/aocsync.py b/aocsync.py index ef4f948..edfe749 100755 --- a/aocsync.py +++ b/aocsync.py @@ -443,6 +443,38 @@ class CargoAOCRunner: logger.warning(f"Could not get git rev for {repo_path}: {e}") return "" + @staticmethod + def get_recent_commits(repo_path: Path, count: int = 2) -> List[dict]: + """Get recent git commit messages and timestamps""" + commits = [] + try: + result = subprocess.run( + ['git', 'log', f'-{count}', '--pretty=format:%H|%s|%ai', '--date=iso'], + cwd=repo_path, + capture_output=True, + text=True, + timeout=5 + ) + if result.returncode == 0: + for line in result.stdout.strip().split('\n'): + if line: + parts = line.split('|', 2) + if len(parts) >= 3: + commits.append({ + 'hash': parts[0][:7], # Short hash + 'message': parts[1], + 'timestamp': parts[2] + }) + elif len(parts) == 2: + commits.append({ + 'hash': parts[0][:7], + 'message': parts[1], + 'timestamp': '' + }) + except Exception as e: + logger.warning(f"Could not get recent commits for {repo_path}: {e}") + return commits + @staticmethod def run_benchmarks(repo_path: Path, year: int, user: str = "unknown", repo_url: str = "", is_multi_year: bool = False) -> List[PerformanceResult]: @@ -824,7 +856,7 @@ class HTMLGenerator: 'repo_url': repo_url } - html = self._generate_html(data, years, users, db) + html = self._generate_html(data, years, users, db, config) output_file = self.output_dir / 'index.html' with open(output_file, 'w') as f: @@ -923,7 +955,78 @@ class HTMLGenerator: svg_parts.append('') return ''.join(svg_parts) - def _generate_html(self, data: dict, years: List[int], users: List[str], db: Database) -> str: + def _generate_compact_commits_for_year(self, config: Config, year: int) -> str: + """Generate compact commit log for a specific year""" + commits_data = [] + + # Collect commits for all repositories for this year + for repo_config in config.repositories: + repo_type = repo_config.get('type', 'single') + user_name = repo_config['name'] + + if repo_type == 'single': + # Check if this repo has data for this year + local_path = repo_config.get('local_path', '') + repo_url = repo_config.get('url', '') + if local_path: + repo_path = Path(local_path) + # Check if year directory exists + year_dir = repo_path / str(year) + if year_dir.exists() and year_dir.is_dir(): + commits = CargoAOCRunner.get_recent_commits(repo_path, count=2) + if commits: + commits_data.append({ + 'user': user_name, + 'repo_url': repo_url, + 'commits': commits + }) + + elif repo_type == 'multi-year': + years_config = repo_config.get('years', []) + for year_config in years_config: + if year_config['year'] == year: + local_path = year_config.get('local_path', '') + repo_url = year_config.get('url', '') + if local_path: + repo_path = Path(local_path) + if repo_path.exists(): + commits = CargoAOCRunner.get_recent_commits(repo_path, count=2) + if commits: + commits_data.append({ + 'user': user_name, + 'repo_url': repo_url, + 'commits': commits + }) + + # Generate HTML if we have any commits + if not commits_data: + return '' + + html = '
' + for commit_info in commits_data: + user = commit_info['user'] + repo_url = commit_info['repo_url'] + commits = commit_info['commits'] + + html += f'
{user}: ' + commit_links = [] + for commit in commits: + commit_time = commit['timestamp'][:16] if commit['timestamp'] else '' # YYYY-MM-DD HH:MM + # Get first line of commit message (split by newline and take first part) + commit_msg_full = commit['message'] + commit_msg_first_line = commit_msg_full.split('\n')[0] if commit_msg_full else '' + commit_msg_display = commit_msg_first_line[:60] + '...' if len(commit_msg_first_line) > 60 else commit_msg_first_line + commit_hash = commit['hash'] + commit_url = f"{repo_url.rstrip('/')}/commit/{commit_hash}" if repo_url else '#' + commit_links.append(f'{commit_hash} ({commit_time}) {commit_msg_display}') + + html += ' | '.join(commit_links) + html += '
' + + html += '
' + return html + + def _generate_html(self, data: dict, years: List[int], users: List[str], db: Database, config: Config) -> str: """Generate HTML content""" # Sort years descending (most recent first) sorted_years = sorted(years, reverse=True) @@ -1217,6 +1320,43 @@ class HTMLGenerator: border-radius: 4px; }} + .compact-commits {{ + margin-bottom: 10px; + padding: 8px; + background: #f8f9fa; + border-radius: 4px; + font-size: 0.8em; + border-left: 3px solid #667eea; + }} + + .commit-entry {{ + margin: 3px 0; + color: #555; + }} + + .commit-entry strong {{ + color: #333; + margin-right: 5px; + }} + + .commit-entry a {{ + color: #667eea; + font-family: 'Courier New', monospace; + text-decoration: none; + margin: 0 3px; + font-weight: bold; + }} + + .commit-entry a:hover {{ + text-decoration: underline; + }} + + .commit-entry .commit-message {{ + color: #666; + font-style: italic; + margin-left: 5px; + }} + .summary {{ margin-top: 30px; padding: 15px; @@ -1314,6 +1454,12 @@ class HTMLGenerator:

Year {year}

""" + # Add compact commit log for this year + html += self._generate_compact_commits_for_year(config, year) + + html += """ +""" + # Collect all day/part combinations for this year day_part_combos = [] for day in sorted(data[year].keys()):