Created
August 21, 2024 14:55
-
-
Save charlires/efb6b964cd59045803e6a8cc50eb660e to your computer and use it in GitHub Desktop.
A go script to merge multiple go files in a dir tree into one single file per dir
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"flag" | |
"fmt" | |
"io/fs" | |
"os" | |
"path/filepath" | |
"strings" | |
) | |
// A go script to merge multiple go files into one single file | |
// - look down recursively in the provided directory | |
// - create a merge file per directory the generated file in each directory and name the file as the directory | |
// - merge all files in a provided directory into the new file | |
// - if the directory doesn't have go files in it void creating a go file for that directory node | |
// - remove duplicated package declaration | |
// - remove duplicated imports | |
// usage: | |
// go run merge.go -dir=path/to/root/directory | |
// go run merge.go -dir=path/to/root/directory -clean | |
func main() { | |
dir := flag.String("dir", ".", "Root directory to search for Go files") | |
clean := flag.Bool("clean", false, "Delete all merged files after merging") | |
flag.Parse() | |
var mergedFiles []string | |
err := filepath.Walk(*dir, func(path string, info os.FileInfo, err error) error { | |
if err != nil { | |
return err | |
} | |
if info.IsDir() { | |
mergedFile := mergeFilesInDirectory(path) | |
if len(mergedFile) > 0 { | |
mergedFiles = append(mergedFiles, mergedFile...) | |
} | |
} | |
return nil | |
}) | |
if err != nil { | |
fmt.Println("Error walking the path:", err) | |
return | |
} | |
fmt.Println("Merge completed for all directories.") | |
if *clean { | |
deleteMergedFiles(mergedFiles) | |
} | |
} | |
func mergeFilesInDirectory(dir string) []string { | |
files, err := os.ReadDir(dir) | |
if err != nil { | |
fmt.Println("Error reading directory:", dir, err) | |
return nil | |
} | |
var goFiles []fs.DirEntry | |
for _, file := range files { | |
if filepath.Ext(file.Name()) == ".go" && file.Name() != filepath.Base(dir)+".go" { | |
goFiles = append(goFiles, file) | |
} | |
} | |
if len(goFiles) == 0 { | |
// No Go files in this directory, so skip creating a merged file | |
return nil | |
} | |
outputFilePath := filepath.Join(dir, filepath.Base(dir)+".go") | |
outputFile, err := os.Create(outputFilePath) | |
if err != nil { | |
fmt.Println("Error creating output file:", err) | |
return nil | |
} | |
defer outputFile.Close() | |
writer := bufio.NewWriter(outputFile) | |
defer writer.Flush() | |
packageDeclared := false | |
importSet := make(map[string]bool) | |
var mergedFiles []string | |
for _, file := range goFiles { | |
filePath := filepath.Join(dir, file.Name()) | |
mergeFile(filePath, writer, &packageDeclared, importSet) | |
mergedFiles = append(mergedFiles, filePath) | |
} | |
fmt.Println("Files merged successfully into", outputFilePath) | |
return mergedFiles | |
} | |
func mergeFile(filePath string, writer *bufio.Writer, packageDeclared *bool, importSet map[string]bool) { | |
file, err := os.Open(filePath) | |
if err != nil { | |
fmt.Println("Error opening file:", filePath, err) | |
return | |
} | |
defer file.Close() | |
scanner := bufio.NewScanner(file) | |
inImportSection := false | |
for scanner.Scan() { | |
line := scanner.Text() | |
trimmedLine := strings.TrimSpace(line) | |
if strings.HasPrefix(trimmedLine, "package ") && *packageDeclared { | |
continue | |
} | |
if strings.HasPrefix(trimmedLine, "package ") && !*packageDeclared { | |
writer.WriteString(line + "\n") | |
*packageDeclared = true | |
continue | |
} | |
if strings.HasPrefix(trimmedLine, "import ") { | |
inImportSection = true | |
} | |
if inImportSection { | |
if trimmedLine == ")" { | |
inImportSection = false | |
} | |
if !importSet[trimmedLine] { | |
writer.WriteString(line + "\n") | |
importSet[trimmedLine] = true | |
} | |
continue | |
} | |
writer.WriteString(line + "\n") | |
} | |
if err := scanner.Err(); err != nil { | |
fmt.Println("Error reading file:", filePath, err) | |
} | |
} | |
func deleteMergedFiles(mergedFiles []string) { | |
for _, filePath := range mergedFiles { | |
err := os.Remove(filePath) | |
if err != nil { | |
fmt.Println("Error deleting file:", filePath, err) | |
} else { | |
fmt.Println("Deleted merged file:", filePath) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment