Fresh repository history for elektrine/tarakan hosted at https://git.elektrine.com/elektrine/tarakan.
449 lines
13 KiB
Elixir
449 lines
13 KiB
Elixir
defmodule Tarakan.GitHubStub do
|
|
@moduledoc false
|
|
|
|
@behaviour Tarakan.GitHubClient
|
|
|
|
@root_tree_sha String.duplicate("1", 40)
|
|
@lib_tree_sha String.duplicate("2", 40)
|
|
@readme_blob_sha String.duplicate("3", 40)
|
|
@source_blob_sha String.duplicate("4", 40)
|
|
@large_blob_sha String.duplicate("5", 40)
|
|
@binary_blob_sha String.duplicate("6", 40)
|
|
@default_commit_sha String.duplicate("7", 40)
|
|
@symlink_blob_sha String.duplicate("9", 40)
|
|
@submodule_sha String.duplicate("a", 40)
|
|
@many_lines_blob_sha String.duplicate("d", 40)
|
|
@truncated_tree_sha String.duplicate("e", 40)
|
|
@unsafe_html_blob_sha String.duplicate("f", 40)
|
|
@readme "# Codex\n"
|
|
@source "defmodule Codex do\n def hello, do: :world\nend\n"
|
|
@unsafe_html "</code><script id=\"source-xss\">alert(1)</script>\n"
|
|
|
|
@codex_etag ~s(W/"codex-metadata")
|
|
|
|
def codex_etag, do: @codex_etag
|
|
|
|
@impl true
|
|
def fetch_repository(owner, name, opts \\ [])
|
|
|
|
def fetch_repository("openai", "codex", opts) do
|
|
if Keyword.get(opts, :etag) == @codex_etag do
|
|
:not_modified
|
|
else
|
|
{:ok,
|
|
%{
|
|
github_id: 95_959_834,
|
|
node_id: "R_kgDOcodex000",
|
|
host: "github.com",
|
|
owner: "openai",
|
|
name: "codex",
|
|
canonical_url: "https://github.com/openai/codex",
|
|
default_branch: "main",
|
|
description: "Lightweight coding agent that runs in your terminal",
|
|
primary_language: "Rust",
|
|
stars_count: 42_000,
|
|
forks_count: 4_200,
|
|
archived: false,
|
|
private: false,
|
|
visibility: "public",
|
|
last_synced_at: ~U[2026-07-10 04:00:00.000000Z],
|
|
etag: @codex_etag
|
|
}}
|
|
end
|
|
end
|
|
|
|
def fetch_repository("missing", "repository", _opts), do: {:error, :not_found}
|
|
|
|
# Renamed on the host: the old path 301s, the immutable id resolves to acme/widget.
|
|
def fetch_repository("legacy", "widget", _opts), do: {:error, :moved}
|
|
|
|
def fetch_repository("acme", "widget", _opts), do: {:ok, renamed_widget_metadata()}
|
|
|
|
def fetch_repository("acme", "gadget", _opts) do
|
|
{:ok,
|
|
%{
|
|
github_id: 77_778,
|
|
node_id: "R_kgDOgadget00",
|
|
host: "github.com",
|
|
owner: "acme",
|
|
name: "gadget",
|
|
canonical_url: "https://github.com/acme/gadget",
|
|
default_branch: "main",
|
|
description: "Gadget toolkit",
|
|
primary_language: "Go",
|
|
stars_count: 21,
|
|
forks_count: 2,
|
|
archived: false,
|
|
private: false,
|
|
visibility: "public",
|
|
last_synced_at: ~U[2026-07-10 04:00:00.000000Z]
|
|
}}
|
|
end
|
|
|
|
def fetch_repository("private", "repository", _opts) do
|
|
{:ok,
|
|
%{
|
|
github_id: 12_345,
|
|
host: "github.com",
|
|
owner: "private",
|
|
name: "repository",
|
|
canonical_url: "https://github.com/private/repository",
|
|
default_branch: "main",
|
|
private: true,
|
|
visibility: "private"
|
|
}}
|
|
end
|
|
|
|
def fetch_repository("rate", "limited", _opts), do: {:error, :rate_limited}
|
|
|
|
def fetch_repository("flip", "repository", _opts) do
|
|
count = Process.get(:github_flip_identity_count, 0)
|
|
Process.put(:github_flip_identity_count, count + 1)
|
|
|
|
if count == 0 do
|
|
{:ok,
|
|
%{
|
|
github_id: 88_888,
|
|
host: "github.com",
|
|
owner: "flip",
|
|
name: "repository",
|
|
canonical_url: "https://github.com/flip/repository",
|
|
default_branch: "main",
|
|
private: false,
|
|
visibility: "public"
|
|
}}
|
|
else
|
|
{:ok,
|
|
%{
|
|
github_id: 88_888,
|
|
owner: "flip",
|
|
name: "repository",
|
|
default_branch: "main",
|
|
private: true,
|
|
visibility: "private"
|
|
}}
|
|
end
|
|
end
|
|
|
|
def fetch_repository("lateflip", "repository", _opts) do
|
|
count = Process.get(:github_late_flip_identity_count, 0)
|
|
Process.put(:github_late_flip_identity_count, count + 1)
|
|
|
|
if count < 3 do
|
|
{:ok,
|
|
%{
|
|
github_id: 99_999,
|
|
host: "github.com",
|
|
owner: "lateflip",
|
|
name: "repository",
|
|
canonical_url: "https://github.com/lateflip/repository",
|
|
default_branch: "main",
|
|
private: false,
|
|
visibility: "public"
|
|
}}
|
|
else
|
|
{:ok,
|
|
%{
|
|
github_id: 99_999,
|
|
owner: "lateflip",
|
|
name: "repository",
|
|
default_branch: "main",
|
|
private: true,
|
|
visibility: "private"
|
|
}}
|
|
end
|
|
end
|
|
|
|
def fetch_repository(_owner, _name, _opts), do: {:error, :unavailable}
|
|
|
|
@impl true
|
|
def fetch_repository_by_id(95_959_834), do: fetch_repository("openai", "codex", [])
|
|
def fetch_repository_by_id(12_345), do: fetch_repository("private", "repository", [])
|
|
def fetch_repository_by_id(88_888), do: fetch_repository("flip", "repository", [])
|
|
def fetch_repository_by_id(99_999), do: fetch_repository("lateflip", "repository", [])
|
|
def fetch_repository_by_id(77_777), do: {:ok, renamed_widget_metadata()}
|
|
def fetch_repository_by_id(_github_id), do: {:error, :not_found}
|
|
|
|
defp renamed_widget_metadata do
|
|
%{
|
|
github_id: 77_777,
|
|
node_id: "R_kgDOwidget00",
|
|
host: "github.com",
|
|
owner: "acme",
|
|
name: "widget",
|
|
canonical_url: "https://github.com/acme/widget",
|
|
default_branch: "main",
|
|
description: "Widget toolkit",
|
|
primary_language: "Elixir",
|
|
stars_count: 12,
|
|
forks_count: 3,
|
|
archived: false,
|
|
private: false,
|
|
visibility: "public",
|
|
last_synced_at: ~U[2026-07-10 04:00:00.000000Z]
|
|
}
|
|
end
|
|
|
|
@impl true
|
|
def fetch_commit("openai", "codex", "dead" <> _rest), do: {:error, :not_found}
|
|
|
|
def fetch_commit("openai", "codex", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") do
|
|
{:ok,
|
|
%{
|
|
sha: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
tree_sha: @root_tree_sha,
|
|
committed_at: ~U[2026-07-01 12:00:00Z]
|
|
}}
|
|
end
|
|
|
|
def fetch_commit("openai", "codex", "cccccccccccccccccccccccccccccccccccccccc") do
|
|
{:ok,
|
|
%{
|
|
sha: "cccccccccccccccccccccccccccccccccccccccc",
|
|
tree_sha: @truncated_tree_sha,
|
|
committed_at: ~U[2026-07-01 12:00:00Z]
|
|
}}
|
|
end
|
|
|
|
# Second precision, mirroring what the GitHub API actually returns.
|
|
def fetch_commit("openai", "codex", sha),
|
|
do:
|
|
{:ok,
|
|
%{
|
|
sha: String.downcase(sha),
|
|
tree_sha: @root_tree_sha,
|
|
committed_at: ~U[2026-07-01 12:00:00Z]
|
|
}}
|
|
|
|
def fetch_commit("acme", "widget", sha), do: fetch_commit("openai", "codex", sha)
|
|
def fetch_commit("acme", "gadget", sha), do: fetch_commit("openai", "codex", sha)
|
|
def fetch_commit("rate", "limited", _sha), do: {:error, :rate_limited}
|
|
def fetch_commit("flip", "repository", sha), do: fetch_commit("openai", "codex", sha)
|
|
def fetch_commit("lateflip", "repository", sha), do: fetch_commit("openai", "codex", sha)
|
|
def fetch_commit(_owner, _name, _sha), do: {:error, :unavailable}
|
|
|
|
@impl true
|
|
def fetch_branch_head("openai", "codex", "main") do
|
|
{:ok,
|
|
%{
|
|
sha: @default_commit_sha,
|
|
tree_sha: @root_tree_sha,
|
|
committed_at: ~U[2026-07-01 12:00:00Z]
|
|
}}
|
|
end
|
|
|
|
def fetch_branch_head("openai", "codex", "develop") do
|
|
{:ok,
|
|
%{
|
|
sha: String.duplicate("8", 40),
|
|
tree_sha: @root_tree_sha,
|
|
committed_at: ~U[2026-07-02 12:00:00Z]
|
|
}}
|
|
end
|
|
|
|
def fetch_branch_head("acme", "widget", branch),
|
|
do: fetch_branch_head("openai", "codex", branch)
|
|
|
|
def fetch_branch_head("acme", "gadget", branch),
|
|
do: fetch_branch_head("openai", "codex", branch)
|
|
|
|
def fetch_branch_head("rate", "limited", _branch), do: {:error, :rate_limited}
|
|
def fetch_branch_head(_owner, _name, _branch), do: {:error, :not_found}
|
|
|
|
@impl true
|
|
def list_branches("openai", "codex"), do: {:ok, ["main", "develop", "feature/auth"]}
|
|
def list_branches("acme", "widget"), do: list_branches("openai", "codex")
|
|
def list_branches("acme", "gadget"), do: list_branches("openai", "codex")
|
|
def list_branches("rate", "limited"), do: {:error, :rate_limited}
|
|
def list_branches(_owner, _name), do: {:error, :not_found}
|
|
|
|
@impl true
|
|
def fetch_tree("openai", "codex", @root_tree_sha, recursive) do
|
|
direct_entries = [
|
|
%{path: "lib", mode: "040000", type: "tree", sha: @lib_tree_sha, size: nil},
|
|
%{
|
|
path: "README.md",
|
|
mode: "100644",
|
|
type: "blob",
|
|
sha: @readme_blob_sha,
|
|
size: byte_size(@readme)
|
|
},
|
|
%{
|
|
path: "space # 100%.txt",
|
|
mode: "100644",
|
|
type: "blob",
|
|
sha: @readme_blob_sha,
|
|
size: byte_size(@readme)
|
|
},
|
|
%{
|
|
path: "λ.ex",
|
|
mode: "100644",
|
|
type: "blob",
|
|
sha: @source_blob_sha,
|
|
size: byte_size(@source)
|
|
},
|
|
%{
|
|
path: "large.txt",
|
|
mode: "100644",
|
|
type: "blob",
|
|
sha: @large_blob_sha,
|
|
size: 512 * 1_024 + 1
|
|
},
|
|
%{
|
|
path: "binary.dat",
|
|
mode: "100644",
|
|
type: "blob",
|
|
sha: @binary_blob_sha,
|
|
size: 4
|
|
},
|
|
%{
|
|
path: "many-lines.txt",
|
|
mode: "100644",
|
|
type: "blob",
|
|
sha: @many_lines_blob_sha,
|
|
size: 10_000
|
|
},
|
|
%{
|
|
path: "unsafe.html",
|
|
mode: "100644",
|
|
type: "blob",
|
|
sha: @unsafe_html_blob_sha,
|
|
size: byte_size(@unsafe_html)
|
|
},
|
|
%{
|
|
path: "source-link",
|
|
mode: "120000",
|
|
type: "symlink",
|
|
sha: @symlink_blob_sha,
|
|
size: 12
|
|
},
|
|
%{
|
|
path: "dependency",
|
|
mode: "160000",
|
|
type: "submodule",
|
|
sha: @submodule_sha,
|
|
size: nil
|
|
}
|
|
]
|
|
|
|
entries =
|
|
if recursive do
|
|
direct_entries ++
|
|
[
|
|
%{
|
|
path: "lib/codex.ex",
|
|
mode: "100644",
|
|
type: "blob",
|
|
sha: @source_blob_sha,
|
|
size: byte_size(@source)
|
|
}
|
|
]
|
|
else
|
|
direct_entries
|
|
end
|
|
|
|
{:ok, %{sha: @root_tree_sha, truncated: false, entries: entries}}
|
|
end
|
|
|
|
def fetch_tree("openai", "codex", @lib_tree_sha, _recursive) do
|
|
{:ok,
|
|
%{
|
|
sha: @lib_tree_sha,
|
|
truncated: false,
|
|
entries: [
|
|
%{
|
|
path: "codex.ex",
|
|
mode: "100644",
|
|
type: "blob",
|
|
sha: @source_blob_sha,
|
|
size: byte_size(@source)
|
|
}
|
|
]
|
|
}}
|
|
end
|
|
|
|
def fetch_tree("openai", "codex", @truncated_tree_sha, _recursive) do
|
|
{:ok, %{sha: @truncated_tree_sha, truncated: true, entries: []}}
|
|
end
|
|
|
|
def fetch_tree("acme", "widget", tree_sha, recursive),
|
|
do: fetch_tree("openai", "codex", tree_sha, recursive)
|
|
|
|
def fetch_tree("acme", "gadget", tree_sha, recursive),
|
|
do: fetch_tree("openai", "codex", tree_sha, recursive)
|
|
|
|
def fetch_tree("rate", "limited", _tree_sha, _recursive), do: {:error, :rate_limited}
|
|
|
|
def fetch_tree("flip", "repository", tree_sha, recursive),
|
|
do: fetch_tree("openai", "codex", tree_sha, recursive)
|
|
|
|
def fetch_tree("lateflip", "repository", tree_sha, recursive),
|
|
do: fetch_tree("openai", "codex", tree_sha, recursive)
|
|
|
|
def fetch_tree(_owner, _name, _tree_sha, _recursive), do: {:error, :not_found}
|
|
|
|
@impl true
|
|
def fetch_text_blob("openai", "codex", @readme_blob_sha) do
|
|
{:ok, %{sha: @readme_blob_sha, size: byte_size(@readme), content: @readme}}
|
|
end
|
|
|
|
def fetch_text_blob("openai", "codex", @source_blob_sha) do
|
|
{:ok, %{sha: @source_blob_sha, size: byte_size(@source), content: @source}}
|
|
end
|
|
|
|
def fetch_text_blob("openai", "codex", @binary_blob_sha) do
|
|
{:ok, %{sha: @binary_blob_sha, size: 4, content: <<0, 1, 2, 3>>}}
|
|
end
|
|
|
|
def fetch_text_blob("openai", "codex", @many_lines_blob_sha) do
|
|
content = String.duplicate("\n", 10_000)
|
|
{:ok, %{sha: @many_lines_blob_sha, size: byte_size(content), content: content}}
|
|
end
|
|
|
|
def fetch_text_blob("openai", "codex", @unsafe_html_blob_sha) do
|
|
{:ok,
|
|
%{
|
|
sha: @unsafe_html_blob_sha,
|
|
size: byte_size(@unsafe_html),
|
|
content: @unsafe_html
|
|
}}
|
|
end
|
|
|
|
def fetch_text_blob("openai", "codex", @large_blob_sha), do: {:error, :unavailable}
|
|
|
|
def fetch_text_blob("acme", "widget", blob_sha),
|
|
do: fetch_text_blob("openai", "codex", blob_sha)
|
|
|
|
def fetch_text_blob("acme", "gadget", blob_sha),
|
|
do: fetch_text_blob("openai", "codex", blob_sha)
|
|
|
|
def fetch_text_blob("rate", "limited", _blob_sha), do: {:error, :rate_limited}
|
|
def fetch_text_blob(_owner, _name, _blob_sha), do: {:error, :not_found}
|
|
end
|
|
|
|
defmodule Tarakan.GitHub.OAuthStub do
|
|
@moduledoc false
|
|
|
|
@behaviour Tarakan.GitHub.OAuthClient
|
|
|
|
@impl true
|
|
def exchange_code("valid-code", verifier, redirect_uri)
|
|
when is_binary(verifier) and is_binary(redirect_uri),
|
|
do: {:ok, "temporary-user-token"}
|
|
|
|
def exchange_code(_code, _verifier, _redirect_uri), do: {:error, :authorization_failed}
|
|
|
|
@impl true
|
|
def fetch_user("temporary-user-token") do
|
|
{:ok,
|
|
%{
|
|
provider_uid: 58_399_067,
|
|
provider_login: "TarakanTester",
|
|
name: "Tarakan Tester",
|
|
avatar_url: "https://avatars.githubusercontent.com/u/58399067",
|
|
profile_url: "https://github.com/TarakanTester"
|
|
}}
|
|
end
|
|
|
|
def fetch_user(_token), do: {:error, :authorization_failed}
|
|
end
|