mirror of
https://github.com/RGBCube/github2forgejo
synced 2026-01-13 00:31:02 +00:00
105 lines
3.6 KiB
Text
Executable file
105 lines
3.6 KiB
Text
Executable file
#!/usr/bin/env nu
|
|
|
|
def str-or [default: closure] {
|
|
if $in == null or $in == "<NONE>" {
|
|
do $default
|
|
} else {
|
|
$in
|
|
}
|
|
}
|
|
|
|
# Migrates a GitHub users repositories to a Gitea or Forgejo instance.
|
|
def main [
|
|
--github-user: string = "<NONE>" # The user to migrate from.
|
|
--github-token: string = "<NONE>" # An access token for fetching private repositories. Optional.
|
|
--gitea-url: string = "<NONE>" # The URL to the Gitea or Forgejo instance
|
|
--gitea-user: string = "<NONE>" # The user to migrate the repositories to.
|
|
--gitea-token: string = "<NONE>" # An access token for the user to actually insert repositories to.
|
|
--strategy: string = "<NONE>" # The strategy. Valid options are "Mirrored" or "Cloned" (case sensitive).
|
|
...repo_urls: string # The GitHub repo URLs to migrate to Gitea or Forgejo. If not given, all will be fetched.
|
|
] {
|
|
let github_user = $github_user | str-or { input $"(ansi red)GitHub username: (ansi reset)" }
|
|
let github_token = $github_token | str-or { input $"(ansi red)GitHub access token (ansi yellow)\((ansi blue)optional, only used for private repositories(ansi yellow))(ansi red): (ansi reset)" }
|
|
|
|
let gitea_url = $gitea_url | str-or { input $"(ansi green)Gitea instance URL: (ansi reset)" }
|
|
let gitea_url = if ($gitea_url | str ends-with "/") {
|
|
$gitea_url | str trim --left --char "/"
|
|
} else {
|
|
$gitea_url
|
|
}
|
|
|
|
let gitea_user = $gitea_user | str-or { input $"(ansi green)Gitea username or organization to migrate to: (ansi reset)" }
|
|
let gitea_token = $gitea_token | str-or { input $"(ansi green)Gitea access token: (ansi reset)" }
|
|
|
|
let gitea_uid = (
|
|
http get $"($gitea_url)/api/v1/users/($gitea_user)"
|
|
-H [ Authorization $"token ($gitea_token)" ]
|
|
) | get --ignore-errors id
|
|
|
|
if $gitea_uid == null {
|
|
echo "Invalid Gitea username or password"
|
|
exit 1
|
|
}
|
|
|
|
let strategy = $strategy | str-or { [ Mirrored Cloned ] | input list $"(ansi cyan)Should the repos be mirrored, or just cloned once? (ansi reset)" }
|
|
|
|
let repo_urls = if ($repo_urls | length) != 0 {
|
|
$repo_urls
|
|
} else {
|
|
if $github_token != "" {
|
|
(
|
|
http get $"https://api.github.com/users/($github_user)/repos?per_page=100"
|
|
-H [ Authorization $"token ($github_token)" ]
|
|
)
|
|
| get html_url
|
|
} else {
|
|
http get $"https://api.github.com/users/($github_user)/repos?per_page=100"
|
|
| get html_url
|
|
}
|
|
}
|
|
|
|
$repo_urls | each {|url|
|
|
let repo_name = $url | split row "/" | last
|
|
|
|
let repo_is_private = if $github_token == "" {
|
|
false
|
|
} else {
|
|
(
|
|
http get ("https://api.github.com/repos/" + $github_user + "/" + $repo_name)
|
|
-H [ Authorization $"token ($github_token)" ]
|
|
).private
|
|
}
|
|
|
|
let url = if not $repo_is_private {
|
|
$url
|
|
} else {
|
|
$"https://($github_token)@github.com/($github_user)/($repo_name)"
|
|
}
|
|
|
|
print --no-newline $"(ansi blue)($strategy | str replace "ed" "ing") ([public private] | get ($repo_is_private | into int)) repository to ($gitea_url)/($gitea_user)/($repo_name)..."
|
|
|
|
let response = (
|
|
http post $"($gitea_url)/api/v1/repos/migrate"
|
|
-t application/json
|
|
-H [
|
|
Authorization $"token ($gitea_token)"
|
|
]
|
|
{
|
|
clone_addr: $url
|
|
mirror: ($strategy == "Mirrored")
|
|
private: $repo_is_private
|
|
uid: $gitea_uid
|
|
|
|
repo_owner: $gitea_user
|
|
repo_name: $repo_name
|
|
}
|
|
)
|
|
|
|
echo $" (ansi green)Success!"
|
|
|
|
# echo ($response | to json)
|
|
|
|
# TODO: Handle ratelimits, 409's and access failures. Also print a
|
|
# nice message and options on what to do next on error.
|
|
}
|
|
}
|