2019-06-09 14:44:07 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
2019-07-09 16:42:04 +02:00
|
|
|
"errors"
|
2019-06-09 14:44:07 +02:00
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
|
|
|
|
"gopkg.in/ini.v1"
|
|
|
|
)
|
|
|
|
|
|
|
|
// GetConfig fetch configuration
|
2019-07-09 16:42:04 +02:00
|
|
|
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)
|
2019-07-09 16:42:04 +02:00
|
|
|
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()
|
2019-07-09 16:42:04 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-06-09 14:44:07 +02:00
|
|
|
|
|
|
|
githubconfig.StarsPages = githubsection.Key("stars_pages").String()
|
|
|
|
githubconfig.MaxPagesNumber, err = githubsection.Key("max_pages_number").Int()
|
2019-07-09 16:42:04 +02:00
|
|
|
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.UID = -1
|
|
|
|
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()
|
2019-07-09 16:42:04 +02:00
|
|
|
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}
|
2019-07-09 16:42:04 +02:00
|
|
|
|
|
|
|
return nil
|
2019-06-09 14:44:07 +02:00
|
|
|
}
|
|
|
|
|
2019-07-07 12:47:28 +02:00
|
|
|
// GetReposFromGitHub get starred repositories from github
|
2019-07-09 16:42:04 +02:00
|
|
|
func GetReposFromGitHub(config *Config) ([]GitHubRepo, error) {
|
2019-07-07 12:47:28 +02:00
|
|
|
var repolist []GitHubRepo
|
|
|
|
var repo []GitHubRepo
|
|
|
|
|
|
|
|
for num := 1; num <= config.githubconfig.MaxPagesNumber; num++ {
|
|
|
|
url := fmt.Sprintf(config.githubconfig.StarsPages, config.githubconfig.AuthUsername, num)
|
|
|
|
|
2019-07-09 16:42:04 +02:00
|
|
|
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
|
|
|
|
2019-07-09 16:42:04 +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-09 16:42:04 +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 ...
|
2019-07-09 16:42:04 +02:00
|
|
|
func InvokeGitHub(config *Config, url string) (*http.Response, error) {
|
2019-07-07 12:47:28 +02:00
|
|
|
req, err := http.NewRequest("GET", url, nil)
|
2019-07-09 16:42:04 +02:00
|
|
|
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)
|
2019-07-09 16:42:04 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-07-07 12:47:28 +02:00
|
|
|
|
2019-07-09 16:42:04 +02:00
|
|
|
return resp, nil
|
2019-07-07 12:47:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetResponseBody converts http responses bodies as bytes slice
|
2019-07-09 16:42:04 +02:00
|
|
|
func GetResponseBody(resp *http.Response) (*[]byte, error) {
|
2019-07-07 12:47:28 +02:00
|
|
|
bodyBytes, err := ioutil.ReadAll(resp.Body)
|
2019-07-09 16:42:04 +02:00
|
|
|
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
|
2019-07-09 16:42:04 +02:00
|
|
|
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)
|
2019-07-09 16:42:04 +02:00
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
2019-06-09 14:44:07 +02:00
|
|
|
|
|
|
|
if resp.StatusCode == 200 {
|
2019-07-09 16:42:04 +02:00
|
|
|
isexists = true
|
|
|
|
} else if resp.StatusCode == 404 {
|
|
|
|
isexists = false
|
2019-06-09 14:44:07 +02:00
|
|
|
} else {
|
2019-07-09 16:42:04 +02:00
|
|
|
err = errors.New(fmt.Sprintf("Can't determine error, cancelling, error %d in gogs webservice", resp.StatusCode))
|
|
|
|
return false, err
|
2019-06-09 14:44:07 +02:00
|
|
|
}
|
|
|
|
|
2019-07-09 16:42:04 +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
|
2019-07-09 16:42:04 +02:00
|
|
|
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)
|
2019-07-09 16:42:04 +02:00
|
|
|
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)
|
2019-07-09 16:42:04 +02:00
|
|
|
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
|
|
|
|
2019-07-09 16:42:04 +02:00
|
|
|
respbody, err := GetResponseBody(resp)
|
|
|
|
|
|
|
|
err = json.Unmarshal(*respbody, &gogsorg)
|
|
|
|
if err != nil {
|
|
|
|
err = errors.New("Failed to parse user ID from gogs webservice, check auth if possible")
|
|
|
|
return err
|
|
|
|
}
|
2019-06-09 14:44:07 +02:00
|
|
|
|
2019-07-07 12:47:28 +02:00
|
|
|
config.gogsconfig.UID = gogsorg.ID
|
2019-07-09 16:42:04 +02:00
|
|
|
|
|
|
|
return nil
|
2019-06-09 14:44:07 +02:00
|
|
|
}
|
|
|
|
|
2019-07-07 12:47:28 +02:00
|
|
|
// MigrateReposToGogs migrates input repositories to gogs
|
2019-07-09 16:42:04 +02:00
|
|
|
func MigrateReposToGogs(config *Config, repolist []GitHubRepo) error {
|
2019-06-09 14:44:07 +02:00
|
|
|
fmt.Println("Migrate repos to Gogs...")
|
|
|
|
|
2019-07-07 12:47:28 +02:00
|
|
|
client := &http.Client{}
|
2019-06-09 14:44:07 +02:00
|
|
|
|
|
|
|
for _, elem := range repolist {
|
2019-07-09 16:42:04 +02:00
|
|
|
existingrepo, err := CheckGogsExistingRepo(config, elem)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if !existingrepo {
|
2019-07-07 12:47:28 +02:00
|
|
|
jsondata := fmt.Sprintf(`{"uid" : %d, "repo_name" : "%s" , "mirror" : %v, "clone_addr" : "%s"}`, config.gogsconfig.UID, elem.Name, true, elem.CloneURL)
|
2019-06-09 14:44:07 +02:00
|
|
|
|
2019-07-07 12:47:28 +02:00
|
|
|
req, err := http.NewRequest("POST", config.gogsconfig.MigrateURL, bytes.NewBufferString(jsondata))
|
2019-07-09 16:42:04 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-06-09 14:44:07 +02:00
|
|
|
|
2019-07-07 12:47:28 +02:00
|
|
|
req.Header.Add("Content-Type", config.gogsconfig.ContentType)
|
|
|
|
req.Header.Set("User-Agent", config.globalconfig.UserAgent)
|
|
|
|
req.Header.Set("Authorization", config.gogsconfig.AuthToken)
|
2019-06-09 14:44:07 +02:00
|
|
|
|
2019-07-07 12:47:28 +02:00
|
|
|
client.Timeout = config.globalconfig.RequestTimeout
|
2019-06-09 14:44:07 +02:00
|
|
|
|
2019-07-09 16:42:04 +02:00
|
|
|
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", elem.Name, resp.StatusCode))
|
|
|
|
if resp.StatusCode != 201 {
|
|
|
|
err = errors.New(fmt.Sprintf("Error when migrating repo %s to gogs, status code %d", elem.Name, resp.StatusCode))
|
|
|
|
log.Println(err)
|
|
|
|
}
|
|
|
|
|
2019-07-07 12:47:28 +02:00
|
|
|
} else {
|
|
|
|
fmt.Println(fmt.Sprintf("Not migrating, %s exists in gogs", elem.Name))
|
2019-06-09 14:44:07 +02:00
|
|
|
}
|
|
|
|
}
|
2019-07-09 16:42:04 +02:00
|
|
|
return nil
|
2019-06-09 14:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Usage displays possible arguments
|
|
|
|
func Usage() {
|
|
|
|
flag.PrintDefaults()
|
|
|
|
os.Exit(1)
|
|
|
|
}
|