Skip to content

Commit

Permalink
Support installing mods from Gitlab repositories. Closes #619
Browse files Browse the repository at this point in the history
  • Loading branch information
pskrbasu authored Jan 7, 2025
1 parent 24d8f15 commit 7077fa4
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 22 deletions.
54 changes: 32 additions & 22 deletions modinstaller/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,36 +31,41 @@ func getGitUrl(modName string, urlMode GitUrlMode) string {
}

func transformToGitURL(input string, urlMode GitUrlMode) string {
// If HTTPS mode is selected
if urlMode == GitUrlModeHTTPS {
if !strings.HasPrefix(input, "https://") {
input = "https://" + input
}
return input
}

if !strings.HasPrefix(input, "github.com") {
return input
}

if !strings.HasPrefix(input, "git@") {
input = "git@" + input
}
// check for GitHub and GitLab-specific transformations
// gitlab can have domain names like example.gitlab.com
if strings.Contains(input, "github.com") || strings.Contains(input, "gitlab.com") {
// For SSH mode
if !strings.HasPrefix(input, "git@") {
input = "git@" + input
}

if !strings.HasSuffix(input, ".git") {
input += ".git"
}
if !strings.HasSuffix(input, ".git") {
input += ".git"
}

// Add a colon after the "[email protected]" part, so it replaces the first / with :
if !strings.Contains(input, ":") {
index := strings.Index(input, "/")
input = input[:index] + ":" + input[index+1:]
// Add a colon after the "git@<host>" part to replace the first /
if !strings.Contains(input, ":") {
index := strings.Index(input, "/")
if index > -1 {
input = input[:index] + ":" + input[index+1:]
}
}
}

// Return the input unmodified for unsupported hosts or already formatted URLs
return input
}

func getRefs(repo string) ([]*plumbing.Reference, error) {
gitHubToken := getGitToken()
gitToken := getGitToken()

// Create the remote with repository URL
rem := git.NewRemote(memory.NewStorage(), &config.RemoteConfig{
Expand All @@ -70,9 +75,9 @@ func getRefs(repo string) ([]*plumbing.Reference, error) {

var listOption git.ListOptions
// if a token was provided, use it
if gitHubToken != "" {
if gitToken != "" {
listOption = git.ListOptions{
Auth: getGitAuthForToken(gitHubToken),
Auth: getGitAuthForToken(gitToken),
}
}
// load remote references
Expand All @@ -83,21 +88,26 @@ func getRefs(repo string) ([]*plumbing.Reference, error) {
return refs, nil
}

func getGitAuthForToken(gitHubToken string) transport.AuthMethod {
if gitHubToken == "" {
func getGitAuthForToken(gitToken string) transport.AuthMethod {
if gitToken == "" {
return nil
}
var auth transport.AuthMethod
// if authentication token is an app token, we need to use the GitHub API to list
if strings.HasPrefix(gitHubToken, GitHubAppInstallationAccessTokenPrefix) {
if strings.HasPrefix(gitToken, GitHubAppInstallationAccessTokenPrefix) {
// (NOTE: set user to x-access-token - this is required for github application tokens))
auth = &http.BasicAuth{
Username: "x-access-token",
Password: gitHubToken,
Password: gitToken,
}
} else if strings.HasPrefix(gitToken, GitLabPersonalAccessTokenPrefix) {
// for gitlab auth
auth = &http.BasicAuth{
Password: gitToken,
}
} else {
auth = &http.BasicAuth{
Username: gitHubToken,
Username: gitToken,
}
}
return auth
Expand Down
46 changes: 46 additions & 0 deletions modinstaller/git_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package modinstaller

import (
"testing"
)

func TestTransformToGitURL(t *testing.T) {
tests := []struct {
name string
input string
urlMode GitUrlMode
expected string
}{
// GitHub - SSH mode
{"GitHub SSH - Basic", "github.com/user/repo", GitUrlModeSSH, "[email protected]:user/repo.git"},
{"GitHub SSH - With Git Prefix", "[email protected]/user/repo", GitUrlModeSSH, "[email protected]:user/repo.git"},
{"GitHub SSH - With .git", "github.com/user/repo.git", GitUrlModeSSH, "[email protected]:user/repo.git"},

// GitHub - HTTPS mode
{"GitHub HTTPS - Basic", "github.com/user/repo", GitUrlModeHTTPS, "https://github.com/user/repo"},
{"GitHub HTTPS - Already HTTPS", "https://github.com/user/repo", GitUrlModeHTTPS, "https://github.com/user/repo"},

// GitLab - SSH mode
{"GitLab SSH - Basic", "gitlab.com/user/repo", GitUrlModeSSH, "[email protected]:user/repo.git"},
{"GitLab SSH - With Git Prefix", "[email protected]/user/repo", GitUrlModeSSH, "[email protected]:user/repo.git"},
{"GitLab SSH - With .git", "gitlab.com/user/repo.git", GitUrlModeSSH, "[email protected]:user/repo.git"},

// GitLab - HTTPS mode
{"GitLab HTTPS - Basic", "gitlab.com/user/repo", GitUrlModeHTTPS, "https://gitlab.com/user/repo"},
{"GitLab HTTPS - Already HTTPS", "https://gitlab.com/user/repo", GitUrlModeHTTPS, "https://gitlab.com/user/repo"},
{"GitLab HTTPS - with domain name", "example.gitlab.com/user/repo", GitUrlModeHTTPS, "https://example.gitlab.com/user/repo"},

// Edge cases
{"Unsupported Host", "other-host.com/user/repo", GitUrlModeSSH, "other-host.com/user/repo"},
{"Invalid Input - Empty", "", GitUrlModeSSH, ""},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := transformToGitURL(tt.input, tt.urlMode)
if got != tt.expected {
t.Errorf("transformToGitURL(%q, %q) = %q; want %q", tt.input, tt.urlMode, got, tt.expected)
}
})
}
}
1 change: 1 addition & 0 deletions modinstaller/github_access_tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ const (
GitHubAppUserAccessTokenPrefix = "ghu_"
GitHubAppInstallationAccessTokenPrefix = "ghs_"
GitHubAppRefreshTokenPrefix = "ghr_"
GitLabPersonalAccessTokenPrefix = "glpat-"
)

0 comments on commit 7077fa4

Please sign in to comment.