github.com/turingchain2020/turingchain@v1.1.21/cmd/tools/strategy/importpackage.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package strategy 6 7 import ( 8 "bytes" 9 "errors" 10 "fmt" 11 "io" 12 "io/ioutil" 13 "os" 14 "os/exec" 15 "strings" 16 17 "github.com/turingchain2020/turingchain/cmd/tools/util" 18 "github.com/BurntSushi/toml" 19 ) 20 21 const ( 22 dappFolderName = "dapp" 23 consensusFolderName = "consensus" 24 storeFolderName = "store" 25 cryptoFolderName = "crypto" 26 mempoolFolderName = "mempool" 27 ) 28 29 type pluginConfigItem struct { 30 Type string 31 Gitrepo string 32 Version string 33 } 34 35 type pluginItem struct { 36 name string 37 gitRepo string 38 version string 39 } 40 41 type importPackageStrategy struct { 42 strategyBasic 43 cfgFileName string 44 cfgItems map[string]*pluginConfigItem 45 projRootPath string 46 projPluginPath string 47 items map[string][]*pluginItem 48 } 49 50 func (im *importPackageStrategy) Run() error { 51 mlog.Info("Begin run turingchain import packages.") 52 defer mlog.Info("Run turingchain import packages finish.") 53 return im.runImpl() 54 } 55 56 func (im *importPackageStrategy) runImpl() error { 57 type STEP func() error 58 steps := []STEP{ 59 im.readConfig, 60 im.initData, 61 im.generateImportFile, 62 im.fetchPluginPackage, 63 } 64 65 for s, step := range steps { 66 err := step() 67 if err != nil { 68 fmt.Println("call", s+1, "step error", err) 69 return err 70 } 71 } 72 return nil 73 } 74 75 func (im *importPackageStrategy) readConfig() error { 76 mlog.Info("读取配置文件") 77 conf, _ := im.getParam("conf") 78 if conf == "" { 79 return nil 80 } 81 if conf != "" { 82 im.cfgFileName = conf 83 } 84 _, err := toml.DecodeFile(im.cfgFileName, &im.cfgItems) 85 return err 86 } 87 88 func (im *importPackageStrategy) initData() error { 89 mlog.Info("初始化数据") 90 im.items = make(map[string][]*pluginItem) 91 dappItems := make([]*pluginItem, 0) 92 consensusItems := make([]*pluginItem, 0) 93 storeItems := make([]*pluginItem, 0) 94 cryptoItems := make([]*pluginItem, 0) 95 mempoolItems := make([]*pluginItem, 0) 96 97 //read current plugin dir 98 //(分成两级,并且去掉了 init 目录) 99 path, _ := im.getParam("path") 100 dirlist, err := im.readPluginDir(path) 101 if err != nil { 102 return err 103 } 104 if im.cfgItems == nil { 105 im.cfgItems = make(map[string]*pluginConfigItem) 106 } 107 for name, value := range dirlist { 108 im.cfgItems[name] = value 109 } 110 out, _ := im.getParam("out") 111 //输出新的配置文件 112 if out != "" { 113 buf := new(bytes.Buffer) 114 err = toml.NewEncoder(buf).Encode(im.cfgItems) 115 if err != nil { 116 return err 117 } 118 err = ioutil.WriteFile(out, buf.Bytes(), 0666) 119 if err != nil { 120 return err 121 } 122 } 123 if len(im.cfgItems) == 0 { 124 return errors.New("empty config") 125 } 126 for name, cfgItem := range im.cfgItems { 127 splitdata := strings.Split(name, "-") 128 if len(splitdata) == 2 { 129 cfgItem.Type = splitdata[0] 130 name = splitdata[1] 131 } 132 item := &pluginItem{ 133 name: name, 134 gitRepo: cfgItem.Gitrepo, 135 version: cfgItem.Version, 136 } 137 switch cfgItem.Type { 138 case dappFolderName: 139 dappItems = append(dappItems, item) 140 case consensusFolderName: 141 consensusItems = append(consensusItems, item) 142 case storeFolderName: 143 storeItems = append(storeItems, item) 144 case cryptoFolderName: 145 cryptoItems = append(cryptoItems, item) 146 case mempoolFolderName: 147 mempoolItems = append(mempoolItems, item) 148 default: 149 fmt.Printf("type %s is not supported.\n", cfgItem.Type) 150 return errors.New("config error") 151 } 152 } 153 im.items[dappFolderName] = dappItems 154 im.items[consensusFolderName] = consensusItems 155 im.items[storeFolderName] = storeItems 156 im.items[cryptoFolderName] = cryptoItems 157 im.items[mempoolFolderName] = mempoolItems 158 im.projRootPath = "" 159 im.projPluginPath, _ = im.getParam("path") 160 return nil 161 } 162 163 func getDirList(path string) ([]string, error) { 164 dirlist, err := ioutil.ReadDir(path) 165 if err != nil { 166 return nil, err 167 } 168 dirs := make([]string, 0) 169 for _, f := range dirlist { 170 if f.IsDir() { 171 if f.Name() == "." || f.Name() == ".." || f.Name() == "init" || f.Name() == ".git" { 172 continue 173 } 174 dirs = append(dirs, f.Name()) 175 } 176 } 177 return dirs, nil 178 } 179 180 func (im *importPackageStrategy) readPluginDir(path string) (map[string]*pluginConfigItem, error) { 181 dirlist, err := getDirList(path) 182 if err != nil { 183 return nil, err 184 } 185 packname, _ := im.getParam("packname") 186 conf := make(map[string]*pluginConfigItem) 187 for _, ty := range dirlist { 188 names, err := getDirList(path + "/" + ty) 189 if err != nil { 190 return nil, err 191 } 192 for _, name := range names { 193 key := ty + "-" + name 194 item := &pluginConfigItem{ 195 Type: ty, 196 Gitrepo: packname + "/" + ty + "/" + name, 197 } 198 conf[key] = item 199 } 200 } 201 return conf, nil 202 } 203 204 func (im *importPackageStrategy) generateImportFile() error { 205 mlog.Info("生成引用文件") 206 importStrs := map[string]string{} 207 for name, plugins := range im.items { 208 for _, item := range plugins { 209 importStrs[name] += fmt.Sprintf("\n_ \"%s\" //auto gen", item.gitRepo) 210 } 211 } 212 for key, value := range importStrs { 213 content := fmt.Sprintf("package init\n\nimport(%s\n)", value) 214 initFile := fmt.Sprintf("%s/%s/init/init.go", im.projPluginPath, key) 215 util.MakeDir(initFile) 216 217 { // 写入到文件中 218 util.DeleteFile(initFile) 219 file, err := util.OpenFile(initFile) 220 if err != nil { 221 return err 222 } 223 defer file.Close() 224 _, err = io.WriteString(file, content) 225 if err != nil { 226 return err 227 } 228 } 229 // 格式化生成的文件 230 cmd := exec.Command("gofmt", "-l", "-s", "-w", initFile) 231 err := cmd.Run() 232 if err != nil { 233 return err 234 } 235 } 236 return nil 237 } 238 239 func (im *importPackageStrategy) fetchPlugin(gitrepo, version string) error { 240 var param string 241 if len(version) > 0 { 242 param = fmt.Sprintf("%s@%s", gitrepo, version) 243 } else { 244 param = gitrepo 245 } 246 cmd := exec.Command("govendor", "fetch", param) 247 cmd.Stdout = os.Stdout 248 cmd.Stderr = os.Stderr 249 return cmd.Run() 250 } 251 252 // fetchPluginPackage 使用govendor来下载依赖包 253 func (im *importPackageStrategy) fetchPluginPackage() error { 254 mlog.Info("下载插件源码包") 255 pwd := util.Pwd() 256 257 defer os.Chdir(pwd) 258 for _, plugins := range im.items { 259 for _, plugin := range plugins { 260 mlog.Info("同步插件", "repo", plugin.gitRepo, "version", plugin.version) 261 if plugin.version == "" { 262 //留给后面的 fetch +m 263 continue 264 } 265 err := im.fetchPlugin(plugin.gitRepo, plugin.version) 266 if err != nil { 267 mlog.Info("同步插件包出错", "repo", plugin.gitRepo, "error", err.Error()) 268 return err 269 } 270 } 271 } 272 return nil 273 }