commit d559356e570a22d54bc9f80273d05cef8fbb5118 Author: Paul Lecuq Date: Sat Jan 5 23:26:55 2019 +0100 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5307335 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +github_to_gogs +github_to_gogs.ini diff --git a/github_to_gogs.go b/github_to_gogs.go new file mode 100644 index 0000000..d1f4df2 --- /dev/null +++ b/github_to_gogs.go @@ -0,0 +1,212 @@ +package main + +import ( + "fmt" + "net/http" + "log" + "bytes" + "encoding/json" + "io/ioutil" + "gopkg.in/ini.v1" + "time" + "os" + "flag" +) + +var globalconfig GlobalConfig +var githubconfig GitHubConfig +var gogsconfig GogsConfig + +var client *http.Client +var resp *http.Response +var err error +var repo []Githubrepo +var repo_list []Githubrepo + +type Githubrepo struct { + Name string `json:"name"` + Clone_Url string `json:"clone_url"` +} + +type GogsMigrateRepo struct { + Name string + Clone_Url string + Uid int + Mirror bool +} + +type GlobalConfig struct { + RequestTimeout time.Duration + UserAgent string +} + +type GitHubConfig struct { + StarsPages string + MaxPagesNumber int + AuthUsername string + AuthPassword string + ContentType string +} + +type GogsConfig struct { + Uid int + Username string + RepoUrlTmpl string + MigrateUrl string + AuthToken string + ContentType string + Mirror bool +} + +func main() { + GetConfig() + GetReposFromGitHub() + MigrateReposToGogs(repo_list) +} + +func usage() { + fmt.Fprintf(os.Stderr, "usage: github_to_gogs [inputfile]\n") + flag.PrintDefaults() + os.Exit(2) +} + +func GetConfig() { + flag.Usage = usage + flag.Parse() + + var configfile string + + if len(os.Args) > 1 { + configfile = os.Args[1] + } else { + usage() + os.Exit(2) + } + HandleError(err) + + config, err := ini.Load(configfile) + HandleError(err) + + global_section := config.Section("global") + github_section := config.Section("github") + gogs_section := config.Section("gogs") + + globalconfig.UserAgent = global_section.Key("user_agent").String() + globalconfig.RequestTimeout, err = global_section.Key("request_timeout").Duration() + HandleError(err) + + githubconfig.StarsPages = github_section.Key("stars_pages").String() + githubconfig.MaxPagesNumber, err = github_section.Key("max_pages_number").Int() + HandleError(err) + + githubconfig.AuthUsername = github_section.Key("auth_username").String() + githubconfig.AuthPassword = github_section.Key("auth_password").String() + githubconfig.ContentType = github_section.Key("content_type").String() + + gogsconfig.Uid, err = gogs_section.Key("uid").Int() + HandleError(err) + + gogsconfig.Username = gogs_section.Key("username").String() + gogsconfig.RepoUrlTmpl = gogs_section.Key("repo_url_tmpl").String() + gogsconfig.MigrateUrl = gogs_section.Key("migrate_url").String() + gogsconfig.AuthToken = gogs_section.Key("auth_token").String() + gogsconfig.ContentType = gogs_section.Key("content_type").String() + gogsconfig.Mirror, err = gogs_section.Key("mirror").Bool() + HandleError(err) + +} + +func CheckGogsIsExistingRepo(repo Githubrepo) bool { + var isexists bool = false + + client = &http.Client{} + resp = &http.Response{} + + var gogs_repo_url string = fmt.Sprintf(gogsconfig.RepoUrlTmpl,gogsconfig.Username,repo.Name) + + req, err := http.NewRequest("GET", gogs_repo_url, nil) + req.Header.Set("Authorization", gogsconfig.AuthToken) + req.Header.Set("User-Agent", globalconfig.UserAgent) + + resp, err = client.Do(req) + HandleError(err) + + if resp.StatusCode == 200 { + isexists = true + } else { + isexists = false + } + + return isexists +} + +func MigrateReposToGogs(repo_list []Githubrepo) { + fmt.Println("Migrate repos to Gogs...") + + client = &http.Client{} + resp = &http.Response{} + + for _,elem := range(repo_list) { + if !CheckGogsIsExistingRepo(elem) { + jsondata := fmt.Sprintf(`{"uid" : %d, "repo_name" : "%s" , "mirror" : %v, "clone_addr" : "%s"}`, gogsconfig.Uid, elem.Name, true, elem.Clone_Url) + fmt.Println(fmt.Sprintf("OK : Send migrating instruction for %s to gogs webservice",elem.Name)) + + req, err := http.NewRequest("POST", gogsconfig.MigrateUrl, bytes.NewBufferString(jsondata)) + HandleError(err) + + req.Header.Add("Content-Type", gogsconfig.ContentType) + req.Header.Set("User-Agent", globalconfig.UserAgent) + req.Header.Set("Authorization", gogsconfig.AuthToken) + + client.Timeout=globalconfig.RequestTimeout + + resp, err = client.Do(req) + HandleError(err) + } else { + fmt.Println(fmt.Sprintf("KO : Not migrating, %s exists ",elem.Name)) + } + } +} + +func GetReposFromGitHub() { + for num := 1; num <= githubconfig.MaxPagesNumber; num++ { + url := fmt.Sprintf(githubconfig.StarsPages, githubconfig.AuthUsername, num) + + InvokeGitHub(url) + + err = json.Unmarshal(*GetResponseBody(resp), &repo) + HandleError(err) + + for _,elem := range repo { + repo_list = append(repo_list, elem) + } + } + fmt.Println("Repositories from Github fetched !") +} + +func InvokeGitHub(url string) { + client = &http.Client{} + resp = &http.Response{} + + req, err := http.NewRequest("GET", url, nil) + HandleError(err) + + req.Header.Add("Content-Type", githubconfig.ContentType) + req.Header.Set("User-Agent", globalconfig.UserAgent) + req.SetBasicAuth(githubconfig.AuthUsername,githubconfig.AuthPassword) + + resp, err = client.Do(req) + HandleError(err) +} + +func GetResponseBody(resp *http.Response) *[]byte { + bodyBytes, err := ioutil.ReadAll(resp.Body) + HandleError(err) + return &bodyBytes +} + +func HandleError(err error) { + if err != nil { + log.Fatal(err) + } +} diff --git a/github_to_gogs.ini.sample b/github_to_gogs.ini.sample new file mode 100644 index 0000000..cdfc03b --- /dev/null +++ b/github_to_gogs.ini.sample @@ -0,0 +1,20 @@ +[global] +request_timeout=1200s +user_agent="Golang" + +[github] +stars_pages="https://api.github.com/users/%s/starred?page=%d" +max_pages_number=8 +auth_username="user" +auth_password="pass" +content_type="application/x-www-form-urlencoded" + +[gogs] +uid=1 +username="user" +repo_url_tmpl="https://gogs.example.com/api/v1/repos/%s/%s" +migrate_url="https://gogs.example.com/api/v1/repos/migrate" +auth_token="token xxxx" +content_type="application/json" +mirror=true +