From 8683db2f51956fd99d1ba62c150ef25866e8ff47 Mon Sep 17 00:00:00 2001 From: Nicolas MASSE Date: Thu, 14 May 2020 12:55:50 +0200 Subject: [PATCH] first commit --- LICENSE | 21 ++++ README.md | 37 +++++++ go.mod | 11 ++ go.sum | 303 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.go | 256 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 628 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3153fe0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Nicolas MASSE + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7aced0d --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# GitHub Repository mirroring for Gitea + +## Context + +Gitea is a nice alternative to GitHub, easy to setup. +When using it as a mirror from GitHub, you might want all repositories created in GitHub to appear automatically in Gitea. + +## Compilation + +```sh +go build -o mirror-github +``` + +## Pre-requisites + +* Generate a [GitHub Personal Access Token](https://github.com/settings/tokens) +* Generate a Gitea Access Token from `https://GITEA_SERVER/user/settings/applications` + +## Usage + +```sh +cat > mirror-github.yaml <= len(gh) { // No more GitHub repos to process... + if gti >= len(gt) { // and no more Gitea repos to process ! + break + } + + // On Gitea but not anymore on GitHub. We could remove the repo from gitea + // but to be safe, keep it there. + log.Printf("Gitea Repository %s is missing from GitHub, leaving it there...\n", gt[gti].Name) + gti = gti + 1 + continue + } + if gti >= len(gt) { // No more Gitea repos to process + toMigrate = append(toMigrate, gh[ghi:len(gh)]...) + break + } + + if *gh[ghi].Name == gt[gti].Name { + ghi = ghi + 1 + gti = gti + 1 + } else if *gh[ghi].Name < gt[gti].Name { + // On GitHub but not yet on Gitea. Migrate it. + toMigrate = append(toMigrate, gh[ghi]) + ghi = ghi + 1 + } else { + // On Gitea but not anymore on GitHub. We could remove the repo from gitea + // but to be safe, keep it there. + log.Printf("Gitea Repository %s is missing from GitHub, leaving it there...\n", gt[gti].Name) + gti = gti + 1 + } + } + + return toMigrate +} + +func migrate(ghRepo *github.Repository, gtClient *gitea.Client, gtUser *gitea.User) { + migrationOptions := gitea.MigrateRepoOption{ + CloneAddr: *ghRepo.CloneURL, + AuthUsername: *ghRepo.Owner.Login, + AuthPassword: viper.GetString("GitHub.PersonalToken"), + UID: int(gtUser.ID), + RepoName: *ghRepo.Name, + Mirror: true, + Private: *ghRepo.Private, + Description: *ghRepo.Description, + } + _, err := gtClient.MigrateRepo(migrationOptions) + if err != nil { + log.Fatal(fmt.Sprintf("MigrateRepo: %s: %s", ghRepo.Name, err)) + } +} + +func main() { + initConfig() + initLogFile() + + // List Gitea repositories + gtClient, gtUserInfo := initGiteaClient() + log.Printf("Connected to Gitea as %s.\n", gtUserInfo.UserName) + gtRepos := listGiteaRepositories(gtClient) + log.Printf("Found %d Gitea repositories\n", len(gtRepos)) + + // List GitHub repositories + ghClient, ghUserInfo := initGitHubClient() + log.Printf("Connected to GitHub as %s.\n", *ghUserInfo.Login) + ghRepos := listGitHubRepositories(ghClient) + log.Printf("Found %d GitHub repositories.\n", len(ghRepos)) + ghRepos = filterGitHubRepositories(ghRepos, *ghUserInfo.Login) + log.Printf("There are %d repositories left after filtering.\n", len(ghRepos)) + + // Sort all lists by repository name so that computeRepositoriesToMigrate + // can perform a diff + sort.Sort(gtRepos) + sort.Sort(ghRepos) + toMigrate := computeRepositoriesToMigrate(ghRepos, gtRepos) + log.Printf("There are %d repositories to migrate from GitHub to Gitea.\n", len(toMigrate)) + + // Migrate each repository + for _, repo := range toMigrate { + fmt.Printf("Migrating %s...\n", *repo.Name) + migrate(repo, gtClient, gtUserInfo) + } +}