github.com/goravel/framework@v1.13.9/foundation/console/vendor_publish_command.go (about) 1 package console 2 3 import ( 4 "errors" 5 "go/build" 6 "os" 7 "path/filepath" 8 "strings" 9 10 "github.com/gookit/color" 11 12 "github.com/goravel/framework/contracts/console" 13 "github.com/goravel/framework/contracts/console/command" 14 "github.com/goravel/framework/support/file" 15 ) 16 17 type VendorPublishCommand struct { 18 publishes map[string]map[string]string 19 publishGroups map[string]map[string]string 20 } 21 22 func NewVendorPublishCommand(publishes, publishGroups map[string]map[string]string) *VendorPublishCommand { 23 return &VendorPublishCommand{ 24 publishes: publishes, 25 publishGroups: publishGroups, 26 } 27 } 28 29 // Signature The name and signature of the console command. 30 func (receiver *VendorPublishCommand) Signature() string { 31 return "vendor:publish" 32 } 33 34 // Description The console command description. 35 func (receiver *VendorPublishCommand) Description() string { 36 return "Publish any publishable assets from vendor packages" 37 } 38 39 // Extend The console command extend. 40 func (receiver *VendorPublishCommand) Extend() command.Extend { 41 return command.Extend{ 42 Category: "vendor", 43 Flags: []command.Flag{ 44 &command.BoolFlag{ 45 Name: "existing", 46 Aliases: []string{"e"}, 47 Usage: "Publish and overwrite only the files that have already been published", 48 }, 49 &command.BoolFlag{ 50 Name: "force", 51 Aliases: []string{"f"}, 52 Usage: "Overwrite any existing files", 53 }, 54 &command.StringFlag{ 55 Name: "package", 56 Aliases: []string{"p"}, 57 Usage: "Package name to publish", 58 }, 59 &command.StringFlag{ 60 Name: "tag", 61 Aliases: []string{"t"}, 62 Usage: "One tag that have assets you want to publish", 63 }, 64 }, 65 } 66 } 67 68 // Handle Execute the console command. 69 func (receiver *VendorPublishCommand) Handle(ctx console.Context) error { 70 packageName := ctx.Option("package") 71 paths := receiver.pathsForPackageOrGroup(packageName, ctx.Option("tag")) 72 if len(paths) == 0 { 73 return errors.New("no vendor found") 74 } 75 76 packageDir, err := receiver.packageDir(packageName) 77 if err != nil { 78 return err 79 } 80 81 for sourcePath, targetValue := range paths { 82 targetValue = strings.TrimPrefix(strings.TrimPrefix(targetValue, "/"), "./") 83 packagePath := filepath.Join(packageDir, sourcePath) 84 85 res, err := receiver.publish(packagePath, targetValue, ctx.OptionBool("existing"), ctx.OptionBool("force")) 86 if err != nil { 87 return err 88 } 89 90 if len(res) > 0 { 91 for sourceFile, targetFile := range res { 92 color.Greenp("Copied Directory ") 93 color.Yellowf("[%s]", sourceFile) 94 color.Greenp(" To ") 95 color.Yellowf("%s\n", targetFile) 96 } 97 } 98 } 99 100 color.Greenln("Publishing complete") 101 102 return nil 103 } 104 105 func (receiver *VendorPublishCommand) pathsForPackageOrGroup(packageName, group string) map[string]string { 106 if packageName != "" && group != "" { 107 return receiver.pathsForProviderAndGroup(packageName, group) 108 } else if group != "" { 109 if paths, exist := receiver.publishGroups[group]; exist { 110 return paths 111 } 112 } else if packageName != "" { 113 if paths, exist := receiver.publishes[packageName]; exist { 114 return paths 115 } 116 } 117 118 return nil 119 } 120 121 func (receiver *VendorPublishCommand) pathsForProviderAndGroup(packageName, group string) map[string]string { 122 packagePaths, exist := receiver.publishes[packageName] 123 if !exist { 124 return nil 125 } 126 127 groupPaths, exist := receiver.publishGroups[group] 128 if !exist { 129 return nil 130 } 131 132 paths := make(map[string]string) 133 for key, path := range packagePaths { 134 if _, exist := groupPaths[key]; exist { 135 paths[key] = path 136 } 137 } 138 139 return paths 140 } 141 142 func (receiver *VendorPublishCommand) packageDir(packageName string) (string, error) { 143 var srcDir string 144 if build.IsLocalImport(packageName) { 145 srcDir = "./" 146 } 147 148 pkg, err := build.Import(packageName, srcDir, build.FindOnly) 149 if err != nil { 150 return "", err 151 } 152 153 return pkg.Dir, nil 154 } 155 156 func (receiver *VendorPublishCommand) publish(sourcePath, targetPath string, existing, force bool) (map[string]string, error) { 157 result := make(map[string]string) 158 isTargetPathDir := filepath.Ext(targetPath) == "" 159 isSourcePathDir := filepath.Ext(sourcePath) == "" 160 161 sourceFiles, err := receiver.getSourceFiles(sourcePath) 162 if err != nil { 163 return nil, err 164 } 165 166 for _, sourceFile := range sourceFiles { 167 relativePath := "" 168 if isSourcePathDir { 169 relativePath, err = filepath.Rel(sourcePath, sourceFile) 170 if err != nil { 171 return nil, err 172 } 173 } else { 174 relativePath = filepath.Base(sourcePath) 175 } 176 177 targetFile := targetPath 178 if isTargetPathDir { 179 targetFile = filepath.Join(targetPath, relativePath) 180 } 181 182 success, err := receiver.publishFile(sourceFile, targetFile, existing, force) 183 if err != nil { 184 return nil, err 185 } 186 if success { 187 result[sourceFile] = targetFile 188 } 189 } 190 191 return result, nil 192 } 193 194 func (receiver *VendorPublishCommand) getSourceFiles(sourcePath string) ([]string, error) { 195 sourcePathStat, err := os.Stat(sourcePath) 196 if err != nil { 197 return nil, err 198 } 199 200 if sourcePathStat.IsDir() { 201 return receiver.getSourceFilesForDir(sourcePath) 202 } else { 203 return []string{sourcePath}, nil 204 } 205 } 206 207 func (receiver *VendorPublishCommand) getSourceFilesForDir(sourcePath string) ([]string, error) { 208 dirEntries, err := os.ReadDir(sourcePath) 209 if err != nil { 210 return nil, err 211 } 212 213 var sourceFiles []string 214 for _, dirEntry := range dirEntries { 215 if dirEntry.IsDir() { 216 sourcePaths, err := receiver.getSourceFilesForDir(filepath.Join(sourcePath, dirEntry.Name())) 217 if err != nil { 218 return nil, err 219 } 220 sourceFiles = append(sourceFiles, sourcePaths...) 221 } else { 222 sourceFiles = append(sourceFiles, filepath.Join(sourcePath, dirEntry.Name())) 223 } 224 } 225 226 return sourceFiles, nil 227 } 228 229 func (receiver *VendorPublishCommand) publishFile(sourceFile, targetFile string, existing, force bool) (bool, error) { 230 content, err := os.ReadFile(sourceFile) 231 if err != nil { 232 return false, err 233 } 234 235 if !file.Exists(targetFile) && existing { 236 return false, nil 237 } 238 if file.Exists(targetFile) && !force && !existing { 239 return false, nil 240 } 241 242 if err := file.Create(targetFile, string(content)); err != nil { 243 return false, err 244 } 245 246 return true, nil 247 }