|
| 1 | +#!/usr/bin/env bash |
| 2 | +# |
| 3 | +# mine.sh — clone a public C# repo (shallow) and run own-check over it, writing a |
| 4 | +# structured Markdown report. Evaluation tooling for the analyser itself: see |
| 5 | +# docs/notes/mining.md. Mine ONE repo at a time — shallow, read-only; this is a |
| 6 | +# spot-check, not a crawler. Be a good citizen. |
| 7 | +# |
| 8 | +# Usage: |
| 9 | +# scripts/mine.sh [--ref <branch|tag|sha>] [--paths <subdir>] [--format human] |
| 10 | +# [--out <dir>] [--keep-src] <owner/repo | git-url> |
| 11 | +# |
| 12 | +# Output goes to corpus/mined/<slug>/ (gitignored): findings.txt, extract.log, |
| 13 | +# report.md, report.json (and src/ with --keep-src). |
| 14 | +# |
| 15 | +# Requires: git, a .NET SDK (dotnet), Python 3.11+. |
| 16 | + |
| 17 | +set -euo pipefail |
| 18 | + |
| 19 | +ref="" |
| 20 | +subpaths="" |
| 21 | +format="human" |
| 22 | +outdir="" |
| 23 | +keep_src=0 |
| 24 | +target="" |
| 25 | + |
| 26 | +while [[ $# -gt 0 ]]; do |
| 27 | + case "$1" in |
| 28 | + --ref) [[ $# -ge 2 ]] || { echo "mine: --ref needs a value" >&2; exit 2; }; ref="$2"; shift 2 ;; |
| 29 | + --paths) [[ $# -ge 2 ]] || { echo "mine: --paths needs a value" >&2; exit 2; }; subpaths="$2"; shift 2 ;; |
| 30 | + --format) [[ $# -ge 2 ]] || { echo "mine: --format needs a value" >&2; exit 2; }; format="$2"; shift 2 ;; |
| 31 | + --out) [[ $# -ge 2 ]] || { echo "mine: --out needs a value" >&2; exit 2; }; outdir="$2"; shift 2 ;; |
| 32 | + --keep-src) keep_src=1; shift ;; |
| 33 | + -h|--help) sed -n '2,19p' "$0"; exit 0 ;; |
| 34 | + --) shift; [[ $# -gt 0 ]] && { target="$1"; shift; } ;; |
| 35 | + *) target="$1"; shift ;; |
| 36 | + esac |
| 37 | +done |
| 38 | + |
| 39 | +[[ -n "$target" ]] || { echo "mine: a target (owner/repo or git URL) is required" >&2; exit 2; } |
| 40 | +command -v git >/dev/null || { echo "mine: git not found" >&2; exit 2; } |
| 41 | +command -v python >/dev/null || { echo "mine: python not found" >&2; exit 2; } |
| 42 | +if ! command -v dotnet >/dev/null; then |
| 43 | + echo "mine: a .NET SDK (dotnet) is required to run the extractor." >&2 |
| 44 | + echo "mine: run this in CI via .github/workflows/mine.yml, or install the SDK." >&2 |
| 45 | + exit 2 |
| 46 | +fi |
| 47 | + |
| 48 | +root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" |
| 49 | + |
| 50 | +# owner/repo -> https URL; pass full git URLs through untouched. |
| 51 | +case "$target" in |
| 52 | + http://*|https://*|git@*) url="$target" ;; |
| 53 | + *) url="https://github.com/${target}.git" ;; |
| 54 | +esac |
| 55 | +slug="$(printf '%s' "$target" | sed -E 's#^https?://[^/]+/##; s#^git@[^:]+:##; s#\.git$##; s#[^A-Za-z0-9._-]#_#g')" |
| 56 | +[[ -n "$outdir" ]] || outdir="$root/corpus/mined/$slug" |
| 57 | + |
| 58 | +mkdir -p "$outdir" |
| 59 | +src="$outdir/src" |
| 60 | +rm -rf "$src" |
| 61 | + |
| 62 | +echo "mine: $target -> $outdir" >&2 |
| 63 | +clone_args=(--quiet --depth 1) |
| 64 | +[[ -n "$ref" ]] && clone_args+=(--branch "$ref") |
| 65 | +git clone "${clone_args[@]}" "$url" "$src" |
| 66 | +commit="$(git -C "$src" rev-parse HEAD)" |
| 67 | + |
| 68 | +scan="$src" |
| 69 | +[[ -n "$subpaths" ]] && scan="$src/$subpaths" |
| 70 | +[[ -e "$scan" ]] || { echo "mine: scan path '$scan' does not exist in the repo" >&2; exit 2; } |
| 71 | + |
| 72 | +echo "mine: scanning $scan (commit $commit)" >&2 |
| 73 | +# own-check sends host-parseable findings to stdout and dotnet/build chatter to |
| 74 | +# stderr; keep them apart. Without --fail-on-finding it exits 0 even with leaks; |
| 75 | +# rc>=2 is a hard error (bad facts) — note it but still report what we captured. |
| 76 | +set +e |
| 77 | +"$root/scripts/own-check.sh" --root "$root" --format "$format" -- "$scan" \ |
| 78 | + >"$outdir/findings.txt" 2>"$outdir/extract.log" |
| 79 | +rc=$? |
| 80 | +set -e |
| 81 | +[[ "$rc" -ge 2 ]] && echo "mine: own-check hard error (rc=$rc); see $outdir/extract.log" >&2 |
| 82 | + |
| 83 | +python "$root/scripts/mine_report.py" "$outdir/findings.txt" \ |
| 84 | + --repo "$target" --commit "$commit" --json "$outdir/report.json" \ |
| 85 | + >"$outdir/report.md" |
| 86 | + |
| 87 | +[[ "$keep_src" -eq 1 ]] || rm -rf "$src" |
| 88 | + |
| 89 | +echo "mine: done -> $outdir/report.md" >&2 |
| 90 | +grep -E '^- findings:' "$outdir/report.md" || true |
0 commit comments