Compare commits
No commits in common. "cb62961be00d1b1c8549f4a7e20759dfcee0b1c4" and "48163aab7d509703edb961e6fb598af0dc34b7a7" have entirely different histories.
cb62961be0
...
48163aab7d
94
aocsync.py
94
aocsync.py
@ -359,27 +359,6 @@ class GitManager:
|
||||
class CargoAOCRunner:
|
||||
"""Runs cargo-aoc benchmarks and parses results"""
|
||||
|
||||
@staticmethod
|
||||
def _strip_ansi_codes(text: str) -> str:
|
||||
"""Remove ANSI escape codes from text"""
|
||||
import re
|
||||
if not text:
|
||||
return text
|
||||
# Remove ANSI escape sequences - comprehensive pattern
|
||||
# This pattern matches all ANSI escape codes including:
|
||||
# - ESC[...m (SGR/color codes)
|
||||
# - ESC[...K (EL codes)
|
||||
# - ESC[...H (cursor positioning)
|
||||
# - ESC[38;5;...m (256-color codes)
|
||||
# - ESC[0m, ESC[1m, etc.
|
||||
ansi_escape = re.compile(r'\x1b\[[0-9;]*[a-zA-Z]')
|
||||
# Also catch standalone ESC sequences
|
||||
ansi_escape2 = re.compile(r'\x1b(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
|
||||
# Remove all ANSI codes
|
||||
text = ansi_escape.sub('', text)
|
||||
text = ansi_escape2.sub('', text)
|
||||
return text
|
||||
|
||||
@staticmethod
|
||||
def find_implemented_days(work_dir: Path) -> List[int]:
|
||||
"""Find which days are implemented in the directory
|
||||
@ -498,8 +477,7 @@ class CargoAOCRunner:
|
||||
|
||||
@staticmethod
|
||||
def run_benchmarks(repo_path: Path, year: int, user: str = "unknown",
|
||||
repo_url: str = "", is_multi_year: bool = False,
|
||||
log_file: Optional[Path] = None) -> List[PerformanceResult]:
|
||||
repo_url: str = "", is_multi_year: bool = False) -> List[PerformanceResult]:
|
||||
"""Run cargo aoc benchmarks and parse results
|
||||
|
||||
Args:
|
||||
@ -508,7 +486,6 @@ class CargoAOCRunner:
|
||||
user: User name for the results
|
||||
repo_url: Repository URL for linking
|
||||
is_multi_year: True if this is a multi-year repo (repo_path is already the year directory)
|
||||
log_file: Optional path to log file to append cargo aoc output to
|
||||
"""
|
||||
results = []
|
||||
repo_path = Path(repo_path)
|
||||
@ -551,30 +528,6 @@ class CargoAOCRunner:
|
||||
timeout=300 # 5 minute timeout per day
|
||||
)
|
||||
|
||||
# Write to log file if provided
|
||||
if log_file:
|
||||
timestamp = datetime.now().isoformat()
|
||||
# Strip ANSI codes from output before writing
|
||||
stdout_clean = CargoAOCRunner._strip_ansi_codes(result.stdout or "")
|
||||
stderr_clean = CargoAOCRunner._strip_ansi_codes(result.stderr or "")
|
||||
|
||||
with open(log_file, 'a', encoding='utf-8') as f:
|
||||
f.write(f"\n{'='*80}\n")
|
||||
f.write(f"[{timestamp}] {user} - Year {year} - Day {day}\n")
|
||||
f.write(f"Command: {' '.join(cmd)}\n")
|
||||
f.write(f"Working Directory: {work_dir}\n")
|
||||
f.write(f"Return Code: {result.returncode}\n")
|
||||
f.write(f"{'='*80}\n")
|
||||
if result.stdout: # Check original, write cleaned version
|
||||
f.write("STDOUT:\n")
|
||||
f.write(stdout_clean)
|
||||
f.write("\n")
|
||||
if result.stderr: # Check original, write cleaned version
|
||||
f.write("STDERR:\n")
|
||||
f.write(stderr_clean)
|
||||
f.write("\n")
|
||||
f.write(f"{'='*80}\n\n")
|
||||
|
||||
if result.returncode != 0:
|
||||
logger.warning(f"cargo aoc failed for day {day} in {work_dir}: {result.stderr}")
|
||||
continue
|
||||
@ -583,13 +536,9 @@ class CargoAOCRunner:
|
||||
if not result.stdout.strip() and not result.stderr.strip():
|
||||
logger.warning(f"No output from cargo aoc for {user} year {year} day {day}")
|
||||
|
||||
# Strip ANSI codes before parsing (for cleaner parsing)
|
||||
stdout_clean = CargoAOCRunner._strip_ansi_codes(result.stdout or "")
|
||||
stderr_clean = CargoAOCRunner._strip_ansi_codes(result.stderr or "")
|
||||
|
||||
# Parse output for runtime information
|
||||
day_results = CargoAOCRunner._parse_runtime_output(
|
||||
stdout_clean, stderr_clean, day, year, user, git_rev, repo_url
|
||||
result.stdout, result.stderr, day, year, user, git_rev, repo_url
|
||||
)
|
||||
if day_results:
|
||||
logger.info(f"Parsed {len(day_results)} runtime result(s) for {user} year {year} day {day}")
|
||||
@ -600,19 +549,9 @@ class CargoAOCRunner:
|
||||
results.extend(day_results)
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
error_msg = f"Timeout running cargo aoc for day {day}"
|
||||
logger.error(error_msg)
|
||||
if log_file:
|
||||
timestamp = datetime.now().isoformat()
|
||||
with open(log_file, 'a', encoding='utf-8') as f:
|
||||
f.write(f"\n[{timestamp}] ERROR: {error_msg}\n")
|
||||
logger.error(f"Timeout running cargo aoc for day {day}")
|
||||
except Exception as e:
|
||||
error_msg = f"Error running cargo aoc for day {day}: {e}"
|
||||
logger.error(error_msg)
|
||||
if log_file:
|
||||
timestamp = datetime.now().isoformat()
|
||||
with open(log_file, 'a', encoding='utf-8') as f:
|
||||
f.write(f"\n[{timestamp}] ERROR: {error_msg}\n")
|
||||
logger.error(f"Error running cargo aoc for day {day}: {e}")
|
||||
|
||||
return results
|
||||
|
||||
@ -1089,9 +1028,6 @@ class HTMLGenerator:
|
||||
|
||||
def _generate_html(self, data: dict, years: List[int], users: List[str], db: Database, config: Config) -> str:
|
||||
"""Generate HTML content"""
|
||||
# Get refresh interval from config (default 5 minutes = 300 seconds)
|
||||
refresh_interval = config.config.get('html_refresh_interval', 300)
|
||||
|
||||
# Sort years descending (most recent first)
|
||||
sorted_years = sorted(years, reverse=True)
|
||||
|
||||
@ -1104,16 +1040,11 @@ class HTMLGenerator:
|
||||
for part in day.values():
|
||||
users_with_data.update(part.keys())
|
||||
|
||||
# Check if log file exists
|
||||
log_file_path = Path(config.output_dir) / 'cargo-aoc.log'
|
||||
log_file_exists = log_file_path.exists()
|
||||
|
||||
html = f"""<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="refresh" content="{refresh_interval}">
|
||||
<title>Advent of Code Performance Comparison</title>
|
||||
<style>
|
||||
* {{
|
||||
@ -1510,7 +1441,6 @@ class HTMLGenerator:
|
||||
|
||||
<div class="controls">
|
||||
<p><strong>Users:</strong> """ + ', '.join(sorted(users)) + """</p>
|
||||
""" + (f'<p><a href="cargo-aoc.log" target="_blank">📋 View Cargo AOC Logs</a></p>' if log_file_exists else '') + """
|
||||
</div>
|
||||
"""
|
||||
|
||||
@ -1864,12 +1794,8 @@ class AOCSync:
|
||||
repo_url: str = "", is_multi_year: bool = False):
|
||||
"""Run benchmarks and store results"""
|
||||
logger.info(f"Running benchmarks for {user} year {year} in {repo_path}")
|
||||
# Create log file path in output directory
|
||||
log_file = Path(self.config.output_dir) / 'cargo-aoc.log'
|
||||
log_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
results = CargoAOCRunner.run_benchmarks(repo_path, year=year, user=user,
|
||||
repo_url=repo_url, is_multi_year=is_multi_year,
|
||||
log_file=log_file)
|
||||
repo_url=repo_url, is_multi_year=is_multi_year)
|
||||
|
||||
# Store results
|
||||
for result in results:
|
||||
@ -1881,15 +1807,6 @@ class AOCSync:
|
||||
"""Sync all repositories"""
|
||||
logger.info("Starting sync of all repositories...")
|
||||
|
||||
# Clear log file at start of sync
|
||||
log_file = Path(self.config.output_dir) / 'cargo-aoc.log'
|
||||
log_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
# Clear the log file and write a header
|
||||
with open(log_file, 'w', encoding='utf-8') as f:
|
||||
f.write(f"{'#'*80}\n")
|
||||
f.write(f"# Sync started at {datetime.now().isoformat()}\n")
|
||||
f.write(f"{'#'*80}\n\n")
|
||||
|
||||
for repo_config in self.config.repositories:
|
||||
user_name = repo_config['name']
|
||||
try:
|
||||
@ -1925,7 +1842,6 @@ class AOCSync:
|
||||
try:
|
||||
# Build rsync command
|
||||
# Use trailing slash on source to sync contents, not the directory itself
|
||||
# This will include all files including cargo-aoc.log
|
||||
source = str(output_dir) + "/"
|
||||
cmd = ['rsync', '-avz', '--delete', source, destination]
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user