GiteaMigrator/main.go

246 lines
7.9 KiB
Go
Raw Normal View History

2023-10-14 17:19:12 +00:00
package main
import (
"context"
"errors"
"fmt"
"os"
"github.com/cqroot/prompt"
"github.com/cqroot/prompt/input"
"github.com/cqroot/prompt/multichoose"
"github.com/google/go-github/github"
)
func CheckErr(err error) {
if err != nil {
if errors.Is(err, prompt.ErrUserQuit) {
fmt.Fprintln(os.Stderr, "Error:", err)
os.Exit(1)
} else {
panic(err)
}
}
}
// authenticateGithub authenticates the user with Github using their username
// and password.
// A Github client is returned.
func authenticateGithub(username string, password string, otp string) *github.Client {
ctx := context.Background()
ts := github.BasicAuthTransport{
Username: username,
Password: password,
OTP: otp,
}
client := github.NewClient(ts.Client())
_, _, err := client.Users.Get(ctx, "")
if err != nil {
fmt.Println("Error", err)
}
return client
}
// getGithubUsername prompts the user for their Github username.
// The username is returned as a string.
func getGithubUsername() string {
result, err := prompt.New().Ask("Github username").Input("johndoe69")
CheckErr(err)
return result
}
// getGithubPassword prompts the user for their Github password.
// The password is returned as a string.
func getGithubPassword() string {
result, err := prompt.New().Ask("Github password or token").
Input("", input.WithEchoMode(input.EchoPassword))
CheckErr(err)
return result
}
// getGithubOTP prompts the user for their Github OTP.
// The OTP is returned as a string.
func getGithubOTP() string {
result, err := prompt.New().Ask("Github OTP (if you used a token, leave blank)").
Input("", input.WithEchoMode(input.EchoPassword))
CheckErr(err)
return result
}
// getGiteaUsername prompts the user for their Gitea username.
// The username is returned as a string.
func getGiteaUsername() string {
result, err := prompt.New().Ask("Gitea username").Input("johndoe69")
CheckErr(err)
return result
}
// getGiteaToken prompts the user for their Gitea application token.
// The token is returned as a string.
func getGiteaToken() string {
result, err := prompt.New().Ask("Gitea application token").
Input("", input.WithEchoMode(input.EchoPassword))
CheckErr(err)
return result
}
// getRepos first prompts users to choose how they want to select repositories.
// They will have the option of fetching a list from github and selecting from that,
// entering a list of repositories manually, providing a path to a file containing
// a list of repositories, or selecting filters which will be used to fetch a list
// of repositories from github.
// Once the user has selected how they want to select repositories, they will be
// prompted to select repositories based on their chosen method.
// The selected repositories are returned as a list of strings.
func getRepos(client *github.Client) []string {
result, err := prompt.New().Ask("How do you want to select repositories?").
Choose([]string{"Fetch from Github", "Enter manually", "File path", "Filters"})
CheckErr(err)
switch result {
case "Fetch from Github":
return getReposFromGithub(client)
// case "Enter manually":
// return getReposManually()
// case "File path":
// return getReposFromFile()
// case "Filters":
// return getReposFromFilters(client)
}
return nil
}
// fetchReposForUser fetches a list of all repositories from github for the given user
// or organization. Github by default only returns 30 repositories at a time, so this
// function will make multiple requests to github to fetch all repositories.
// The list of repositories is returned as a list of strings.
func fetchReposForUser(client *github.Client, user string, organization bool) []string {
var repos []string
var page int = 1
var per_page int = 30
for {
var repo_list []*github.Repository
var err error
if organization {
repo_list, _, err = client.Repositories.ListByOrg(context.Background(), user, &github.RepositoryListByOrgOptions{
ListOptions: github.ListOptions{
Page: page,
PerPage: per_page,
},
})
} else {
repo_list, _, err = client.Repositories.List(context.Background(), user, &github.RepositoryListOptions{
ListOptions: github.ListOptions{
Page: page,
PerPage: per_page,
},
})
}
if err != nil {
fmt.Println("Error", err)
}
if len(repo_list) == 0 {
break
}
for _, repo := range repo_list {
repos = append(repos, fmt.Sprintf("%s/%s", user, repo.GetName()))
}
page++
}
return repos
}
// getReposFromGithub first asks the user for the name of the organization,
// or user, whose repositories they want to migrate.
// It then fetches a list of repositories from github, and prompts the user
// to select which repositories they want to migrate.
// The selected repositories are returned as a list of strings.
func getReposFromGithub(client *github.Client) []string {
result, err := prompt.New().Ask("Select repositories from:").
Choose([]string{"Organization", "User"})
CheckErr(err)
var repo_names []string
switch result {
case "Organization":
result, err := prompt.New().Ask("Organization name").Input("acme")
CheckErr(err)
repos := fetchReposForUser(client, result, true)
repo_names = append(repo_names, repos...)
case "User":
result, err := prompt.New().Ask("User name").Input("johndoe69")
CheckErr(err)
repos := fetchReposForUser(client, result, false)
repo_names = append(repo_names, repos...)
}
selected, err := prompt.New().Ask("Select repositories:").
MultiChoose(repo_names, multichoose.WithTheme(ThemeScroll))
CheckErr(err)
return selected
}
// Github to Gitea migration tool.
// This tool will migrate selected repositories from Github to Gitea,
// based on user input. This process is entirely interactive.
// The tool will ask for the following:
// - Github username
// - Github password/token
// - Gitea username
// - Gitea application token
// - Repositories to migrate, or filters to select repositories to migrate
// - Whether repos should be mirrored, or migrated as a one-time copy
// - Whether to migrate issues, use the github issue tracker, or neither
// - How to set visibility of the migrated repos
// - Whether to migrate wiki pages, labels, pull requests, milestones, and releases
func main() {
fmt.Println("Welcome to the Github to Gitea migration tool!")
// githubUsername := getGithubUsername()
// githubPassword := getGithubPassword()
// githubOTP := getGithubOTP()
githubClient := authenticateGithub("watzon", "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", "")
// giteaUsername := getGiteaUsername()
// giteaToken := getGiteaToken()
// giteaClient = authenticateGitea(giteaUsername, giteaToken)
repos := getRepos(githubClient)
fmt.Println(repos)
// should_mirror := getMirror()
// should_migrate_issues, use_github_issue_tracker := getIssues()
// repos_by_visibility := getVisibility(repos)
// should_migrate_wiki := getWiki()
// should_migrate_labels := getLabels()
// should_migrate_pull_requests := getPullRequests()
// should_migrate_milestones := getMilestones()
// should_migrate_releases := getReleases()
// res, err = execute_migration(&MigrationOptions{
// githubUsername: githubUsername,
// githubPassword: githubPassword,
// giteaUsername: giteaUsername,
// giteaToken: giteaToken,
// repos: repos,
// should_mirror: should_mirror,
// should_migrate_issues: should_migrate_issues,
// use_github_issue_tracker: use_github_issue_tracker,
// repos_by_visibility: repos_by_visibility,
// should_migrate_wiki: should_migrate_wiki,
// should_migrate_labels: should_migrate_labels,
// should_migrate_pull_requests: should_migrate_pull_requests,
// should_migrate_milestones: should_migrate_milestones,
// should_migrate_releases: should_migrate_releases,
// })
// if err != nil {
// fmt.Println("Error", err)
// } else {
// fmt.Println("Migration completed successfully!")
// }
}