From ddb22a2f65fb58fa229d4f2bfc801066b20d8db7 Mon Sep 17 00:00:00 2001
From: sudoforge <no-reply@sudoforge.com>
Date: Sun, 18 May 2025 21:54:06 -0700
Subject: [PATCH] fix(cli): ignore missing sections when removing configuration
 (#1455)

This change fixes an error typically encountered in the `git-bug-wipe`
command, caused by overly zealous implementations of
//repository:config.go%ConfigWrite.RemoveAll(). This change refactors
these implementations to only attempt to remove sections that exist,
and ignore non-existent sections.

Closes: #1451
Change-Id: I66e710239915c8601dd70a78ae65eb625e093ef6
---
 CONTRIBUTING.md              | 10 ++++++++++
 commands/wipe.go             |  1 +
 repository/config_mem.go     |  7 -------
 repository/config_testing.go |  9 +++------
 repository/gogit_config.go   | 13 +------------
 5 files changed, 15 insertions(+), 25 deletions(-)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4b190aa9..6882b428 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -16,6 +16,7 @@ getting started as a contributor to this project.
   - [4.2 | Test the development shell](#42--test-the-development-shell)
 - [Useful development commands](#useful-development-commands)
 - [Submitting changes](#submitting-changes)
+  - [Commit messages are the source of truth](#commit-messages-are-the-source-of-truth)
   - [Push early, push often](#push-early-push-often)
   - [Pull requests are squashed](#pull-requests-are-squashed)
   - [Draft vs Ready](#draft-vs-ready)
@@ -265,6 +266,15 @@ repository, and create a pull request.
 If you are in the development shell, you have the `gh` command line tool
 available for use with github.
 
+### Commit messages are the source of truth<a name="commit-messages-are-the-source-of-truth"></a>
+
+Commit subjects and messages are the source of truth for a variety of things,
+including the public-facing changelog (\[`//:CHANGELOG.md`\]\[changelog\]) and
+release descriptions. Writing thorough commit messages is beneficial to anyone
+reviewing a commit, including future you!
+
+Please be sure to read the [commit message guidelines][doc/contrib/commit].
+
 ### Push early, push often<a name="push-early-push-often"></a>
 
 We encourage pushing small changes. There is no such thing as a contribution
diff --git a/commands/wipe.go b/commands/wipe.go
index 2f378e90..d9dab42a 100644
--- a/commands/wipe.go
+++ b/commands/wipe.go
@@ -33,6 +33,7 @@ func runWipe(env *execenv.Env) error {
 		_ = env.Backend.Close()
 		return err
 	}
+
 	err = env.Backend.LocalConfig().RemoveAll("git-bug")
 	if err != nil {
 		_ = env.Backend.Close()
diff --git a/repository/config_mem.go b/repository/config_mem.go
index d9126f39..1639a25d 100644
--- a/repository/config_mem.go
+++ b/repository/config_mem.go
@@ -1,7 +1,6 @@
 package repository
 
 import (
-	"fmt"
 	"strconv"
 	"strings"
 	"time"
@@ -82,18 +81,12 @@ func (mc *MemConfig) ReadTimestamp(key string) (time.Time, error) {
 // RemoveAll remove all key/value pair matching the key prefix
 func (mc *MemConfig) RemoveAll(keyPrefix string) error {
 	keyPrefix = normalizeKey(keyPrefix)
-	found := false
 	for key := range mc.config {
 		if strings.HasPrefix(key, keyPrefix) {
 			delete(mc.config, key)
-			found = true
 		}
 	}
 
-	if !found {
-		return fmt.Errorf("section not found")
-	}
-
 	return nil
 }
 
diff --git a/repository/config_testing.go b/repository/config_testing.go
index 8c22934a..f658708d 100644
--- a/repository/config_testing.go
+++ b/repository/config_testing.go
@@ -56,7 +56,7 @@ func testConfig(t *testing.T, config Config) {
 	require.ErrorIs(t, err, ErrNoConfigEntry)
 
 	err = config.RemoveAll("section.nonexistingkey")
-	require.Error(t, err)
+	require.NoError(t, err)
 
 	err = config.RemoveAll("section.key")
 	require.NoError(t, err)
@@ -65,20 +65,17 @@ func testConfig(t *testing.T, config Config) {
 	require.ErrorIs(t, err, ErrNoConfigEntry)
 
 	err = config.RemoveAll("nonexistingsection")
-	require.Error(t, err)
+	require.NoError(t, err)
 
 	err = config.RemoveAll("section.time")
 	require.NoError(t, err)
 
 	err = config.RemoveAll("section")
-	require.Error(t, err)
+	require.NoError(t, err)
 
 	_, err = config.ReadString("section.key")
 	require.Error(t, err)
 
-	err = config.RemoveAll("section.key")
-	require.Error(t, err)
-
 	// section + subsections
 	require.NoError(t, config.StoreString("section.opt1", "foo"))
 	require.NoError(t, config.StoreString("section.opt2", "foo2"))
diff --git a/repository/gogit_config.go b/repository/gogit_config.go
index afa652b1..1427b344 100644
--- a/repository/gogit_config.go
+++ b/repository/gogit_config.go
@@ -212,27 +212,16 @@ func (cw *goGitConfigWriter) RemoveAll(keyPrefix string) error {
 	case len(split) == 1:
 		if cfg.Raw.HasSection(split[0]) {
 			cfg.Raw.RemoveSection(split[0])
-		} else {
-			return fmt.Errorf("invalid key prefix")
-		}
-	default:
-		if !cfg.Raw.HasSection(split[0]) {
-			return fmt.Errorf("invalid key prefix")
 		}
+	case cfg.Raw.HasSection(split[0]):
 		section := cfg.Raw.Section(split[0])
 		rest := strings.Join(split[1:], ".")
 
-		ok := false
 		if section.HasSubsection(rest) {
 			section.RemoveSubsection(rest)
-			ok = true
 		}
 		if section.HasOption(rest) {
 			section.RemoveOption(rest)
-			ok = true
-		}
-		if !ok {
-			return fmt.Errorf("invalid key prefix")
 		}
 	}
 
-- 
GitLab