summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Carr <[email protected]>2025-08-20 11:44:32 -0500
committerJeff Carr <[email protected]>2025-08-20 11:44:32 -0500
commit80dd77a6c8d0204d9e184b7290c008dc1221cdc2 (patch)
tree51d8584da9e3ac3f6afac6adacc41ac8b1945ae4
parent12a66969603471c4686110cff53c102734054a41 (diff)
more cleanups on doClean()v0.22.127
-rw-r--r--doClean.go57
-rw-r--r--doDirty.go2
-rw-r--r--gitconfig_parser.go143
3 files changed, 196 insertions, 6 deletions
diff --git a/doClean.go b/doClean.go
index 4b435b3..dbb2b18 100644
--- a/doClean.go
+++ b/doClean.go
@@ -44,7 +44,54 @@ func doClean() error {
doRepoCleanDevel(repo)
}
- log.Info("finished attempt at cleaning devel branches")
+ found := gitpb.NewRepos()
+
+ total := 0
+ // find all repos that aren't "clean"
+ all = me.forge.Repos.SortByFullPath()
+ for all.Scan() {
+ repo := all.Next()
+ total += 1
+
+ // find repos not on master branch
+ if repo.GetCurrentBranchName() != repo.GetMasterBranchName() {
+ found.AppendByGoPath(repo)
+ continue
+ }
+
+ // find dirty repos
+ if repo.IsDirty() {
+ found.AppendByGoPath(repo)
+ continue
+ }
+
+ // find repos that still have a local user branch
+ if repo.IsLocalBranch(repo.GetUserBranchName()) {
+ found.AppendByGoPath(repo)
+ continue
+ }
+
+ // find repos that still have a local devel branch
+ if repo.IsLocalBranch(repo.GetDevelBranchName()) {
+ found.AppendByGoPath(repo)
+ continue
+ }
+ }
+
+ // display all the repos that aren't clean to the user
+ log.Printf("\n") // padding for now
+ if argv.Verbose {
+ me.forge.PrintHumanTableDirty(found)
+ } else {
+ me.forge.PrintHumanTable(found)
+ }
+ log.Printf("\n") // padding for now
+
+ if found.Len() == 0 {
+ log.Printf("%d repos are not clean\n", found.Len())
+ } else {
+ log.Info("All repos are clean", total, found.Len())
+ }
return nil
}
@@ -100,7 +147,7 @@ func doRepoCleanUser(repo *gitpb.Repo) error {
if b1 == 0 {
// every user branch exists in devel. delete user branch
cmd := []string{"git", "branch", "-D", bruser}
- log.Info("USER IS IN DEVEL", repo.GetGoPath(), cmd)
+ // log.Info("USER IS IN DEVEL", repo.GetGoPath(), cmd)
err := repo.RunVerbose(cmd)
return err
}
@@ -116,7 +163,7 @@ func doRepoCleanUser(repo *gitpb.Repo) error {
b1 := repo.CountDiffObjects(bruser, "refs/heads/"+brmaster) // should be zero
if b1 == 0 {
cmd := []string{"git", "branch", "-D", bruser}
- log.Info("USER IS IN DEVEL", repo.GetGoPath(), cmd)
+ // log.Info("USER IS IN DEVEL", repo.GetGoPath(), cmd)
err := repo.RunVerbose(cmd)
return err
}
@@ -143,7 +190,7 @@ func justDeleteTheDevelBranchAlready(repo *gitpb.Repo) error {
b1 := repo.CountDiffObjects(branch, remote) // should be zero
if b1 == 0 {
cmd := []string{"git", "branch", "-D", repo.GetDevelBranchName()}
- log.Info("DEVEL IS IN REMOTE", repo.GetGoPath(), cmd)
+ // log.Info("DEVEL IS IN REMOTE", repo.GetGoPath(), cmd)
err := repo.RunVerbose(cmd)
return err
}
@@ -158,7 +205,7 @@ func justDeleteTheDevelBranchAlready(repo *gitpb.Repo) error {
b1 := repo.CountDiffObjects(branch, "refs/heads/"+master) // should be zero
if b1 == 0 {
cmd := []string{"git", "branch", "-D", repo.GetDevelBranchName()}
- log.Info("DEVEL IS IN REMOTE", repo.GetGoPath(), cmd)
+ // log.Info("DEVEL IS IN REMOTE", repo.GetGoPath(), cmd)
err := repo.RunVerbose(cmd)
return err
}
diff --git a/doDirty.go b/doDirty.go
index d13a31d..f4373d9 100644
--- a/doDirty.go
+++ b/doDirty.go
@@ -36,7 +36,7 @@ func doDirty() {
// this needs to run each time in case repos were added manually by the user
// this also verifies that
func checkNormalRepoState(repo *gitpb.Repo) error {
- if err := repo.MakeLocalDevelBranch(); err != nil {
+ if _, err := repo.MakeLocalDevelBranch(); err != nil {
return err
}
if repo.GetCurrentBranchName() != repo.GetUserBranchName() {
diff --git a/gitconfig_parser.go b/gitconfig_parser.go
new file mode 100644
index 0000000..edab556
--- /dev/null
+++ b/gitconfig_parser.go
@@ -0,0 +1,143 @@
+package main
+
+// playing with gemini to do simple tasks. it kicked this out
+
+import (
+ "bufio"
+ "errors"
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+// ParsedGitConfig represents the structure of a .gitconfig file,
+// which is a map of section names to a map of their key-value pairs.
+// For example:
+//
+// {
+// "user": {
+// "name": "John Doe",
+// "email": "[email protected]",
+// },
+// "core": {
+// "editor": "vim",
+// },
+// }
+type ParsedGitConfig map[string]map[string]string
+
+// ParseGlobalGitConfig finds and parses the global .gitconfig file for the current user.
+// It is platform-agnostic and works on Windows, macOS, and Linux.
+// It returns the parsed configuration or an error if the file cannot be found or read.
+func ParseGlobalGitConfig() (ParsedGitConfig, error) {
+ // os.UserHomeDir() is the platform-agnostic way to get the user's home directory.
+ homeDir, err := os.UserHomeDir()
+ if err != nil {
+ return nil, fmt.Errorf("could not get user home directory: %w", err)
+ }
+
+ // filepath.Join correctly constructs the path for the current OS.
+ gitConfigPath := filepath.Join(homeDir, ".gitconfig")
+
+ file, err := os.Open(gitConfigPath)
+ if err != nil {
+ if errors.Is(err, os.ErrNotExist) {
+ return nil, fmt.Errorf(".gitconfig file not found at %s", gitConfigPath)
+ }
+ return nil, fmt.Errorf("could not open .gitconfig file: %w", err)
+ }
+ defer file.Close()
+
+ config := make(ParsedGitConfig)
+ var currentSection string
+ scanner := bufio.NewScanner(file)
+
+ for scanner.Scan() {
+ line := strings.TrimSpace(scanner.Text())
+
+ // Ignore empty lines and comments
+ if line == "" || line[0] == '#' || line[0] == ';' {
+ continue
+ }
+
+ // Check for a new section
+ if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
+ sectionName := line[1 : len(line)-1]
+ // Handle subsections like [remote "origin"] by splitting them.
+ // For simplicity, we'll just use the full string as the key.
+ // A more complex parser might create nested maps.
+ currentSection = strings.TrimSpace(sectionName)
+ if _, exists := config[currentSection]; !exists {
+ config[currentSection] = make(map[string]string)
+ }
+ continue
+ }
+
+ // Parse key-value pairs within a section
+ if currentSection != "" {
+ // Split by "=". Use SplitN to handle values that might contain "=".
+ parts := strings.SplitN(line, "=", 2)
+ if len(parts) == 2 {
+ key := strings.TrimSpace(parts[0])
+ value := strings.TrimSpace(parts[1])
+ config[currentSection][key] = value
+ }
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ return nil, fmt.Errorf("error reading .gitconfig file: %w", err)
+ }
+
+ return config, nil
+}
+
+// GetValue retrieves a specific value from the parsed git config.
+// It takes the section and key as input (e.g., "user", "name").
+// It returns the value and a boolean indicating if the key was found.
+func (c ParsedGitConfig) GetValue(section, key string) (string, bool) {
+ if sectionMap, ok := c[section]; ok {
+ if value, ok := sectionMap[key]; ok {
+ return value, true
+ }
+ }
+ return "", false
+}
+
+/*
+// main function to demonstrate the usage of ParseGlobalGitConfig.
+func main() {
+ config, err := ParseGlobalGitConfig()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error: %v\n", err)
+ os.Exit(1)
+ }
+
+ fmt.Println("Successfully parsed global .gitconfig file.")
+ fmt.Println("-----------------------------------------")
+
+ // Example of using GetValue to retrieve the user's name and email.
+ userName, found := config.GetValue("user", "name")
+ if found {
+ fmt.Printf("User Name: %s\n", userName)
+ } else {
+ fmt.Println("User name not found.")
+ }
+
+ userEmail, found := config.GetValue("user", "email")
+ if found {
+ fmt.Printf("User Email: %s\n", userEmail)
+ } else {
+ fmt.Println("User email not found.")
+ }
+
+ fmt.Println("\nFull configuration:")
+ // Print out the full parsed configuration
+ for section, keys := range config {
+ fmt.Printf("[%s]\n", section)
+ for key, value := range keys {
+ fmt.Printf(" %s = %s\n", key, value)
+ }
+ }
+}
+*/