mirror of
https://github.com/RGBCube/GitHub2Forgejo
synced 2025-07-27 05:07:45 +00:00
No more Gitea, only Forgejo
This commit is contained in:
parent
fd315bdff5
commit
9523361143
2 changed files with 44 additions and 34 deletions
|
@ -1,4 +1,4 @@
|
||||||
# GitHub to Gitea/Forgejo Migration Script
|
# GitHub to Forgejo Migration Script
|
||||||
|
|
||||||
Plain simple, just install [Nushell](https://nushell.sh) and run the script:
|
Plain simple, just install [Nushell](https://nushell.sh) and run the script:
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ for a uninteractive run, or run the script like so:
|
||||||
|
|
||||||
And get a nice interactive experience.
|
And get a nice interactive experience.
|
||||||
|
|
||||||
This works on any Gitea or Forgejo instance.
|
This works on any Forgejo instance.
|
||||||
|
|
||||||
## FAQ
|
## FAQ
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ This works on any Gitea or Forgejo instance.
|
||||||
|
|
||||||
### Can I migrate specific repositories?
|
### Can I migrate specific repositories?
|
||||||
|
|
||||||
Nope. Just use the Gitea/Forgejo web UI for that.
|
Nope. Just use the Forgejo web UI for that.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|
72
migrate.nu
72
migrate.nu
|
@ -1,33 +1,43 @@
|
||||||
#!/usr/bin/env nu
|
#!/usr/bin/env nu
|
||||||
|
|
||||||
def or-default [default: closure] {
|
def or-default [default: closure] {
|
||||||
if ($in | is-empty) {
|
if ($in == null) {
|
||||||
do $default
|
do $default
|
||||||
} else {
|
} else {
|
||||||
$in
|
$in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Migrates a GitHub users repositories to a Gitea or Forgejo instance.
|
# Migrates a GitHub users repositories to a Forgejo instance.
|
||||||
#
|
#
|
||||||
# Here is the accepted environment variables, if one isn't set, it will
|
# Accepted environment variables:
|
||||||
# be prompted for:
|
|
||||||
#
|
#
|
||||||
# GITHUB_USER: The user to migrate from.
|
# GITHUB_USER: The user to fetch the repositories from.
|
||||||
# GITHUB_TOKEN: An access token for fetching private repositories. Optional.
|
# GITHUB_TOKEN: An access token for fetching private repositories. Optional.
|
||||||
# GITEA_URL: The URL to the Gitea or Forgejo instance
|
#
|
||||||
# GITEA_USER: The user to migrate the repositories to.
|
# FORGEJO_URL: The URL to the Forgejo instance. Must include the protocol (https://).
|
||||||
# GITEA_TOKEN: An access token for the user to actually insert repositories to.
|
# FORGEJO_USER: The user to migrate the repositories to.
|
||||||
# STRATEGY: The strategy. Valid options are "mirrored" or "cloned" (case insensitive).
|
# FORGEJO_TOKEN: An access token for the specified user.
|
||||||
# FORCE_SYNC: Whether to delete a mirrored repo from Gitea or Forgejo if the source on GitHub doesn't exist anymore. Must be either "true" or "false".
|
#
|
||||||
|
# STRATEGY:
|
||||||
|
# The strategy. Valid options are "mirrored" or "cloned" (case insensitive).
|
||||||
|
# "mirrored" will mirror the repository and tell the Forgejo instance to
|
||||||
|
# periodically update it, "cloned" will only clone once. "cloned" is
|
||||||
|
# useful if you are never going to use GitHub again.
|
||||||
|
#
|
||||||
|
# FORCE_SYNC:
|
||||||
|
# Whether to delete a mirrored repo from the Forgejo instance if the
|
||||||
|
# source on GitHub doesn't exist anymore. Must be either "true" or "false".
|
||||||
|
#
|
||||||
|
# To leave an environment variable unspecified, set it to an empty string.
|
||||||
def main [] {
|
def main [] {
|
||||||
let github_user = $env | get -i GITHUB_USER | or-default { input $"(ansi red)GitHub username: (ansi reset)" }
|
let github_user = $env | get -i GITHUB_USER | or-default { input $"(ansi red)GitHub username: (ansi reset)" }
|
||||||
let github_token = $env | get -i GITHUB_TOKEN | or-default { input $"(ansi red)GitHub access token (ansi yellow)\((ansi blue)optional, only used for private repositories(ansi yellow))(ansi red): (ansi reset)" }
|
let github_token = $env | get -i GITHUB_TOKEN | or-default { 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 = $env | get -i GITEA_URL | or-default { input $"(ansi green)Gitea instance URL \(with https://): (ansi reset)" } | str trim --right --char "/"
|
let forgejo_url = $env | get -i FORGEJO_URL | or-default { input $"(ansi green)Forgejo instance URL \(with https://): (ansi reset)" } | str trim --right --char "/"
|
||||||
let gitea_user = $env | get -i GITEA_USER | or-default { input $"(ansi green)Gitea username or organization to migrate to: (ansi reset)" }
|
let forgejo_user = $env | get -i FORGEJO_USER | or-default { input $"(ansi green)Forgejo username or organization to migrate to: (ansi reset)" }
|
||||||
let gitea_token = $env | get -i GITEA_TOKEN | or-default { input $"(ansi green)Gitea access token: (ansi reset)" }
|
let forgejo_token = $env | get -i FORGEJO_TOKEN | or-default { input $"(ansi green)Forgejo access token: (ansi reset)" }
|
||||||
let strategy = $env | get -i STRATEGY | or-default { [ Mirrored Cloned ] | input list $"(ansi cyan)Should the repos be mirrored, or just cloned once?(ansi reset)" } | str downcase
|
let strategy = $env | get -i STRATEGY | or-default { [ Mirrored Cloned ] | input list $"(ansi cyan)Should the repos be mirrored, or just cloned once?(ansi reset)" } | str downcase
|
||||||
let force_sync = $env | get -i FORCE_SYNC | or-default { [ "Yup, delete them" Nope ] | input list $"(ansi yellow)Should mirrored repos that don't have a GitHub source anymore be deleted?(ansi reset)" } | $in != "Nope"
|
let force_sync = $env | get -i FORCE_SYNC | or-default { [ "Yup, delete them" Nope ] | input list $"(ansi yellow)Should mirrored repos that don't have a GitHub source anymore be deleted?(ansi reset)" } | $in != "Nope"
|
||||||
|
|
||||||
let github_repos = do {
|
let github_repos = do {
|
||||||
def get-repos-at [page_nr: number] {
|
def get-repos-at [page_nr: number] {
|
||||||
|
@ -60,32 +70,32 @@ def main [] {
|
||||||
if $force_sync {
|
if $force_sync {
|
||||||
let github_repo_names = ($github_repos | get name)
|
let github_repo_names = ($github_repos | get name)
|
||||||
|
|
||||||
let gitea_mirrored_repos = (
|
let forgejo_mirrored_repos = (
|
||||||
http get $"($gitea_url)/api/v1/user/repos"
|
http get $"($forgejo_url)/api/v1/user/repos"
|
||||||
-H [ Authorization $"token ($gitea_token)" ]
|
-H [ Authorization $"token ($forgejo_token)" ]
|
||||||
| filter { get mirror }
|
| filter { get mirror }
|
||||||
| filter { ($github_token != "") and not $in.private }
|
| filter { ($github_token != "") and not $in.private }
|
||||||
)
|
)
|
||||||
|
|
||||||
let gitea_not_on_github = ($gitea_mirrored_repos | filter { not ($in.name in $github_repo_names) })
|
let forgejo_not_on_github = ($forgejo_mirrored_repos | filter { not ($in.name in $github_repo_names) })
|
||||||
|
|
||||||
$gitea_not_on_github | each {|gitea_repo|
|
$forgejo_not_on_github | each {|forgejo_repo|
|
||||||
print --no-newline $"(ansi red)Deleting ($gitea_url)/($gitea_repo.full_name) because the mirror source doesn't exist on GitHub anymore...(ansi reset)"
|
print --no-newline $"(ansi red)Deleting ($forgejo_url)/($forgejo_repo.full_name) because the mirror source doesn't exist on GitHub anymore...(ansi reset)"
|
||||||
|
|
||||||
(http delete $"($gitea_url)/api/v1/repos/($gitea_repo.full_name)"
|
(http delete $"($forgejo_url)/api/v1/repos/($forgejo_repo.full_name)"
|
||||||
-H [ Authorization $"token ($gitea_token)" ])
|
-H [ Authorization $"token ($forgejo_token)" ])
|
||||||
|
|
||||||
print $" (ansi green_bold)Success!(ansi reset)"
|
print $" (ansi green_bold)Success!(ansi reset)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Mirror repos that do exist on GitHub to Gitea.
|
# Mirror repos that do exist on GitHub to Forgejo.
|
||||||
$github_repos | each {|github_repo|
|
$github_repos | each {|github_repo|
|
||||||
print --no-newline $"(ansi blue)(
|
print --no-newline $"(ansi blue)(
|
||||||
$strategy | str capitalize | str replace "ed" "ing"
|
$strategy | str capitalize | str replace "ed" "ing"
|
||||||
) (
|
) (
|
||||||
[ $"(ansi green)public(ansi blue)(char space)" $"(ansi red)private(ansi blue)" ] | get ($github_repo.private | into int)
|
[ $"(ansi green)public(ansi blue)(char space)" $"(ansi red)private(ansi blue)" ] | get ($github_repo.private | into int)
|
||||||
) repository (ansi purple)($github_repo.html_url)(ansi blue) to (ansi white_bold)($gitea_url)/($gitea_user)/($github_repo.name)(ansi blue)...(ansi reset)"
|
) repository (ansi purple)($github_repo.html_url)(ansi blue) to (ansi white_bold)($forgejo_url)/($forgejo_user)/($github_repo.name)(ansi blue)...(ansi reset)"
|
||||||
|
|
||||||
let github_repo_url = if not $github_repo.private {
|
let github_repo_url = if not $github_repo.private {
|
||||||
$github_repo.html_url
|
$github_repo.html_url
|
||||||
|
@ -94,16 +104,16 @@ def main [] {
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = (
|
let response = (
|
||||||
http post $"($gitea_url)/api/v1/repos/migrate"
|
http post $"($forgejo_url)/api/v1/repos/migrate"
|
||||||
--allow-errors
|
--allow-errors
|
||||||
-t application/json
|
-t application/json
|
||||||
-H [ Authorization $"token ($gitea_token)" ]
|
-H [ Authorization $"token ($forgejo_token)" ]
|
||||||
{
|
{
|
||||||
clone_addr: $github_repo_url
|
clone_addr: $github_repo_url
|
||||||
mirror: ($strategy != "cloned")
|
mirror: ($strategy != "cloned")
|
||||||
private: $github_repo.private
|
private: $github_repo.private
|
||||||
|
|
||||||
repo_owner: $gitea_user
|
repo_owner: $forgejo_user
|
||||||
repo_name: $github_repo.name
|
repo_name: $github_repo.name
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue