Introduces the `gitlocal` command-line tool for managing nested Git repositories. Includes the following main commands: - `convert`: Renames `.git` to `.gitlocal`, allowing a parent repository to ignore the converted child repository. Supports recursive scanning and dry-run options. Tracks converted repositories in a global configuration. - `revert`: Restores `.gitlocal` to `.git`. Includes an option to revert all tracked repositories. - `status`: Displays a list of all repositories currently tracked by `gitlocal`, showing their path, conversion time, and original remote/branch. Establishes internal modules for Git operations, configuration management, and recursive repository scanning. Adds a comprehensive test suite covering core command logic and utility functions. Initializes Go module and basic project `.gitignore`.
60 lines
1.5 KiB
Go
60 lines
1.5 KiB
Go
package scanner
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"git.membo.co.uk/dtomlinson/gitlocal/internal/git"
|
|
)
|
|
|
|
// FindNestedGitRepos recursively scans rootPath for nested .git and .gitlocal directories
|
|
// and returns a list of absolute paths to directories containing .git or .gitlocal
|
|
// It skips the root repo's .git/.gitlocal directory if one exists
|
|
func FindNestedGitRepos(rootPath string) ([]string, error) {
|
|
var repos []string
|
|
|
|
// Get absolute path
|
|
absRoot, err := filepath.Abs(rootPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Check if root itself is a git repo (either .git or .gitlocal)
|
|
rootIsGitRepo := git.IsGitRepo(absRoot) || git.IsGitLocalRepo(absRoot)
|
|
rootGitPath := filepath.Join(absRoot, git.GitDir)
|
|
rootGitLocalPath := filepath.Join(absRoot, git.GitLocalDir)
|
|
|
|
err = filepath.Walk(absRoot, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Skip if not a directory
|
|
if !info.IsDir() {
|
|
return nil
|
|
}
|
|
|
|
// Skip if this is the root's .git or .gitlocal directory
|
|
if rootIsGitRepo && (path == rootGitPath || path == rootGitLocalPath) {
|
|
return filepath.SkipDir
|
|
}
|
|
|
|
// Check if this directory is named .git or .gitlocal
|
|
if info.Name() == git.GitDir || info.Name() == git.GitLocalDir {
|
|
// Get the parent directory (the actual repo path)
|
|
repoPath := filepath.Dir(path)
|
|
repos = append(repos, repoPath)
|
|
// Skip descending into .git/.gitlocal directory
|
|
return filepath.SkipDir
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return repos, nil
|
|
}
|