/commands/clone.go

https://gitlab.com/jslee1301/hub · Go · 135 lines · 116 code · 19 blank · 0 comment · 26 complexity · 45828e04c89f5f1c535b1ad13256e1c5 MD5 · raw file

  1. package commands
  2. import (
  3. "fmt"
  4. "regexp"
  5. "strings"
  6. "github.com/github/hub/github"
  7. "github.com/github/hub/utils"
  8. )
  9. var cmdClone = &Command{
  10. Run: clone,
  11. GitExtension: true,
  12. Usage: "clone [-p] [<OPTIONS>] [<USER>/]<REPOSITORY> [<DESTINATION>]",
  13. Long: `Clone a repository from GitHub.
  14. ## Options:
  15. -p
  16. (Deprecated) Clone private repositories over SSH.
  17. [<USER>/]<REPOSITORY>
  18. <USER> defaults to your own GitHub username.
  19. <DESTINATION>
  20. Directory name to clone into (default: <REPOSITORY>).
  21. ## Examples:
  22. $ hub clone rtomayko/ronn
  23. > git clone git://github.com/rtomayko/ronn.git
  24. ## See also:
  25. hub-fork(1), hub(1), git-clone(1)
  26. `,
  27. }
  28. func init() {
  29. CmdRunner.Use(cmdClone)
  30. }
  31. func clone(command *Command, args *Args) {
  32. if !args.IsParamsEmpty() {
  33. transformCloneArgs(args)
  34. }
  35. }
  36. func transformCloneArgs(args *Args) {
  37. isSSH := parseClonePrivateFlag(args)
  38. hasValueRegxp := regexp.MustCompile("^(--(upload-pack|template|depth|origin|branch|reference|name)|-[ubo])$")
  39. nameWithOwnerRegexp := regexp.MustCompile(NameWithOwnerRe)
  40. for i := 0; i < args.ParamsSize(); i++ {
  41. a := args.Params[i]
  42. if strings.HasPrefix(a, "-") {
  43. if hasValueRegxp.MatchString(a) {
  44. i++
  45. }
  46. } else {
  47. if nameWithOwnerRegexp.MatchString(a) && !isCloneable(a) {
  48. name, owner := parseCloneNameAndOwner(a)
  49. var host *github.Host
  50. if owner == "" {
  51. config := github.CurrentConfig()
  52. h, err := config.DefaultHost()
  53. if err != nil {
  54. utils.Check(github.FormatError("cloning repository", err))
  55. }
  56. host = h
  57. owner = host.User
  58. }
  59. var hostStr string
  60. if host != nil {
  61. hostStr = host.Host
  62. }
  63. expectWiki := strings.HasSuffix(name, ".wiki")
  64. if expectWiki {
  65. name = strings.TrimSuffix(name, ".wiki")
  66. }
  67. project := github.NewProject(owner, name, hostStr)
  68. gh := github.NewClient(project.Host)
  69. repo, err := gh.Repository(project)
  70. if err != nil {
  71. if strings.Contains(err.Error(), "HTTP 404") {
  72. err = fmt.Errorf("Error: repository %s/%s doesn't exist", project.Owner, project.Name)
  73. }
  74. utils.Check(err)
  75. }
  76. if expectWiki {
  77. if !repo.HasWiki {
  78. utils.Check(fmt.Errorf("Error: %s/%s doesn't have a wiki", project.Owner, project.Name))
  79. } else {
  80. name = name + ".wiki"
  81. }
  82. }
  83. if !isSSH &&
  84. args.Command != "submodule" &&
  85. !github.IsHttpsProtocol() {
  86. isSSH = repo.Private || repo.Permissions.Push
  87. }
  88. url := project.GitURL(name, owner, isSSH)
  89. args.ReplaceParam(i, url)
  90. }
  91. break
  92. }
  93. }
  94. }
  95. func parseClonePrivateFlag(args *Args) bool {
  96. if i := args.IndexOfParam("-p"); i != -1 {
  97. args.RemoveParam(i)
  98. return true
  99. }
  100. return false
  101. }
  102. func parseCloneNameAndOwner(arg string) (name, owner string) {
  103. name, owner = arg, ""
  104. if strings.Contains(arg, "/") {
  105. split := strings.SplitN(arg, "/", 2)
  106. name = split[1]
  107. owner = split[0]
  108. }
  109. return
  110. }