Adds initial gitlocal CLI and core functionality
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`.
This commit is contained in:
59
internal/scanner/scanner.go
Normal file
59
internal/scanner/scanner.go
Normal file
@@ -0,0 +1,59 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user