Buckets:

Mercity/SkillsStorage / code /fill_repo_cap.py
Pranav2748's picture
download
raw
8.06 kB
"""Targeted fill pass: fetch the content of bundle files that the crawler skipped with skipped='repo_cap'
(the 100 MB-per-repo memory guard). Only a handful of huge skill-collection repos are affected.
1. Collect targets from the bucket (processed/github_delta/<run>/files where skipped='repo_cap'): the exact
git blob SHA of every skipped file is already recorded, so we fetch exactly those blobs.
2. Per repo: blobless shallow clone, then batched `git fetch --stdin <blob oids>` + `cat-file --batch`,
written straight to parquet in small batches (bounded RAM regardless of repo size).
3. Rows use the original skill_uid / rel_path, so they supersede the repo_cap placeholder rows:
processed/github_delta/<run>/files/fill-repo_cap-<n>.parquet (consumers: prefer the row WITH content)
Usage: python code/fill_repo_cap.py [run ...] (default: all three runs). Resumable via work/fill/done.txt.
"""
import os, sys, json, shutil, subprocess, hashlib, time
from pathlib import Path
import pyarrow as pa, pyarrow.parquet as pq
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "code"))
from bucket_query import urls, connect
from build_github_delta import FI_SCHEMA
from huggingface_hub import HfApi
RUNS = sys.argv[1:] or ["pass1_sourcegraph", "pass2_new", "backfill_gitskills"]
WORK = ROOT / "work/fill"; WORK.mkdir(parents=True, exist_ok=True)
DONE = WORK / "done.txt"; done = set(DONE.read_text().split()) if DONE.exists() else set()
ENV = {**os.environ, "GIT_TERMINAL_PROMPT": "0", "GIT_LFS_SKIP_SMUDGE": "1"}
NO_LAZY = {**ENV, "GIT_NO_LAZY_FETCH": "1"}
BATCH_OIDS, BATCH_BYTES, MAX_BIN = 1500, 48 << 20, 256 << 10
api = HfApi()
def git(*a, cwd=None, inp=None, env=ENV, timeout=900):
return subprocess.run(["git", *a], cwd=cwd, input=inp, capture_output=True, env=env, timeout=timeout)
RAW_DIR = {"pass1_sourcegraph": "github_delta", "pass2_new": "github_delta_p2", "backfill_gitskills": "github_backfill"}
def clone(repo):
d = WORK / hashlib.md5(repo.encode()).hexdigest(); shutil.rmtree(d, ignore_errors=True)
r = git("clone", "-q", "--depth", "1", "--filter=blob:none", "--no-checkout", "--single-branch",
f"https://github.com/{repo}.git", str(d), timeout=600)
if r.returncode:
print(f" {repo}: clone failed ({r.stderr.decode(errors='replace')[:120].strip()}) — will retry next run", flush=True)
return None
return d
def fetch_and_write(run, repo, rows, d, tag):
"""rows carry blob_sha; fetch those blobs in batches and upload fill rows. Returns (rows_out, blobs_got, blobs)."""
by_sha = {}
for x in rows: by_sha.setdefault(x["blob_sha"], []).append(x)
oids = list(by_sha); n_out = n_got = 0
batches, cur, cur_b = [], [], 0 # batch by bytes (~48 MB) as well as count: capped files can be up to 1 MB each
for o in oids:
sz = by_sha[o][0]["size"] or 0
if cur and (len(cur) >= BATCH_OIDS or cur_b + sz > BATCH_BYTES): batches.append(cur); cur, cur_b = [], 0
cur.append(o); cur_b += sz
if cur: batches.append(cur)
for part, chunk in enumerate(batches):
git("-c", "fetch.negotiationAlgorithm=noop", "fetch", "-q", "--no-tags", "--no-write-fetch-head",
"--recurse-submodules=no", "--filter=blob:none", "origin", "--stdin", cwd=d, inp=("\n".join(chunk) + "\n").encode())
buf = git("cat-file", "--batch", cwd=d, env=NO_LAZY, inp=("\n".join(chunk) + "\n").encode()).stdout
got, i = {}, 0
while i < len(buf):
nl = buf.index(b"\n", i); hdr = buf[i:nl].decode().split()
if len(hdr) < 3 or hdr[1] == "missing": i = nl + 1; continue
n = int(hdr[2]); got[hdr[0]] = buf[nl + 1: nl + 1 + n]; i = nl + 2 + n
del buf
out = []
for sha in chunk:
c_ = got.get(sha)
for x in by_sha[sha]:
text = c_ is not None and b"\0" not in c_[:8192]
keep_bin = c_ is not None and not text and len(c_) <= MAX_BIN
out.append({**{k2: x[k2] for k2 in ("skill_uid", "source", "repo", "skill_dir", "rel_path", "size", "blob_sha")},
"content": c_.decode("utf-8", "replace") if text else None,
"content_bin": c_ if keep_bin else None, "has_content": text or keep_bin,
"skipped": None if (text or keep_bin) else ("binary_large" if c_ is not None else "fetch_failed")})
n_got += len(got); n_out += len(out)
name = f"fill-repo_cap-{tag}{hashlib.md5(repo.encode()).hexdigest()[:10]}-{part:03d}.parquet"
p = WORK / name; pq.write_table(pa.Table.from_pylist(out, FI_SCHEMA), p, compression="zstd")
for attempt in range(6):
try:
api.batch_bucket_files("Mercity/SkillsStorage", add=[(str(p), f"processed/github_delta/{run}/files/{name}")]); break
except Exception:
time.sleep(15 * (attempt + 1))
else:
raise RuntimeError(f"upload failed {name}")
p.unlink(); del got, out
return n_out, n_got, len(oids)
def targets(run, by_path):
tf = WORK / f"targets-{run}{'-bypath' if by_path else ''}.parquet"
if not tf.exists():
c = connect("300MB")
c.execute(f"""copy (select skill_uid, source, repo, skill_dir, rel_path, size, blob_sha from read_parquet({urls(f'processed/github_delta/{run}/files/')})
where skipped = 'repo_cap' and blob_sha is {'' if by_path else 'not '}null) to '{tf}' (format parquet)""")
c.close()
t = pq.read_table(tf); by_repo = {}
for r in t.to_pylist(): by_repo.setdefault(r["repo"], []).append(r)
return by_repo
for by_path in (False, True):
# by_path=True: files skipped on the codeload path have no blob SHA recorded -> resolve path -> SHA with
# `git ls-tree` at the exact commit that was crawled (full commit id from raw/<run>/repos.jsonl), then fetch.
for run in RUNS:
by_repo = targets(run, by_path)
print(f"{run}{' (by path)' if by_path else ''}: {sum(map(len, by_repo.values()))} files in {len(by_repo)} repos", flush=True)
commits = {}
if by_path and by_repo:
for l in open(ROOT / "data/raw" / RAW_DIR[run] / "repos.jsonl"):
m = json.loads(l)
if m.get("commit"): commits[m["repo"]] = m["commit"]
for repo in sorted(by_repo):
key = f"{run}|{repo}{'|bypath' if by_path else ''}"
if key in done: continue
rows = by_repo[repo]
d = clone(repo)
if d is None: continue
if by_path:
ref = commits.get(repo) or "HEAD"
if ref != "HEAD" and git("rev-parse", "HEAD", cwd=d).stdout.decode().strip() != ref:
git("fetch", "-q", "--depth", "1", "--filter=blob:none", "origin", ref, cwd=d, timeout=600)
full = lambda x: x["rel_path"] if x["skill_dir"] == "." else f"{x['skill_dir']}/{x['rel_path']}"
dirs = sorted({x["skill_dir"] for x in rows}); sha_of = {}
for k in range(0, len(dirs), 200):
out = git("--literal-pathspecs", "ls-tree", "-r", "-z", ref, "--", *dirs[k:k + 200], cwd=d).stdout
for rec in out.decode(errors="replace").split("\0"):
if "\t" not in rec: continue
info, path = rec.split("\t", 1); parts = info.split()
if len(parts) == 3 and parts[1] == "blob": sha_of[path] = parts[2]
rows = [{**x, "blob_sha": sha_of[full(x)]} for x in rows if full(x) in sha_of]
n_out, n_got, n_oids = fetch_and_write(run, repo, rows, d, "bypath-" if by_path else "")
shutil.rmtree(d, ignore_errors=True)
with open(DONE, "a") as f: f.write(key + "\n")
print(f" {repo}: {n_out} rows written ({n_got}/{n_oids} blobs fetched)" + (f", {len(by_repo[repo]) - len(rows)} paths not found at commit" if by_path else ""), flush=True)
print("fill done", flush=True)

Xet Storage Details

Size:
8.06 kB
·
Xet hash:
0f6de9fcafc6835c97774b7776e15e0bc7f7ed1ae268de1af6c1acdc14211856

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.