g2g/functions.go

282 lines
7.3 KiB
Go
Raw Normal View History

2019-06-09 14:44:07 +02:00
package main
import (
"bytes"
"encoding/json"
"errors"
2019-06-09 14:44:07 +02:00
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
2019-07-10 15:07:41 +02:00
"sync"
2019-06-09 14:44:07 +02:00
"gopkg.in/ini.v1"
)
// GetConfig fetch configuration
func GetConfig(config *Config) error {
2019-07-07 12:47:28 +02:00
var configfile string
var globalconfig GlobalConfig
var githubconfig GitHubConfig
var gogsconfig GogsConfig
2019-06-09 14:44:07 +02:00
flag.Usage = Usage
2019-07-07 12:47:28 +02:00
flag.StringVar(&configfile, "configfile", "github-to-gogs.ini", "config file to use with github-to-gogs section")
2019-06-09 14:44:07 +02:00
flag.Parse()
cfg, err := ini.Load(configfile)
if err != nil {
return err
}
2019-06-09 14:44:07 +02:00
globalsection := cfg.Section("global")
githubsection := cfg.Section("github")
gogssection := cfg.Section("gogs")
globalconfig.UserAgent = globalsection.Key("user_agent").String()
globalconfig.RequestTimeout, err = globalsection.Key("request_timeout").Duration()
if err != nil {
return err
}
2019-07-10 15:07:41 +02:00
globalconfig.Threads, err = globalsection.Key("threads").Int()
if err != nil {
return err
}
2019-06-09 14:44:07 +02:00
githubconfig.StarsPages = githubsection.Key("stars_pages").String()
2019-07-10 15:07:41 +02:00
githubconfig.PageNum, err = githubsection.Key("page_num").Int()
if err != nil {
return err
}
githubconfig.MaxPerPage, err = githubsection.Key("max_per_page").Int()
if err != nil {
return err
}
2019-06-09 14:44:07 +02:00
githubconfig.AuthUsername = githubsection.Key("auth_username").String()
githubconfig.AuthPassword = githubsection.Key("auth_password").String()
githubconfig.ContentType = githubsection.Key("content_type").String()
gogsconfig.Username = gogssection.Key("username").String()
gogsconfig.DestUsername = gogssection.Key("dest_username").String()
gogsconfig.RepoURLTmpl = gogssection.Key("repo_url_tmpl").String()
gogsconfig.OrgsURLTmpl = gogssection.Key("orgs_url_tmpl").String()
gogsconfig.MigrateURL = gogssection.Key("migrate_url").String()
gogsconfig.AuthToken = gogssection.Key("auth_token").String()
gogsconfig.ContentType = gogssection.Key("content_type").String()
gogsconfig.Mirror, err = gogssection.Key("mirror").Bool()
if err != nil {
return err
}
2019-06-09 14:44:07 +02:00
2019-07-07 12:47:28 +02:00
*config = Config{globalconfig: globalconfig,
githubconfig: githubconfig,
gogsconfig: gogsconfig}
return nil
2019-06-09 14:44:07 +02:00
}
2019-07-07 12:47:28 +02:00
// GetReposFromGitHub get starred repositories from github
func GetReposFromGitHub(config *Config) ([]GitHubRepo, error) {
2019-07-07 12:47:28 +02:00
var repolist []GitHubRepo
var repo []GitHubRepo
2019-07-10 15:07:41 +02:00
for num := 1; num <= config.githubconfig.PageNum; num++ {
url := fmt.Sprintf(config.githubconfig.StarsPages, config.githubconfig.AuthUsername, config.githubconfig.MaxPerPage, num)
fmt.Println(url)
2019-07-07 12:47:28 +02:00
2019-07-10 15:07:41 +02:00
fmt.Println("Getting GitHub starred repos")
resp, err := InvokeGitHub(config, url)
if err != nil {
return nil, err
}
respbody, err := GetResponseBody(resp)
if err != nil {
return nil, err
}
2019-07-07 12:47:28 +02:00
err = json.Unmarshal(*respbody, &repo)
if err != nil {
return nil, err
}
2019-07-07 12:47:28 +02:00
for _, elem := range repo {
repolist = append(repolist, elem)
}
}
2019-07-10 15:07:41 +02:00
fmt.Println(fmt.Sprintf("%d repositories from Github fetched", len(repolist)))
return repolist, nil
2019-07-07 12:47:28 +02:00
}
2019-06-09 14:44:07 +02:00
2019-07-07 12:47:28 +02:00
// InvokeGitHub ...
func InvokeGitHub(config *Config, url string) (*http.Response, error) {
2019-07-07 12:47:28 +02:00
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
2019-06-09 14:44:07 +02:00
2019-07-07 12:47:28 +02:00
req.Header.Add("Content-Type", config.githubconfig.ContentType)
req.Header.Set("User-Agent", config.globalconfig.UserAgent)
req.SetBasicAuth(config.githubconfig.AuthUsername, config.githubconfig.AuthPassword)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
2019-07-07 12:47:28 +02:00
return resp, nil
2019-07-07 12:47:28 +02:00
}
// GetResponseBody converts http responses bodies as bytes slice
func GetResponseBody(resp *http.Response) (*[]byte, error) {
2019-07-07 12:47:28 +02:00
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return &bodyBytes, nil
2019-07-07 12:47:28 +02:00
}
// CheckGogsExistingRepo checks if there's an existing repository in gogs
func CheckGogsExistingRepo(config *Config, repo GitHubRepo) (bool, error) {
var isexists bool
2019-07-07 12:47:28 +02:00
gogsrepourl := fmt.Sprintf(config.gogsconfig.RepoURLTmpl, config.gogsconfig.DestUsername, repo.Name)
2019-06-09 14:44:07 +02:00
req, err := http.NewRequest("GET", gogsrepourl, nil)
2019-07-07 12:47:28 +02:00
req.Header.Set("Authorization", config.gogsconfig.AuthToken)
req.Header.Set("User-Agent", config.globalconfig.UserAgent)
2019-06-09 14:44:07 +02:00
2019-07-07 12:47:28 +02:00
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return false, err
}
2019-06-09 14:44:07 +02:00
if resp.StatusCode == 200 {
isexists = true
} else if resp.StatusCode == 404 {
isexists = false
2019-06-09 14:44:07 +02:00
} else {
2019-07-10 15:07:41 +02:00
err = fmt.Errorf("Can't determine error, cancelling, error %d in gogs webservice", resp.StatusCode)
return false, err
2019-06-09 14:44:07 +02:00
}
return isexists, nil
2019-06-09 14:44:07 +02:00
}
2019-07-07 12:47:28 +02:00
// GetGogsUserUID get the logued user identifier
func GetGogsUserUID(config *Config) error {
2019-06-09 14:44:07 +02:00
var gogsorg GogsOrg
gogsrepourl := fmt.Sprintf(config.gogsconfig.OrgsURLTmpl, config.gogsconfig.DestUsername)
req, err := http.NewRequest("GET", gogsrepourl, nil)
if err != nil {
return err
}
2019-06-09 14:44:07 +02:00
req.Header.Set("Authorization", config.gogsconfig.AuthToken)
req.Header.Set("User-Agent", config.globalconfig.UserAgent)
2019-07-07 12:47:28 +02:00
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
if resp.StatusCode != 200 {
err = errors.New("Error invoking gogs webservice")
return err
}
2019-06-09 14:44:07 +02:00
respbody, err := GetResponseBody(resp)
err = json.Unmarshal(*respbody, &gogsorg)
if err != nil {
2019-07-10 15:07:41 +02:00
err = errors.New("Failed to parse user ID from gogs webservice, check auth")
return err
}
2019-06-09 14:44:07 +02:00
2019-07-07 12:47:28 +02:00
config.gogsconfig.UID = gogsorg.ID
return nil
2019-06-09 14:44:07 +02:00
}
2019-07-10 15:07:41 +02:00
// RunMigration run threads for migration
func RunMigration(config *Config, repolist []GitHubRepo) {
jobs := make(chan GitHubRepo)
done := make(chan bool)
2019-06-09 14:44:07 +02:00
2019-07-10 15:07:41 +02:00
var wg sync.WaitGroup
for thr := range make([]int, config.globalconfig.Threads) {
go MigrateReposToGogs(config, &wg, jobs, done, thr)
}
2019-06-09 14:44:07 +02:00
2019-07-10 15:07:41 +02:00
for _, repo := range repolist {
jobs <- repo
}
close(jobs)
<-done
wg.Wait()
}
2019-06-09 14:44:07 +02:00
2019-07-10 15:07:41 +02:00
// MigrateReposToGogs migrates input repositories to gogs
func MigrateReposToGogs(config *Config, wg *sync.WaitGroup, jobs chan GitHubRepo, done chan bool, thr int) error {
wg.Add(1)
for {
elem, more := <-jobs
if more {
client := &http.Client{}
var resp *http.Response
existingrepo, err := CheckGogsExistingRepo(config, elem)
if err != nil {
return err
}
2019-07-10 15:07:41 +02:00
if !existingrepo {
jsondata := fmt.Sprintf(`{"uid" : %d, "repo_name" : "%s" , "mirror" : %v, "clone_addr" : "%s"}`, config.gogsconfig.UID, elem.Name, true, elem.CloneURL)
req, err := http.NewRequest("POST", config.gogsconfig.MigrateURL, bytes.NewBufferString(jsondata))
if err != nil {
return err
}
req.Header.Add("Content-Type", config.gogsconfig.ContentType)
req.Header.Set("User-Agent", config.globalconfig.UserAgent)
req.Header.Set("Authorization", config.gogsconfig.AuthToken)
client.Timeout = config.globalconfig.RequestTimeout
fmt.Println(fmt.Sprintf("Migrating repo %s to gogs rest api", elem.Name))
resp, err = client.Do(req)
if err != nil {
return err
}
fmt.Println(fmt.Sprintf("Repo %s migrated with status code %d on gogs webservice", elem.Name, resp.StatusCode))
if resp.StatusCode != 201 {
err = fmt.Errorf("Error when migrating repo %s to gogs with status code %d on gogs webservice", elem.Name, resp.StatusCode)
log.Println(err)
}
} else {
fmt.Println(fmt.Sprintf("Not migrating, %s exists in gogs", elem.Name))
}
2019-07-07 12:47:28 +02:00
} else {
2019-07-10 15:07:41 +02:00
fmt.Println(fmt.Sprintf("All repo migrated on thread num %d", thr))
wg.Done()
done <- true
return nil
2019-06-09 14:44:07 +02:00
}
}
}
// Usage displays possible arguments
func Usage() {
flag.PrintDefaults()
os.Exit(1)
}