package gitpb import ( "bufio" "fmt" "io/ioutil" "os" "path/filepath" "strings" "go.wit.com/log" ) // does processing on the go.mod and go.sum files func (repo *Repo) updateGitConfig() error { if repo == nil { return fmt.Errorf("gitpb.updateGitConfig() repo == nil") } if repo.GitConfig == nil { repo.GitConfig = new(GitConfig) } repo.GitConfig.Core = make(map[string]string) repo.GitConfig.Remotes = make(map[string]*GitRemote) repo.GitConfig.Branches = make(map[string]*GitBranch) repo.GitConfig.Submodules = make(map[string]string) repo.GitConfig.Versions = make(map[string]string) repo.GitConfig.Hashes = make(map[string]string) return repo.readGitConfig() } // readGitConfig reads and parses the .git/config file func (repo *Repo) readGitConfig() error { filename := filepath.Join(repo.GetFullPath(), ".git/config") file, err := os.Open(filename) defer file.Close() if err != nil { return err } var currentSection string = "" var currentName string = "" 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]) key = strings.TrimSuffix(key, "\"") value := strings.TrimSpace(partsNew[1]) value = strings.TrimSuffix(value, "\"") switch currentSection { case "core": repo.GitConfig.Core[key] = value case "gui": // don't really need gui stuff right now case "pull": // don't store git config pull settings here // git config probably has 'rebase = false' case "remote": test, ok := repo.GitConfig.Remotes[currentName] if !ok { test = new(GitRemote) repo.GitConfig.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(INFO, "error url mismatch", test.Url, value) case "fetch": if test.Fetch == value { continue } if test.Fetch == "" { test.Fetch = value continue } log.Log(INFO, "error fetch mismatch", test.Fetch, value) default: log.Log(INFO, "unknown remote:", line) } case "branch": test, ok := repo.GitConfig.Branches[currentName] if !ok { test = new(GitBranch) repo.GitConfig.Branches[currentName] = test repo.processBranch(currentName) } switch key { case "remote": repo.GitConfig.Branches[currentName].Remote = value case "merge": repo.GitConfig.Branches[currentName].Merge = value default: log.Log(INFO, "error unknown remote:", currentSection, currentName, key, value) log.Log(INFO, "unknown branch:", line) } case "submodule": // test, ok := rs.gitConfig.submodules[currentName] switch key { case "active": // probably 'true' or 'false' case "url": repo.GitConfig.Submodules[currentName] = value default: log.Log(WARN, "unknown submodule line:", line) } default: log.Log(WARN, "unknown line:", line) } } if err := scanner.Err(); err != nil { return err } return nil } func (repo *Repo) processBranch(branch string) { log.Log(INFO, " ", branch) hash, ok := repo.GitConfig.Hashes[branch] filename := filepath.Join(repo.GetFullPath() + "/.git/refs/heads/" + branch) log.Log(INFO, " hash: need to open", filename) data, err := ioutil.ReadFile(filename) if err != nil { log.Log(WARN, "hash: read failed", filename) return } newhash := strings.TrimSpace(string(data)) log.Log(INFO, " hash:", newhash) repo.GitConfig.Hashes[branch] = newhash if ok { if hash != newhash { log.Log(WARN, "hash changed", hash) } } name, _ := repo.gitDescribeByHash(newhash) repo.GitConfig.Versions[newhash] = name log.Log(INFO, " hash: version", name) }