mirror of
https://github.com/safishamsi/graphify.git
synced 2026-07-13 02:47:00 +00:00
feat: graphify clone <github-url> — clone any repo and run full pipeline on it
This commit is contained in:
@@ -906,6 +906,59 @@ def claude_uninstall(project_dir: Path | None = None) -> None:
|
||||
_uninstall_claude_hook(project_dir or Path("."))
|
||||
|
||||
|
||||
def _clone_repo(url: str, branch: str | None = None, out_dir: Path | None = None) -> Path:
|
||||
"""Clone a GitHub repo to a local cache dir and return the path.
|
||||
|
||||
Clones into ~/.graphify/repos/<owner>/<repo> by default so repeated
|
||||
runs on the same URL reuse the existing clone (git pull instead of clone).
|
||||
"""
|
||||
import subprocess as _sp
|
||||
import re as _re
|
||||
|
||||
# Normalise URL — strip trailing .git if present
|
||||
url = url.rstrip("/")
|
||||
if not url.endswith(".git"):
|
||||
git_url = url + ".git"
|
||||
else:
|
||||
git_url = url
|
||||
url = url[:-4]
|
||||
|
||||
# Extract owner/repo from URL
|
||||
m = _re.search(r"github\.com[:/]([^/]+)/([^/]+?)(?:\.git)?$", url)
|
||||
if not m:
|
||||
print(f"error: not a recognised GitHub URL: {url}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
owner, repo = m.group(1), m.group(2)
|
||||
|
||||
if out_dir:
|
||||
dest = out_dir
|
||||
else:
|
||||
dest = Path.home() / ".graphify" / "repos" / owner / repo
|
||||
|
||||
if dest.exists():
|
||||
print(f"Repo already cloned at {dest} — pulling latest...", flush=True)
|
||||
cmd = ["git", "-C", str(dest), "pull"]
|
||||
if branch:
|
||||
cmd += ["origin", branch]
|
||||
result = _sp.run(cmd, capture_output=True, text=True)
|
||||
if result.returncode != 0:
|
||||
print(f"warning: git pull failed:\n{result.stderr}", file=sys.stderr)
|
||||
else:
|
||||
dest.parent.mkdir(parents=True, exist_ok=True)
|
||||
print(f"Cloning {url} → {dest} ...", flush=True)
|
||||
cmd = ["git", "clone", "--depth", "1"]
|
||||
if branch:
|
||||
cmd += ["--branch", branch]
|
||||
cmd += [git_url, str(dest)]
|
||||
result = _sp.run(cmd, capture_output=True, text=True)
|
||||
if result.returncode != 0:
|
||||
print(f"error: git clone failed:\n{result.stderr}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Ready at: {dest}", flush=True)
|
||||
return dest
|
||||
|
||||
|
||||
def main() -> None:
|
||||
# Check all known skill install locations for a stale version stamp.
|
||||
# Skip during install/uninstall (hook writes trigger a fresh check anyway).
|
||||
@@ -923,6 +976,9 @@ def main() -> None:
|
||||
print(" --graph <path> path to graph.json (default graphify-out/graph.json)")
|
||||
print(" explain \"X\" plain-language explanation of a node and its neighbors")
|
||||
print(" --graph <path> path to graph.json (default graphify-out/graph.json)")
|
||||
print(" clone <github-url> clone a GitHub repo locally and print its path for /graphify")
|
||||
print(" --branch <branch> checkout a specific branch (default: repo default)")
|
||||
print(" --out <dir> clone to a custom directory (default: ~/.graphify/repos/<owner>/<repo>)")
|
||||
print(" add <url> fetch a URL and save it to ./raw, then update the graph")
|
||||
print(" --author \"Name\" tag the author of the content")
|
||||
print(" --contributor \"Name\" tag who added it to the corpus")
|
||||
@@ -1359,6 +1415,25 @@ def main() -> None:
|
||||
from graphify.watch import check_update
|
||||
check_update(Path(sys.argv[2]).resolve())
|
||||
sys.exit(0)
|
||||
elif cmd == "clone":
|
||||
if len(sys.argv) < 3:
|
||||
print("Usage: graphify clone <github-url> [--branch <branch>] [--out <dir>]", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
url = sys.argv[2]
|
||||
branch: str | None = None
|
||||
out_dir: Path | None = None
|
||||
args = sys.argv[3:]
|
||||
i = 0
|
||||
while i < len(args):
|
||||
if args[i] == "--branch" and i + 1 < len(args):
|
||||
branch = args[i + 1]; i += 2
|
||||
elif args[i] == "--out" and i + 1 < len(args):
|
||||
out_dir = Path(args[i + 1]); i += 2
|
||||
else:
|
||||
i += 1
|
||||
local_path = _clone_repo(url, branch=branch, out_dir=out_dir)
|
||||
print(local_path)
|
||||
|
||||
elif cmd == "benchmark":
|
||||
from graphify.benchmark import run_benchmark, print_benchmark
|
||||
graph_path = sys.argv[2] if len(sys.argv) > 2 else "graphify-out/graph.json"
|
||||
|
||||
@@ -13,6 +13,8 @@ Turn any folder of files into a navigable knowledge graph with community detecti
|
||||
```
|
||||
/graphify # full pipeline on current directory → Obsidian vault
|
||||
/graphify <path> # full pipeline on specific path
|
||||
/graphify https://github.com/<owner>/<repo> # clone repo then run full pipeline on it
|
||||
/graphify https://github.com/<owner>/<repo> --branch <branch> # clone a specific branch
|
||||
/graphify <path> --mode deep # thorough extraction, richer INFERRED edges
|
||||
/graphify <path> --update # incremental - re-extract only new/changed files
|
||||
/graphify <path> --directed # build directed graph (preserves edge direction: source→target)
|
||||
@@ -57,8 +59,20 @@ Use it for:
|
||||
|
||||
If no path was given, use `.` (current directory). Do not ask the user for a path.
|
||||
|
||||
If the path argument starts with `https://github.com/` or `http://github.com/`, treat it as a GitHub URL — run Step 0 before anything else, then continue with the resolved local path.
|
||||
|
||||
Follow these steps in order. Do not skip steps.
|
||||
|
||||
### Step 0 - Clone GitHub repo (only if a GitHub URL was given)
|
||||
|
||||
```bash
|
||||
# Clone the repo (or pull if already cloned) and capture the local path
|
||||
LOCAL_PATH=$(graphify clone <github-url> [--branch <branch>])
|
||||
# Use LOCAL_PATH as the target for all subsequent steps
|
||||
```
|
||||
|
||||
Graphify clones into `~/.graphify/repos/<owner>/<repo>` so repeated calls on the same URL reuse the existing clone. Print the resolved path to the user before continuing. If `--branch` was specified, pass it through.
|
||||
|
||||
### Step 1 - Ensure graphify is installed
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user