util.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. package util
  2. import (
  3. "crypto/rand"
  4. "crypto/rsa"
  5. "crypto/x509"
  6. "encoding/pem"
  7. "errors"
  8. "fmt"
  9. "io"
  10. fs "io/ioutil"
  11. "net"
  12. "net/url"
  13. "os"
  14. "path/filepath"
  15. "regexp"
  16. "github.com/chzyer/readline"
  17. homedir "github.com/mitchellh/go-homedir"
  18. "golang.org/x/crypto/ssh"
  19. )
  20. func Keygen(publicPath, privatePath string, bits int) error {
  21. privateKey, err := rsa.GenerateKey(rand.Reader, bits)
  22. if err != nil {
  23. return err
  24. }
  25. // generate and write private key as PEM
  26. privateFile, err := os.OpenFile(privatePath, os.O_RDWR|os.O_CREATE, 0600)
  27. if err != nil {
  28. return err
  29. }
  30. defer privateFile.Close()
  31. privatePEM := &pem.Block{
  32. Type: "RSA PRIVATE KEY",
  33. Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
  34. }
  35. if err := pem.Encode(privateFile, privatePEM); err != nil {
  36. return err
  37. }
  38. // generate and write public key
  39. publicKey, err := ssh.NewPublicKey(&privateKey.PublicKey)
  40. if err != nil {
  41. return err
  42. }
  43. return fs.WriteFile(publicPath, ssh.MarshalAuthorizedKey(publicKey), 0600)
  44. }
  45. func JoinHostPort(host, port string) string {
  46. if port != "" {
  47. return fmt.Sprintf("%s:%s", host, port)
  48. }
  49. return host
  50. }
  51. func SplitHostPort(host string) (string, string) {
  52. h, p, err := net.SplitHostPort(host)
  53. if err != nil {
  54. return host, ""
  55. }
  56. return h, p
  57. }
  58. var ScpRe = regexp.MustCompile(`^([a-zA-Z0-9_]+)@([a-zA-Z0-9._-]+):(.*)$`)
  59. var Schemes = []string{"git", "https", "http", "git+ssh", "ssh"}
  60. func ParseURL(repo string) (*url.URL, error) {
  61. var err error
  62. var repoURL *url.URL
  63. if m := ScpRe.FindStringSubmatch(repo); m != nil {
  64. repoURL = &url.URL{
  65. Scheme: "ssh",
  66. User: url.User(m[1]),
  67. Host: m[2],
  68. Path: m[3],
  69. }
  70. } else {
  71. repoURL, err = url.Parse(repo)
  72. if err != nil {
  73. return nil, err
  74. }
  75. }
  76. for _, scheme := range Schemes {
  77. if repoURL.Scheme == scheme {
  78. return repoURL, nil
  79. }
  80. }
  81. return nil, errors.New(repoURL.Scheme + " is not supported")
  82. }
  83. type PromptConfig struct {
  84. Prompt string
  85. Default string
  86. Silent bool
  87. }
  88. func (c *PromptConfig) String() string {
  89. if c.Default != "" {
  90. return fmt.Sprintf("%s(%s) ", c.Prompt, c.Default)
  91. }
  92. return c.Prompt
  93. }
  94. func CheckError(err error) {
  95. if err == nil {
  96. return
  97. }
  98. fmt.Printf("\x1b[31;1m%s\x1b[0m\n", fmt.Sprintf("Error: %s", err))
  99. os.Exit(1)
  100. }
  101. func Prompt(cfg *PromptConfig) string {
  102. r, err := readline.NewEx(&readline.Config{
  103. Prompt: cfg.String(),
  104. EnableMask: cfg.Silent,
  105. MaskRune: 42,
  106. })
  107. CheckError(err)
  108. defer r.Close()
  109. for {
  110. line, err := r.Readline()
  111. CheckError(err)
  112. if line != "" {
  113. return line
  114. }
  115. if cfg.Default != "" {
  116. return cfg.Default
  117. }
  118. }
  119. }
  120. func IsExist(path string) bool {
  121. p, err := homedir.Expand(path)
  122. if err != nil {
  123. return false
  124. }
  125. if _, err := os.Stat(p); os.IsNotExist(err) {
  126. return false
  127. }
  128. return true
  129. }
  130. func Mkdir(paths ...string) (string, error) {
  131. p, err := homedir.Expand(filepath.Join(paths...))
  132. if err != nil {
  133. return "", err
  134. }
  135. if err := os.MkdirAll(p, 0755); err != nil {
  136. return "", err
  137. }
  138. return p, nil
  139. }
  140. func JoinPath(paths ...string) (string, error) {
  141. p, err := homedir.Expand(filepath.Join(paths...))
  142. if err != nil {
  143. return "", err
  144. }
  145. return p, nil
  146. }
  147. func Copy(src, dst string) error {
  148. in, err := os.Open(src)
  149. if err != nil {
  150. return err
  151. }
  152. defer in.Close()
  153. out, err := os.Create(dst)
  154. if err != nil {
  155. return err
  156. }
  157. defer out.Close()
  158. _, err = io.Copy(out, in)
  159. if err != nil {
  160. return err
  161. }
  162. return out.Close()
  163. }
  164. func SysSSHConfig() (string, error) {
  165. keypairs := []string{"~/.ssh/id_rsa", "~/.ssh/id_ed25519"}
  166. for _, k := range keypairs {
  167. if IsExist(k) && IsExist(k+".pub") {
  168. return homedir.Expand(k)
  169. }
  170. }
  171. return "", errors.New("System ssh config not found")
  172. }