diff --git a/file.go b/file.go index 3a8f148..c623f35 100644 --- a/file.go +++ b/file.go @@ -9,6 +9,7 @@ package gocodewalker import ( "bytes" "errors" + "fmt" "github.com/boyter/gocodewalker/go-gitignore" "golang.org/x/sync/errgroup" "os" @@ -20,8 +21,9 @@ import ( ) const ( - GitIgnore = ".gitignore" - Ignore = ".ignore" + GitIgnore = ".gitignore" + Ignore = ".ignore" + GitModules = ".gitmodules" ) // ErrTerminateWalk error which indicates that the walker was terminated @@ -56,6 +58,7 @@ type FileWalker struct { isWalking bool IgnoreIgnoreFile bool // Should .ignore files be respected? IgnoreGitIgnore bool // Should .gitignore files be respected? + IgnoreGitModules bool // Should .gitmodules files be respected? IncludeHidden bool // Should hidden files and directories be included/walked osOpen func(name string) (*os.File, error) osReadFile func(name string) ([]byte, error) @@ -86,6 +89,7 @@ func NewFileWalker(directory string, fileListQueue chan *File) *FileWalker { isWalking: false, IgnoreIgnoreFile: false, IgnoreGitIgnore: false, + IgnoreGitModules: false, IncludeHidden: false, osOpen: os.Open, osReadFile: os.ReadFile, @@ -117,6 +121,7 @@ func NewParallelFileWalker(directories []string, fileListQueue chan *File) *File isWalking: false, IgnoreIgnoreFile: false, IgnoreGitIgnore: false, + IgnoreGitModules: false, IncludeHidden: false, osOpen: os.Open, osReadFile: os.ReadFile, @@ -305,6 +310,27 @@ func (f *FileWalker) walkDirectoryRecursive(iteration int, directory string, git ignores = append(ignores, gitIgnore) } } + + // this should only happen on the first iteration + // because there can only be one .gitmodules file per repository + // however we also need to support someone running in a directory of + // projects that have multiple repositories or in a go vendor + // repository etc... + if !f.IgnoreGitModules { + if file.Name() == GitModules { + // now we need to open and parse the file + c, err := f.osReadFile(filepath.Join(directory, file.Name())) + if err != nil { + if f.errorsHandler(err) { + continue // if asked to ignore it lets continue + } + return err + } + + fmt.Println(c) + //extractGitModuleFolders() + } + } } // Process files first to start feeding whatever process is consuming diff --git a/gitmodule.go b/gitmodule.go new file mode 100644 index 0000000..361a780 --- /dev/null +++ b/gitmodule.go @@ -0,0 +1,23 @@ +package gocodewalker + +import ( + "regexp" + "strings" +) + +func extractGitModuleFolders(input string) []string { + // Compile a regular expression to match lines starting with "path =" + re := regexp.MustCompile(`^\s*path\s*=\s*(.*)`) + output := []string{} + + for _, line := range strings.Split(input, "\n") { + // Check if the line matches the "path = " pattern + if matches := re.FindStringSubmatch(line); matches != nil { + // Extract the submodule path (which is captured in the regex group) + submodulePath := strings.TrimSpace(matches[1]) + output = append(output, submodulePath) + } + } + + return output +} diff --git a/gitmodule_test.go b/gitmodule_test.go new file mode 100644 index 0000000..8b4c34c --- /dev/null +++ b/gitmodule_test.go @@ -0,0 +1,63 @@ +package gocodewalker + +import ( + "reflect" + "testing" +) + +func Test_extractGitModuleFolders(t *testing.T) { + type args struct { + input string + } + tests := []struct { + name string + args args + want []string + }{ + { + name: "", + args: args{ + input: `[submodule "contracts/lib/forge-std"] + path = contracts/lib/forge-std + url = https://github.com/foundry-rs/forge-std + tag = v1.8.2 +[submodule "contracts/lib/sp1-contracts"] + path = contracts/lib/sp1-contracts + url = https://github.com/succinctlabs/sp1-contracts + tag = main +[submodule "contracts/lib/openzeppelin-contracts"] + path = contracts/lib/openzeppelin-contracts + url = https://github.com/OpenZeppelin/openzeppelin-contracts +[submodule "lib/java-tron"] + path = lib/java-tron + url = https://github.com/tronprotocol/java-tron +[submodule "lib/googleapis"] + path = lib/googleapis + url = https://github.com/googleapis/googleapis +[submodule "contracts/lib/openzeppelin-contracts-upgradeable"] + path = contracts/lib/openzeppelin-contracts-upgradeable + url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable +[submodule "contracts/lib/v2-testnet-contracts"] + path = contracts/lib/v2-testnet-contracts + url = https://github.com/matter-labs/v2-testnet-contracts + branch = beta`, + }, + want: []string{ + "contracts/lib/forge-std", + "contracts/lib/sp1-contracts", + "contracts/lib/openzeppelin-contracts", + "lib/java-tron", + "lib/googleapis", + "contracts/lib/openzeppelin-contracts-upgradeable", + "contracts/lib/v2-testnet-contracts", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := extractGitModuleFolders(tt.args.input); !reflect.DeepEqual(got, tt.want) { + t.Errorf("extractGitModuleFolders() = %v, want %v", got, tt.want) + } + }) + } +}