package main import ( "bufio" "encoding/json" "flag" "fmt" // "io/ioutil" "os" "os/exec" "strings" ) // Configuration represents a single Perforce configuration item. type Configuration struct { Name string `json:"Name"` Type string `json:"Type"` Value string `json:"Value"` } var ( p4dRoot string executeCommands bool action string jsonFile string ) func init() { flag.StringVar(&p4dRoot, "r", "", "The P4D root directory") flag.BoolVar(&executeCommands, "y", false, "Execute commands instead of echoing (dry run by default)") flag.StringVar(&action, "action", "", "The action to perform: csave, unset, or set") flag.StringVar(&jsonFile, "json-file", "", "The path to the JSON file") } func main() { flag.Parse() if p4dRoot == "" { fmt.Println("P4D_ROOT directory must be specified with -r") flag.Usage() os.Exit(1) } if jsonFile == "" || (action != "save" && action != "csave" && action != "unset" && action != "set") { fmt.Println("You must specify a valid action (-action) and a JSON file (-json-file)") flag.Usage() os.Exit(1) } switch action { // case "save": // saveSettings() case "csave": csaveSettings() case "unset": processConfigs("unset") case "set": processConfigs("set") } } /* Disabled for now func saveSettings() { fmt.Printf("Saving Perforce server configuration settings to %s...\n", jsonFile) cmd := exec.Command("p4", "-Mj", "-ztag", "configure", "show") output, err := cmd.Output() if err != nil { fmt.Println("Error executing p4 command:", err) return } err = ioutil.WriteFile(jsonFile, output, 0644) if err != nil { fmt.Println("Error writing to file:", err) return } fmt.Println("Settings saved.") } */ func processConfigs(operation string) { fmt.Printf("Processing commands to %s configurations from %s...\n", operation, jsonFile) file, err := os.Open(jsonFile) if err != nil { fmt.Println("Error opening JSON file:", err) return } defer file.Close() scanner := bufio.NewScanner(file) for scanner.Scan() { var config Configuration err := json.Unmarshal(scanner.Bytes(), &config) if err != nil { fmt.Println("Error parsing JSON:", err) continue } if config.Type == "configure" || config.Type == "tunable (configure)" { cmdStr := "" if operation == "unset" { cmdStr = fmt.Sprintf("p4d -r \"%s\" \"-cunset %s\"", p4dRoot, config.Name) } else if operation == "set" { cmdStr = fmt.Sprintf("p4d -r \"%s\" \"-cset %s=%s\"", p4dRoot, config.Name, config.Value) } runOrEcho(cmdStr) } } if err := scanner.Err(); err != nil { fmt.Println("Error reading JSON file:", err) } } func csaveSettings() { fmt.Printf("Saving Perforce server configuration settings using -cshow to %s...\n", jsonFile) // Execute the p4d -cshow command cmd := exec.Command("p4d", "-r", p4dRoot, "-cshow") output, err := cmd.Output() if err != nil { fmt.Println("Error executing p4d command:", err) return } // Open the JSON file for writing file, err := os.Create(jsonFile) if err != nil { fmt.Println("Error opening file for writing:", err) return } defer file.Close() // Split the output into lines and process each line lines := strings.Split(string(output), "\n") for _, line := range lines { line = strings.TrimSpace(line) if line == "" { continue // skip empty lines } // Handle special prefixes and remove "any:" prefix var prefix, name, value string if strings.Contains(line, ":") { parts := strings.SplitN(line, ": ", 2) prefix = strings.TrimSpace(parts[0]) parts = strings.SplitN(parts[1], " = ", 2) name, value = parts[0], parts[1] } else { parts := strings.SplitN(line, " = ", 2) name, value = parts[0], parts[1] } // Construct the configuration object with appropriate name formatting var configName string if prefix != "" && prefix != "any" { configName = prefix + "#" + name } else { configName = name } // Determine the configuration type (placeholder function) configType := determineConfigType(name) // Write the configuration to the file config := Configuration{Name: configName, Type: configType, Value: value} jsonData, err := json.Marshal(config) if err != nil { fmt.Println("Error marshalling JSON:", err) continue } _, err = file.WriteString(string(jsonData) + "\n") if err != nil { fmt.Println("Error writing to file:", err) return } } fmt.Println("Settings saved.") } // Determine the type of configuration based on the name // This is a placeholder function, implement the logic based on your requirements func determineConfigType(name string) string { // Example: return "tunable (configure)" for specific known names, otherwise "configure" if strings.HasPrefix(name, "db.") || strings.HasPrefix(name, "lbr.") { return "tunable (configure)" } return "configure" } // determineType infers the type of the configuration based on its name. // Update this function to accurately reflect how you determine the types. func determineType(name string) string { if strings.HasPrefix(name, "server.") || strings.HasPrefix(name, "db.") { return "tunable (configure)" } return "configure" } func runOrEcho(commandStr string) { if executeCommands { fmt.Println("Executing:", commandStr) cmd := exec.Command("sh", "-c", commandStr) err := cmd.Run() if err != nil { fmt.Println("Error executing command:", err) } } else { fmt.Println("[DRY RUN]", commandStr) } }