mirror of
https://github.com/zenlm/zen-family.git
synced 2026-11-02 03:10:56 +00:00
171 lines
5.0 KiB
Python
171 lines
5.0 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Robust Git Extraction - Sequential, No Hanging
|
|
Skips already processed repos, strict timeouts
|
|
"""
|
|
|
|
import json
|
|
import subprocess
|
|
import re
|
|
import os
|
|
import sys
|
|
import signal
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
|
|
OUTPUT_DIR = Path(__file__).parent / 'data' / 'full_history'
|
|
MAX_DIFF = 30000
|
|
TIMEOUT = 10 # seconds per git command
|
|
|
|
class TimeoutError(Exception):
|
|
pass
|
|
|
|
def timeout_handler(signum, frame):
|
|
raise TimeoutError()
|
|
|
|
def sanitize(text):
|
|
if not isinstance(text, str):
|
|
return str(text) if text else ""
|
|
text = re.sub(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', '[EMAIL]', text)
|
|
text = re.sub(r'sk-[a-zA-Z0-9]{20,}', '[API_KEY]', text)
|
|
text = re.sub(r'ghp_[a-zA-Z0-9]{36}', '[TOKEN]', text)
|
|
return text
|
|
|
|
def get_stage(d):
|
|
try:
|
|
y = int(d[:4])
|
|
if y <= 2010: return "early"
|
|
elif y <= 2013: return "growth"
|
|
elif y <= 2016: return "senior"
|
|
elif y <= 2019: return "architect"
|
|
elif y <= 2022: return "principal"
|
|
else: return "frontier"
|
|
except: return "dev"
|
|
|
|
def extract(repo_path):
|
|
name = f"{repo_path.parent.name}_{repo_path.name}"
|
|
out = OUTPUT_DIR / f"{name}.jsonl"
|
|
|
|
if out.exists() and out.stat().st_size > 0:
|
|
return name, 0, 0, "skip"
|
|
|
|
examples = []
|
|
bytes_total = 0
|
|
|
|
try:
|
|
signal.signal(signal.SIGALRM, timeout_handler)
|
|
|
|
# Get commits
|
|
signal.alarm(TIMEOUT)
|
|
r = subprocess.run(
|
|
['git', 'log', '--pretty=format:%H|||%s|||%ai', '-n2000'],
|
|
cwd=repo_path, capture_output=True, text=True, errors='replace'
|
|
)
|
|
signal.alarm(0)
|
|
|
|
if r.returncode != 0:
|
|
return name, 0, 0, "nolog"
|
|
|
|
for line in r.stdout.split('\n'):
|
|
if '|||' not in line:
|
|
continue
|
|
parts = line.split('|||')
|
|
if len(parts) < 3:
|
|
continue
|
|
|
|
sha, msg, date = parts[0], parts[1], parts[2]
|
|
|
|
try:
|
|
signal.alarm(TIMEOUT)
|
|
dr = subprocess.run(
|
|
['git', 'show', '--patch', '--no-color', sha],
|
|
cwd=repo_path, capture_output=True, text=True, errors='replace'
|
|
)
|
|
signal.alarm(0)
|
|
|
|
if dr.returncode != 0:
|
|
continue
|
|
|
|
diff = dr.stdout
|
|
if len(diff) > MAX_DIFF:
|
|
diff = diff[:MAX_DIFF] + "\n..."
|
|
|
|
diff = sanitize(diff)
|
|
msg = sanitize(msg)
|
|
stage = get_stage(date)
|
|
bytes_total += len(diff)
|
|
|
|
examples.append({
|
|
"messages": [
|
|
{"role": "system", "content": f"You are Z, a {stage} developer."},
|
|
{"role": "user", "content": f"Implement: {msg}"},
|
|
{"role": "assistant", "content": f"```diff\n{diff}\n```"}
|
|
],
|
|
"metadata": {"sha": sha[:8], "repo": name, "date": date, "stage": stage}
|
|
})
|
|
|
|
except TimeoutError:
|
|
continue
|
|
except:
|
|
continue
|
|
|
|
if examples:
|
|
with open(out, 'w') as f:
|
|
for e in examples:
|
|
f.write(json.dumps(e) + '\n')
|
|
|
|
return name, len(examples), bytes_total, None
|
|
|
|
except TimeoutError:
|
|
return name, 0, 0, "timeout"
|
|
except Exception as e:
|
|
return name, 0, 0, str(e)[:30]
|
|
finally:
|
|
signal.alarm(0)
|
|
|
|
def find_repos():
|
|
r = subprocess.run(
|
|
f'find {os.path.expanduser("~/work")} {os.path.expanduser("~/play")} -maxdepth 4 -name .git -type d 2>/dev/null | grep -v node_modules | grep -v vendor | grep -v .venv',
|
|
shell=True, capture_output=True, text=True
|
|
)
|
|
repos = []
|
|
for l in r.stdout.split('\n'):
|
|
if l.strip():
|
|
repos.append(Path(l).parent)
|
|
return sorted(set(repos))
|
|
|
|
def main():
|
|
print("="*70)
|
|
print("ZEN-AGENTIC: ROBUST GIT EXTRACTION")
|
|
print("="*70)
|
|
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
|
|
|
|
repos = find_repos()
|
|
print(f"Found {len(repos)} repos")
|
|
|
|
total_commits = 0
|
|
total_bytes = 0
|
|
done = 0
|
|
skipped = 0
|
|
|
|
for i, repo in enumerate(repos):
|
|
name, commits, bytes_c, err = extract(repo)
|
|
done += 1
|
|
if err == "skip":
|
|
skipped += 1
|
|
else:
|
|
total_commits += commits
|
|
total_bytes += bytes_c
|
|
|
|
if (i+1) % 20 == 0 or i == len(repos)-1:
|
|
gb = total_bytes / 1024**3
|
|
tokens = total_bytes // 4
|
|
print(f"[{done}/{len(repos)}] Skip:{skipped} Commits:{total_commits:,} Tokens:{tokens/1e9:.2f}B Size:{gb:.2f}GB")
|
|
|
|
print(f"\nDONE: {total_commits:,} commits, {total_bytes//4:,} tokens ({total_bytes/1024**3:.2f}GB)")
|
|
with open(OUTPUT_DIR / 'summary.json', 'w') as f:
|
|
json.dump({"repos": done, "commits": total_commits, "tokens": total_bytes//4, "bytes": total_bytes}, f)
|
|
|
|
if __name__ == '__main__':
|
|
main()
|