236 lines
5.4 KiB
Go
236 lines
5.4 KiB
Go
|
package repostatus
|
||
|
|
||
|
import (
|
||
|
"bufio"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
"strings"
|
||
|
|
||
|
"go.wit.com/log"
|
||
|
)
|
||
|
|
||
|
// GitConfig represents the parsed .git/config data
|
||
|
// type GitConfig map[string]map[string]string
|
||
|
|
||
|
type remote struct {
|
||
|
url string
|
||
|
fetch string
|
||
|
}
|
||
|
|
||
|
type branch struct {
|
||
|
remote string
|
||
|
merge string
|
||
|
}
|
||
|
|
||
|
type GitConfig struct {
|
||
|
core map[string]string // map[origin] = "https:/git.wit.org/gui/gadgets"
|
||
|
remotes map[string]*remote // map[origin] = "https:/git.wit.org/gui/gadgets"
|
||
|
branches map[string]*branch // map[guimaster] = origin guimaster
|
||
|
}
|
||
|
|
||
|
type GoConfig map[string]string
|
||
|
|
||
|
func listGitDirectories() []string {
|
||
|
var all []string
|
||
|
homeDir, err := os.UserHomeDir()
|
||
|
if err != nil {
|
||
|
log.Log(WARN, "Error getting home directory:", err)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
srcDir := filepath.Join(homeDir, "go/src")
|
||
|
|
||
|
err = filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
|
||
|
if err != nil {
|
||
|
log.Log(WARN, "Error accessing path:", path, err)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Check if the current path is a directory and has a .git subdirectory
|
||
|
if info.IsDir() && isGitDir(path) {
|
||
|
all = append(all, path)
|
||
|
// fmt.Println(path)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
})
|
||
|
|
||
|
if err != nil {
|
||
|
log.Log(WARN, "Error walking the path:", srcDir, err)
|
||
|
}
|
||
|
|
||
|
return all
|
||
|
}
|
||
|
|
||
|
// isGitDir checks if a .git directory exists inside the given directory
|
||
|
func isGitDir(dir string) bool {
|
||
|
gitDir := filepath.Join(dir, ".git")
|
||
|
info, err := os.Stat(gitDir)
|
||
|
if os.IsNotExist(err) {
|
||
|
return false
|
||
|
}
|
||
|
return info.IsDir()
|
||
|
}
|
||
|
|
||
|
// readGitConfig reads and parses the .git/config file
|
||
|
func readGitConfig(filePath string) (*GitConfig, error) {
|
||
|
file, err := os.Open(filePath)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
defer file.Close()
|
||
|
|
||
|
var currentSection string = ""
|
||
|
var currentName string = ""
|
||
|
|
||
|
config := new(GitConfig)
|
||
|
config.core = make(map[string]string)
|
||
|
config.remotes = make(map[string]*remote)
|
||
|
config.branches = make(map[string]*branch)
|
||
|
|
||
|
scanner := bufio.NewScanner(file)
|
||
|
for scanner.Scan() {
|
||
|
line := strings.TrimSpace(scanner.Text())
|
||
|
|
||
|
// Skip empty lines and comments
|
||
|
if line == "" || strings.HasPrefix(line, "#") || strings.HasPrefix(line, ";") {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
// Check for section headers
|
||
|
if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
|
||
|
line = strings.Trim(line, "[]")
|
||
|
parts := strings.Split(line, " ")
|
||
|
currentSection = parts[0]
|
||
|
|
||
|
if len(parts) == 2 {
|
||
|
line = strings.Trim(line, "[]")
|
||
|
currentName = strings.Trim(parts[1], "[]")
|
||
|
}
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
partsNew := strings.SplitN(line, "=", 2)
|
||
|
if len(partsNew) != 2 {
|
||
|
log.Log(WARN, "error on config section:", currentSection, "line:", line)
|
||
|
}
|
||
|
|
||
|
key := strings.TrimSpace(partsNew[0])
|
||
|
value := strings.TrimSpace(partsNew[1])
|
||
|
|
||
|
switch currentSection {
|
||
|
case "core":
|
||
|
config.core[key] = value
|
||
|
case "remote":
|
||
|
test, ok := config.remotes[currentName]
|
||
|
if !ok {
|
||
|
test = new(remote)
|
||
|
config.remotes[currentName] = test
|
||
|
}
|
||
|
log.Log(INFO, "switch currentSection", currentSection, currentName)
|
||
|
switch key {
|
||
|
case "url":
|
||
|
if test.url == value {
|
||
|
continue
|
||
|
}
|
||
|
if test.url == "" {
|
||
|
test.url = value
|
||
|
continue
|
||
|
}
|
||
|
log.Log(WARN, "error url mismatch", test.url, value)
|
||
|
case "fetch":
|
||
|
if test.fetch == value {
|
||
|
continue
|
||
|
}
|
||
|
if test.fetch == "" {
|
||
|
test.fetch = value
|
||
|
continue
|
||
|
}
|
||
|
log.Log(WARN, "error fetch mismatch", test.fetch, value)
|
||
|
default:
|
||
|
log.Log(WARN, "error unknown remote:", currentSection, currentName, "key", key, "value", value)
|
||
|
}
|
||
|
case "branch":
|
||
|
test, ok := config.branches[currentName]
|
||
|
if !ok {
|
||
|
test = new(branch)
|
||
|
config.branches[currentName] = test
|
||
|
}
|
||
|
switch key {
|
||
|
case "remote":
|
||
|
config.branches[currentName].remote = value
|
||
|
case "merge":
|
||
|
config.branches[currentName].merge = value
|
||
|
default:
|
||
|
log.Log(WARN, "error unknown remote:", currentSection, currentName, key, value)
|
||
|
}
|
||
|
default:
|
||
|
log.Log(WARN, "error unknown currentSection", currentSection, "line:", line)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if err := scanner.Err(); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return config, nil
|
||
|
}
|
||
|
|
||
|
// readGoMod reads and parses the go.sum file (TODO: do the go.mod file)
|
||
|
func (rs *RepoStatus) ReadGoMod() bool {
|
||
|
tmp := filepath.Join(rs.realPath.String(), "go.sum")
|
||
|
gomod, err := os.Open(tmp)
|
||
|
if err != nil {
|
||
|
log.Log(WARN, "missing go.mod", rs.realPath.String())
|
||
|
rs.goConfig = nil
|
||
|
return false
|
||
|
}
|
||
|
defer gomod.Close()
|
||
|
|
||
|
tmp = filepath.Join(rs.realPath.String(), "go.sum")
|
||
|
gosum, err := os.Open(tmp)
|
||
|
if err != nil {
|
||
|
log.Log(WARN, "missing go.sum", rs.realPath.String())
|
||
|
rs.goConfig = nil
|
||
|
return false
|
||
|
}
|
||
|
defer gosum.Close()
|
||
|
|
||
|
var deps GoConfig
|
||
|
deps = make(GoConfig)
|
||
|
|
||
|
scanner := bufio.NewScanner(gosum)
|
||
|
log.Log(INFO, "gosum:", tmp)
|
||
|
for scanner.Scan() {
|
||
|
line := strings.TrimSpace(scanner.Text())
|
||
|
|
||
|
parts := strings.Split(line, " ")
|
||
|
if len(parts) == 3 {
|
||
|
godep := strings.TrimSpace(parts[0])
|
||
|
version := strings.TrimSpace(parts[1])
|
||
|
if strings.HasSuffix(version, "/go.mod") {
|
||
|
version = strings.TrimSuffix(version, "/go.mod")
|
||
|
}
|
||
|
currentversion, ok := deps[godep]
|
||
|
if ok {
|
||
|
if currentversion != version {
|
||
|
log.Log(WARN, "versions do not match!!!", deps[godep], version, currentversion)
|
||
|
}
|
||
|
} else {
|
||
|
deps[godep] = version
|
||
|
log.Log(INFO, "\t", godep, "=", version)
|
||
|
}
|
||
|
} else {
|
||
|
log.Log(WARN, "\t INVALID:", parts)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if err := scanner.Err(); err != nil {
|
||
|
rs.goConfig = nil
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
rs.goConfig = deps
|
||
|
return true
|
||
|
}
|