From 249e90e00ccdd592f020facc6dd96d989456d9de Mon Sep 17 00:00:00 2001 From: Zoker Date: Sat, 11 Jul 2020 08:26:11 +0800 Subject: [PATCH] add create Gitee group feature --- platform/gitee.go | 77 +++++++++++++++++++++++++++++++++++++++-------- share/tools.go | 19 ++++++++++++ 2 files changed, 84 insertions(+), 12 deletions(-) diff --git a/platform/gitee.go b/platform/gitee.go index 7e7004b..fb9b9a5 100644 --- a/platform/gitee.go +++ b/platform/gitee.go @@ -14,6 +14,7 @@ import ( "github.com/gookit/gcli/v2/interact" "github.com/gookit/gcli/v2/progress" "gopkg.in/src-d/go-git.v4/plumbing/transport/http" + "github.com/bitly/go-simplejson" ) type RepoResult struct { @@ -55,9 +56,11 @@ func GiteeCommand() *gcli.Command { /other/path/to/git-bare-repo3 ... - Using Source: {$binName} {$cmd} github:zoker + Using Source: {$binName} {$cmd} github:zoker YOUR_TOKEN_HERE(OPTIONAL) Support import from Github source, replace {zoker} with your expected Github path + It better to provide your own access_token to avoid api rate limit, eg on Github: https://github.com/settings/tokens Alert: Only Github source and public project supported, other platform like Gitlab, Bitbucket will be added later + `} // bind args with names @@ -97,7 +100,7 @@ func syncGitee(c *gcli.Command, args []string) error { color.Green.Printf("\nHello, %s! \n\n", userInfo["name"]) // get available namespace todo: enterprise and group - allNamespace := getNamespace(userInfo) + allNamespace := getNamespace(userInfo, accessToken) namespace := make([]string, len(allNamespace)) for i, n := range allNamespace { namespace[i] = n[1] @@ -105,8 +108,17 @@ func syncGitee(c *gcli.Command, args []string) error { selectedNumber := askNamespace(namespace) numberD, _ := strconv.Atoi(selectedNumber) - // select namespace and ask for ensure - selectedNp := allNamespace[numberD] + var selectedNp []string + if numberD == 0 { + // create a new group + selectedNp = createGroup(accessToken) + if selectedNp == nil { + return nil + } + } else { + // select namespace and ask for ensure + selectedNp = allNamespace[numberD] + } color.Notice.Printf("\nSelected %s(https://gitee.com/%s) as namespace, Type: %s \n" + "The following projects will be generated on Gitee: \n\n", selectedNp[0], selectedNp[1], selectedNp[2]) @@ -159,7 +171,7 @@ func syncGitee(c *gcli.Command, args []string) error { color.Red.Println(err.Error()) return nil } - fmt.Printf("\nA tmp repo dir `%s` created for tmp repositories, you can remove it after sync successed\n", tmpDir) + fmt.Printf("\nA tmp repo dir `%s` created for tmp repositories, you can remove it after sync successed\n\n", tmpDir) fmt.Println("Cloning and Uploading Projects to Gitee, Please Wait...") } syncRes := multiSync(avaiRepo, auth, asExi, tmpDir) @@ -228,16 +240,57 @@ func filterResult(result map[string]interface{}, key string) (string, bool) { } // todo enable select group and enterprise -func getNamespace(userInfo map [string]string) [][]string { - namespace := make([][]string, 1) - namespace[0] = make([]string, 4) - namespace[0][0] = userInfo["name"] - namespace[0][1] = userInfo["username"] - namespace[0][2] = "Personal" - namespace[0][3] = "0" +func getNamespace(userInfo map [string]string, token string) [][]string { + var namespace [][]string + newOrg := []string{"Create a new Group", "Create a new Group", ""} + owner := []string{userInfo["name"], userInfo["username"], "Personal"} + namespace = append(namespace, newOrg, owner) + + orgUrl := fmt.Sprintf("https://gitee.com/api/v5/user/orgs?access_token=%s&per_page=100", token) + if result, _, err := share.GetByte(orgUrl); err == nil { + orgRes, _ := simplejson.NewJson([]byte(result)) + serOrg, _ := orgRes.Array() + for _, org := range serOrg { + orgA := org.(map[string]interface{}) + orgName := orgA["login"].(string) + namespace = append(namespace, []string{orgName, orgName, "Group"}) + } + } + return namespace } +func createGroup(token string) []string { + orgPath, _ := interact.ReadLine("\nPlease enter your new Group path(eg: zoker, zoker123, osc123): ") + if len(orgPath) == 0 { + color.Red.Println("Group path must be provided!") + } else { + orgUrl := "https://gitee.com/api/v5/users/organization" + params := fmt.Sprintf(`{ + "access_token": "%s", + "name": "%s", + "org": "%s" + }`, token, orgPath, orgPath) + var paramsJson map[string]interface{} + json.Unmarshal([]byte(params), ¶msJson) + + if result, _, err := share.PostFormByte(orgUrl, paramsJson); err == nil { + orgRes, _ := simplejson.NewJson([]byte(result)) + login, _ := orgRes.Get("login").String() + errorMsg, _ := orgRes.Get("message").String() + if login == orgPath { + color.Green.Printf("\nGroup https://gitee.com/%s has been successfully Created!\n", orgPath) + return []string{orgPath, orgPath, "Group"} + } else { + color.Red.Println(errorMsg) + } + } else { + color.Red.Println(err.Error()) + } + } + return nil +} + func askNamespace(namespace []string) string { np := interact.SelectOne( "Please select which namespace you want to put this repositories: ", diff --git a/share/tools.go b/share/tools.go index d3565e5..6e2762b 100644 --- a/share/tools.go +++ b/share/tools.go @@ -386,6 +386,25 @@ func PostForm(uri string, params map[string]interface{}) (map[string]interface{} return result, nil } +func PostFormByte(uri string, params map[string]interface{}) ([]byte, NetHttp.Header, error) { + data := "" + for k, v := range params { + data += fmt.Sprintf("%s=%s&%s", k, v.(string), data) + } + + response, err := NetHttp.Post(uri, "application/x-www-form-urlencoded", strings.NewReader(data)) + if err != nil { + color.Red.Printf("Request failed, Error: %s \n", err.Error()) + return nil, nil, err + } + defer response.Body.Close() + + body, _ := ioutil.ReadAll(response.Body) + header := response.Header + + return body, header, nil +} + func ShowProjectLists(host string, repos []string, path string) { for i, r := range repos { i = i + 1