diff --git a/.formatter.exs b/.formatter.exs index d2cda26..c185fe1 100644 --- a/.formatter.exs +++ b/.formatter.exs @@ -1,4 +1,4 @@ # Used by "mix format" [ - inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] + inputs: ["{mix,.formatter}.exs", "{config,lib,test,examples}/**/*.{ex,exs}"] ] diff --git a/README.md b/README.md index 9d22121..edd18dc 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,15 @@ refetch. Perfect for agent loops that want snapshot semantics. The on-disk format is a standard bare git repo — `git log`, `git fsck`, and friends all work on it. +There's a runnable worked example at +[`examples/partial_clone_demo.exs`](examples/partial_clone_demo.exs) — +`Mix.install`, partial clone, one file read, with `memory_report/1` +showing `blob_count: 0 -> 1` around the read: + +```sh +elixir examples/partial_clone_demo.exs +``` + ### Private repos ```elixir diff --git a/examples/partial_clone_demo.exs b/examples/partial_clone_demo.exs new file mode 100644 index 0000000..fa19b90 --- /dev/null +++ b/examples/partial_clone_demo.exs @@ -0,0 +1,32 @@ +# Partial clone, worked example. +# +# Clones a public repo under a `blob:none` filter — the server ships +# refs + commits + trees but NO file contents — then reads one file. +# The `blob_count: 0 -> 1` transition around the read is the proof +# that exactly one blob crossed the wire. +# +# Run with: elixir examples/partial_clone_demo.exs + +Mix.install([{:exgit, "~> 0.1.0"}]) + +stats = fn repo -> + Exgit.Repository.memory_report(repo) |> Map.take([:blob_count, :tree_count, :cache_bytes]) +end + +# Partial clone: refs + commits + trees cross the wire. No file contents. +{:ok, repo} = Exgit.clone("https://github.com/elixir-ai-tools/just_bash", filter: {:blob, :none}) +IO.inspect(stats.(repo), label: "after clone ") + +# The size probe refuses to fetch — gate on it before pulling big files. +{:error, :not_local} = Exgit.FS.size(repo, "HEAD", "README.md") + +# Reading ONE file fetches ONE blob. +{:ok, {_mode, blob}, repo} = Exgit.FS.read_path(repo, "HEAD", "README.md") +first_line = blob.data |> String.split("\n", parts: 2) |> hd() +IO.puts(~s(read README.md: #{byte_size(blob.data)} bytes — "#{first_line}")) +IO.inspect(stats.(repo), label: "after one read") + +# Navigation stays free: directory listings come from the local +# trees, so blob_count doesn't move. +{:ok, entries, repo} = Exgit.FS.ls(repo, "HEAD", "") +IO.puts("ls /: #{length(entries)} entries — blob_count still #{stats.(repo).blob_count}")