package git import ( "testing" ) func TestParseTangledURL(t *testing.T) { tests := []struct { name string input string want *TangledRepo }{ { name: "ssh", input: "git@tangled.sh:alice.bsky.social/my-project", want: &TangledRepo{Owner: "alice.bsky.social", Name: "my-project"}, }, { name: "ssh with .git", input: "git@tangled.sh:alice.bsky.social/my-project.git", want: &TangledRepo{Owner: "alice.bsky.social", Name: "my-project"}, }, { name: "https", input: "https://tangled.sh/alice.bsky.social/my-project", want: &TangledRepo{Owner: "alice.bsky.social", Name: "my-project"}, }, { name: "https with .git", input: "https://tangled.sh/alice.bsky.social/my-project.git", want: &TangledRepo{Owner: "alice.bsky.social", Name: "my-project"}, }, { name: "non-tangled ssh", input: "git@github.com:user/repo", want: nil, }, { name: "non-tangled https", input: "https://github.com/user/repo", want: nil, }, { name: "knot ssh url", input: "git@knot.example.com:alice.bsky.social/my-project", want: &TangledRepo{Owner: "alice.bsky.social", Name: "my-project"}, }, { name: "knot https url", input: "https://knot.example.com/alice.bsky.social/my-project", want: &TangledRepo{Owner: "alice.bsky.social", Name: "my-project"}, }, { name: "ssh repo name with dots", input: "git@tangled.sh:alice.bsky.social/my.project", want: &TangledRepo{Owner: "alice.bsky.social", Name: "my.project"}, }, { name: "ssh repo name with dots and .git", input: "git@tangled.sh:alice.bsky.social/my.project.git", want: &TangledRepo{Owner: "alice.bsky.social", Name: "my.project"}, }, { name: "empty", input: "", want: nil, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := ParseTangledURL(tt.input) if tt.want == nil { if got != nil { t.Errorf("ParseTangledURL(%q) = %+v, want nil", tt.input, got) } return } if got == nil { t.Fatalf("ParseTangledURL(%q) = nil, want %+v", tt.input, tt.want) } if got.Owner != tt.want.Owner || got.Name != tt.want.Name { t.Errorf("ParseTangledURL(%q) = {%s, %s}, want {%s, %s}", tt.input, got.Owner, got.Name, tt.want.Owner, tt.want.Name) } }) } } func TestTangledRepo_FullName(t *testing.T) { repo := TangledRepo{Owner: "alice.bsky.social", Name: "my-project"} if got := repo.FullName(); got != "alice.bsky.social/my-project" { t.Errorf("FullName() = %q", got) } } func TestParseRemotes(t *testing.T) { input := `origin git@tangled.sh:alice.bsky.social/my-project (fetch) origin git@tangled.sh:alice.bsky.social/my-project (push) upstream https://tangled.sh/bob.bsky.social/my-project (fetch) upstream https://tangled.sh/bob.bsky.social/my-project (push) ` remotes := ParseRemotes(input) if len(remotes) != 2 { t.Fatalf("got %d remotes, want 2", len(remotes)) } if remotes[0].Name != "origin" { t.Errorf("remotes[0].Name = %q, want 'origin'", remotes[0].Name) } if remotes[0].FetchURL != "git@tangled.sh:alice.bsky.social/my-project" { t.Errorf("remotes[0].FetchURL = %q", remotes[0].FetchURL) } if remotes[0].PushURL != "git@tangled.sh:alice.bsky.social/my-project" { t.Errorf("remotes[0].PushURL = %q", remotes[0].PushURL) } if remotes[1].Name != "upstream" { t.Errorf("remotes[1].Name = %q, want 'upstream'", remotes[1].Name) } if remotes[1].FetchURL != "https://tangled.sh/bob.bsky.social/my-project" { t.Errorf("remotes[1].FetchURL = %q", remotes[1].FetchURL) } } func TestParseRemotes_Empty(t *testing.T) { remotes := ParseRemotes("") if len(remotes) != 0 { t.Errorf("got %d remotes for empty input, want 0", len(remotes)) } } func TestParseRemotes_MalformedLines(t *testing.T) { input := `origin git@tangled.sh:alice/repo (fetch) bad-line also-bad url origin git@tangled.sh:alice/repo (push) ` remotes := ParseRemotes(input) if len(remotes) != 1 { t.Fatalf("got %d remotes, want 1", len(remotes)) } if remotes[0].FetchURL == "" || remotes[0].PushURL == "" { t.Error("expected both fetch and push URLs") } }