package main import ( bpmutilsshared "bpm-utils-shared" "bufio" "bytes" "fmt" "io" "log" "os" "os/exec" "path" "strings" flag "github.com/spf13/pflag" yaml "gopkg.in/yaml.v3" ) var name = flag.StringP("name", "n", "", "Set the package name") var description = flag.StringP("description", "d", "Default Package Description", "Set the description") var version = flag.StringP("version", "v", "1.0", "Set the package version") var url = flag.StringP("url", "u", "", "Set the package URL") var license = flag.StringP("license", "l", "", "Set the package licenses") var template = flag.StringP("template", "t", "gnu-configure", "Set the package template") var git = flag.BoolP("git", "g", true, "Create git repository") var directory = "" func main() { // Setup flags and help setupFlagsAndHelp("bpm-setup ", "Sets up files and directories for BPM source package creation") // Trim package name *name = strings.TrimSpace(*name) // Show command help if no directory name is given if *name == "" { log.Println("Error: name flag is required") flag.Usage() os.Exit(1) } // Get current repository repo := bpmutilsshared.GetRepository() // Set directory if repo != "" { directory = path.Join(repo, "recipes", *name) } else { workDir, err := os.Getwd() if err != nil { log.Fatalf("Error: could not get working directory") } directory = path.Join(workDir, *name) } // run checks runChecks() // Show summary showSummary() // Confirmation prompt fmt.Printf("Create package directory? [y\\N]: ") reader := bufio.NewReader(os.Stdin) text, _ := reader.ReadString('\n') if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" { fmt.Println("Cancelling package directory creation...") os.Exit(1) } // Create package directory createDirectory() } func runChecks() { // Check if package name is valid if *name == "" { log.Fatalf("Error: no package name was specified!") } // Check if parent directory is valid if _, err := os.Stat(path.Dir(directory)); err != nil { log.Fatalf("Error: %s is not a valid directory: %s", path.Dir(directory), err) } // Check if package directory exists if _, err := os.Stat(directory); err == nil { log.Fatalf("Error: %s already exists", directory) } // Check if template file is valid if stat, err := os.Stat(path.Join("/etc/bpm-utils/templates/", *template)); err != nil || stat.IsDir() { log.Fatalf("Error: '%s' is not a valid template file!", *template) } } func showSummary() { fmt.Printf("Setting up package directory at %s with the following information:\n", directory) fmt.Printf("Package name: %s\n", strings.TrimSpace(*name)) fmt.Printf("Package description: %s\n", *description) fmt.Printf("Package version: %s\n", *version) if url != nil && *url != "" { fmt.Printf("Package URL: %s\n", *url) } else { fmt.Printf("Package URL: Not Set\n") } if license != nil && *license != "" { fmt.Printf("Package license: %s\n", *license) } else { fmt.Printf("Package license: Not Set\n") } fmt.Printf("Template file: %s\n", *template) fmt.Printf("Create git repository: %t\n", *git) } func replaceVariables(templateContents string) string { templateContents = strings.ReplaceAll(templateContents, "$NAME", *name) templateContents = strings.ReplaceAll(templateContents, "$DESCRIPTION", *description) templateContents = strings.ReplaceAll(templateContents, "$VERSION", *version) templateContents = strings.ReplaceAll(templateContents, "$URL", *url) return templateContents } func createDirectory() { // Read BPM utils config config, err := bpmutilsshared.ReadBPMUtilsConfig() if err != nil { log.Fatalf("Error: failed to read config: %s", err) } // Create directory err = os.Mkdir(directory, 0755) if err != nil { log.Fatalf("Error: could not create directory: %s", err) } // Create package info struct pkgInfo := bpmutilsshared.PackageInfo{ Name: *name, Description: *description, Version: *version, Revision: 1, Url: *url, License: *license, Arch: "any", Type: "source", Downloads: []bpmutilsshared.PackageDownload{ { Url: "https://wwww.my-url.com/file.tar.gz", ExtractTo: "${BPM_SOURCE}", ExtractStripComponents: 1, Checksum: "replaceme", }, }, } if config.DefaultMaintainer != "" { pkgInfo.Maintainers = append(pkgInfo.Maintainers, config.DefaultMaintainer) } var buffer bytes.Buffer encoder := yaml.NewEncoder(&buffer) encoder.SetIndent(2) encoder.Encode(&pkgInfo) // Write package info to file err = os.WriteFile(path.Join(directory, "info.yml"), buffer.Bytes(), 0644) if err != nil { log.Fatalf("Could not write to info.yml: %s", err) } // Create source-files directory err = os.Mkdir(path.Join(directory, "source-files"), 0755) if err != nil { log.Fatalf("Error: could not create directory: %s", err) } // Copy source template file input, err := os.ReadFile(path.Join("/etc/bpm-utils/templates", *template)) if err != nil { log.Fatalf("Error: could not read template file: %s", err) return } // Replace variables in template file input = []byte(replaceVariables(string(input))) err = os.WriteFile(path.Join(directory, "recipe.sh"), input, 0644) if err != nil { log.Fatalf("Error: could not write to source file: %s", err) return } // Create git repository if git != nil && *git { err = exec.Command("git", "init", directory).Run() if err != nil { log.Fatalf("Error: could not initialize git repository: %s", err) } // Copy default gitignore defaultGitignoreFile, err := os.Open("/etc/bpm-utils/gitignore.default") if err != nil { return } defer defaultGitignoreFile.Close() newGitignoreFile, err := os.OpenFile(path.Join(directory, ".gitignore"), os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Fatalf("Error: could not create .gitignore file: %s", err) } _, err = io.Copy(newGitignoreFile, defaultGitignoreFile) if err != nil { log.Fatalf("Error: could not copy data to .gitignore file: %s", err) } } } func setupFlagsAndHelp(usage, desc string) { flag.Usage = func() { fmt.Println("Usage: " + usage) fmt.Println("Description: " + desc) fmt.Println("Options:") flag.PrintDefaults() } flag.Parse() }