install.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. package install
  2. import (
  3. "ehang.io/nps/lib/common"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "github.com/c4milo/unpackit"
  8. "io"
  9. "io/ioutil"
  10. "log"
  11. "net/http"
  12. "os"
  13. "path/filepath"
  14. "runtime"
  15. "strings"
  16. )
  17. func UpdateNps() {
  18. destPath := downloadLatest("server")
  19. //复制文件到对应目录
  20. copyStaticFile(destPath, "nps")
  21. fmt.Println("Update completed, please restart")
  22. }
  23. func UpdateNpc() {
  24. destPath := downloadLatest("client")
  25. //复制文件到对应目录
  26. copyStaticFile(destPath, "npc")
  27. fmt.Println("Update completed, please restart")
  28. }
  29. type release struct {
  30. TagName string `json:"tag_name"`
  31. }
  32. func downloadLatest(bin string) string {
  33. // get version
  34. data, err := http.Get("https://api.github.com/repos/cnlh/nps/releases/latest")
  35. if err != nil {
  36. log.Fatal(err.Error())
  37. }
  38. b, err := ioutil.ReadAll(data.Body)
  39. if err != nil {
  40. log.Fatal(err)
  41. }
  42. rl := new(release)
  43. json.Unmarshal(b, &rl)
  44. version := rl.TagName
  45. fmt.Println("the latest version is", version)
  46. filename := runtime.GOOS + "_" + runtime.GOARCH + "_" + bin + ".tar.gz"
  47. // download latest package
  48. downloadUrl := fmt.Sprintf("https://ehang.io/nps/releases/download/%s/%s", version, filename)
  49. fmt.Println("download package from ", downloadUrl)
  50. resp, err := http.Get(downloadUrl)
  51. if err != nil {
  52. log.Fatal(err.Error())
  53. }
  54. destPath, err := unpackit.Unpack(resp.Body, "")
  55. if err != nil {
  56. log.Fatal(err)
  57. }
  58. if bin == "server" {
  59. destPath = strings.Replace(destPath, "/web", "", -1)
  60. destPath = strings.Replace(destPath, `\web`, "", -1)
  61. destPath = strings.Replace(destPath, "/views", "", -1)
  62. destPath = strings.Replace(destPath, `\views`, "", -1)
  63. } else {
  64. destPath = strings.Replace(destPath, `\conf`, "", -1)
  65. destPath = strings.Replace(destPath, "/conf", "", -1)
  66. }
  67. return destPath
  68. }
  69. func copyStaticFile(srcPath, bin string) string {
  70. path := common.GetInstallPath()
  71. if bin == "nps" {
  72. //复制文件到对应目录
  73. if err := CopyDir(filepath.Join(srcPath, "web", "views"), filepath.Join(path, "web", "views")); err != nil {
  74. log.Fatalln(err)
  75. }
  76. chMod(filepath.Join(path, "web", "views"), 0766)
  77. if err := CopyDir(filepath.Join(srcPath, "web", "static"), filepath.Join(path, "web", "static")); err != nil {
  78. log.Fatalln(err)
  79. }
  80. chMod(filepath.Join(path, "web", "static"), 0766)
  81. }
  82. binPath, _ := filepath.Abs(os.Args[0])
  83. if !common.IsWindows() {
  84. if _, err := copyFile(filepath.Join(srcPath, bin), "/usr/bin/"+bin); err != nil {
  85. if _, err := copyFile(filepath.Join(srcPath, bin), "/usr/local/bin/"+bin); err != nil {
  86. log.Fatalln(err)
  87. } else {
  88. copyFile(filepath.Join(srcPath, bin), "/usr/local/bin/"+bin+"-update")
  89. chMod("/usr/local/bin/"+bin+"-update", 0755)
  90. binPath = "/usr/local/bin/" + bin
  91. }
  92. } else {
  93. copyFile(filepath.Join(srcPath, bin), "/usr/bin/"+bin+"-update")
  94. chMod("/usr/bin/"+bin+"-update", 0755)
  95. binPath = "/usr/bin/" + bin
  96. }
  97. } else {
  98. copyFile(filepath.Join(srcPath, bin+".exe"), filepath.Join(common.GetAppPath(), bin+"-update.exe"))
  99. copyFile(filepath.Join(srcPath, bin+".exe"), filepath.Join(common.GetAppPath(), bin+".exe"))
  100. }
  101. chMod(binPath, 0755)
  102. return binPath
  103. }
  104. func InstallNpc() {
  105. path := common.GetInstallPath()
  106. if !common.FileExists(path) {
  107. err := os.Mkdir(path, 0755)
  108. if err != nil {
  109. log.Fatal(err)
  110. }
  111. }
  112. copyStaticFile(common.GetAppPath(), "npc")
  113. }
  114. func InstallNps() string {
  115. path := common.GetInstallPath()
  116. if common.FileExists(path) {
  117. MkidrDirAll(path, "web/static", "web/views")
  118. } else {
  119. MkidrDirAll(path, "conf", "web/static", "web/views")
  120. // not copy config if the config file is exist
  121. if err := CopyDir(filepath.Join(common.GetAppPath(), "conf"), filepath.Join(path, "conf")); err != nil {
  122. log.Fatalln(err)
  123. }
  124. chMod(filepath.Join(path, "conf"), 0766)
  125. }
  126. binPath := copyStaticFile(common.GetAppPath(), "nps")
  127. log.Println("install ok!")
  128. log.Println("Static files and configuration files in the current directory will be useless")
  129. log.Println("The new configuration file is located in", path, "you can edit them")
  130. if !common.IsWindows() {
  131. log.Println(`You can start with:
  132. nps start|stop|restart|uninstall|update or nps-update update
  133. anywhere!`)
  134. } else {
  135. log.Println(`You can copy executable files to any directory and start working with:
  136. nps.exe start|stop|restart|uninstall|update or nps-update.exe update
  137. now!`)
  138. }
  139. chMod(common.GetLogPath(), 0777)
  140. return binPath
  141. }
  142. func MkidrDirAll(path string, v ...string) {
  143. for _, item := range v {
  144. if err := os.MkdirAll(filepath.Join(path, item), 0755); err != nil {
  145. log.Fatalf("Failed to create directory %s error:%s", path, err.Error())
  146. }
  147. }
  148. }
  149. func CopyDir(srcPath string, destPath string) error {
  150. //检测目录正确性
  151. if srcInfo, err := os.Stat(srcPath); err != nil {
  152. fmt.Println(err.Error())
  153. return err
  154. } else {
  155. if !srcInfo.IsDir() {
  156. e := errors.New("SrcPath is not the right directory!")
  157. return e
  158. }
  159. }
  160. if destInfo, err := os.Stat(destPath); err != nil {
  161. return err
  162. } else {
  163. if !destInfo.IsDir() {
  164. e := errors.New("DestInfo is not the right directory!")
  165. return e
  166. }
  167. }
  168. err := filepath.Walk(srcPath, func(path string, f os.FileInfo, err error) error {
  169. if f == nil {
  170. return err
  171. }
  172. if !f.IsDir() {
  173. destNewPath := strings.Replace(path, srcPath, destPath, -1)
  174. log.Println("copy file ::" + path + " to " + destNewPath)
  175. copyFile(path, destNewPath)
  176. if !common.IsWindows() {
  177. chMod(destNewPath, 0766)
  178. }
  179. }
  180. return nil
  181. })
  182. return err
  183. }
  184. //生成目录并拷贝文件
  185. func copyFile(src, dest string) (w int64, err error) {
  186. srcFile, err := os.Open(src)
  187. if err != nil {
  188. return
  189. }
  190. defer srcFile.Close()
  191. //分割path目录
  192. destSplitPathDirs := strings.Split(dest, string(filepath.Separator))
  193. //检测时候存在目录
  194. destSplitPath := ""
  195. for index, dir := range destSplitPathDirs {
  196. if index < len(destSplitPathDirs)-1 {
  197. destSplitPath = destSplitPath + dir + string(filepath.Separator)
  198. b, _ := pathExists(destSplitPath)
  199. if b == false {
  200. log.Println("mkdir:" + destSplitPath)
  201. //创建目录
  202. err := os.Mkdir(destSplitPath, os.ModePerm)
  203. if err != nil {
  204. log.Fatalln(err)
  205. }
  206. }
  207. }
  208. }
  209. dstFile, err := os.Create(dest)
  210. if err != nil {
  211. return
  212. }
  213. defer dstFile.Close()
  214. return io.Copy(dstFile, srcFile)
  215. }
  216. //检测文件夹路径时候存在
  217. func pathExists(path string) (bool, error) {
  218. _, err := os.Stat(path)
  219. if err == nil {
  220. return true, nil
  221. }
  222. if os.IsNotExist(err) {
  223. return false, nil
  224. }
  225. return false, err
  226. }
  227. func chMod(name string, mode os.FileMode) {
  228. if !common.IsWindows() {
  229. os.Chmod(name, mode)
  230. }
  231. }