Skip to content

Commit 0622252

Browse files
committed
v1.2.2
Switches the `-c`/`--command` flag from `StringSlice` to `StringArray` to prevent splitting commands on commas, ensuring single quoted commands (e.g., PowerShell `Select-Object`) are preserved as intended. Updates CLI, tests, documentation, and version to v1.2.2; adds release notes and improves robustness for Windows shell usage.
1 parent 21ba747 commit 0622252

File tree

9 files changed

+89
-13
lines changed

9 files changed

+89
-13
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33

44
All notable changes to this project will be documented in this file.
55

6+
## v1.2.2 - 2026-01-17
7+
8+
- Bugfix: Preserve comma-containing commands passed via a single `-c` flag (e.g., PowerShell `Select-Object` usage such as `Get-ComputerInfo | Select-Object OsName, OsVersion, OsArchitecture`). The CLI no longer splits a single `-c` value on commas — instead we use repeatable `-c` flags (`StringArray`) and ensure a single quoted `-c` is preserved literally.
9+
- Internal: Switch `-c` command flags from `StringSlice` (which splits on commas) to `StringArray` to avoid unintended splitting; update retrieval functions accordingly and add unit tests to validate behavior.
10+
- Tests: Add `TestSaveCommand_PreservesCommasInFlag` and update save-related tests to be robust across Windows-style inputs and quoting edge cases.
11+
- Docs: Update `docs/cli.md` and add release notes for v1.2.2 describing the change and upgrade guidance.
12+
613
## v1.2.1 - 2026-01-17
714

815
- CLI: **save** — Enhanced the `krnr save` command to better handle shell quoting mistakes by joining or merging split command arguments (e.g., when shells split embedded quotes) and heuristically reinserting `/C:"pattern"` quoting for common `findstr` usages. Adds robust argument splitting via `github.com/kballard/go-shellquote` and new unit tests.

RELEASE_NOTES/GITHUB_v1.2.2.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# v1.2.2 — 2026-01-17
2+
3+
Patch release focusing on a robustness fix for the `save` command.
4+
5+
What’s changed
6+
7+
- Preserve comma-containing commands passed via a single `-c` flag (PowerShell `Select-Object` usage). A single quoted `-c` will now be stored as a single command and is no longer split on commas.
8+
- Internal: switched the repeatable command flag to `StringArray` to avoid unintended splitting and added tests to cover the behavior.
9+
10+
Upgrade notes
11+
12+
- No DB schema changes are required.
13+
- When using Windows shells, prefer quoting `-c` values fully (e.g., `-c 'Get-ComputerInfo | Select-Object OsName, OsVersion, OsArchitecture'`) to avoid shell-level tokenization issues.
14+
15+
Thanks to contributors and maintainers for quick turnaround on this fix.

cmd/edit.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ var editCmd = &cobra.Command{
1919
Args: cobra.ExactArgs(1),
2020
RunE: func(cmd *cobra.Command, args []string) error {
2121
name := args[0]
22-
cmdsFlags, _ := cmd.Flags().GetStringSlice("command")
22+
cmdsFlags, _ := cmd.Flags().GetStringArray("command")
2323

2424
dbConn, err := db.InitDB()
2525
if err != nil {
@@ -89,6 +89,6 @@ var editCmd = &cobra.Command{
8989
}
9090

9191
func init() {
92-
editCmd.Flags().StringSliceP("command", "c", []string{}, "Replace commands non-interactively (use multiple times)")
92+
editCmd.Flags().StringArrayP("command", "c", []string{}, "Replace commands non-interactively (use multiple times)")
9393
rootCmd.AddCommand(editCmd)
9494
}

cmd/save.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Note: When using Windows shells, be sure to properly quote embedded double-quote
2323
RunE: func(cmd *cobra.Command, args []string) error {
2424
name := args[0]
2525
desc, _ := cmd.Flags().GetString("description")
26-
cmds, _ := cmd.Flags().GetStringSlice("command")
26+
cmds, _ := cmd.Flags().GetStringArray("command")
2727
// If the user accidentally allowed the shell to split a quoted
2828
// command into multiple positionals, join the remaining args into a
2929
// single command. If exactly one `-c` was provided, merge the
@@ -161,7 +161,7 @@ func normalizeFindstrCArgs(s string) string {
161161

162162
func init() {
163163
saveCmd.Flags().StringP("description", "d", "", "Description for the command set")
164-
saveCmd.Flags().StringSliceP("command", "c", []string{}, "Command to add to the set (can be repeated)")
164+
saveCmd.Flags().StringArrayP("command", "c", []string{}, "Command to add to the set (can be repeated)")
165165
saveCmd.Flags().StringP("author", "a", "", "Author name for this command set (overrides stored whoami)")
166166
saveCmd.Flags().StringP("author-email", "e", "", "Author email for this command set (optional)")
167167
rootCmd.AddCommand(saveCmd)

cmd/save_cli_test.go

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func TestSaveWithSplitArgs_MergeIntoSingle(t *testing.T) {
5454
// the flag parser returning a single command element and the CLI args
5555
// holding the remaining tokens.
5656
local := &cobra.Command{RunE: saveCmd.RunE, Args: saveCmd.Args}
57-
local.Flags().StringSliceP("command", "c", []string{}, "Command to add to the set (can be repeated)")
57+
local.Flags().StringArrayP("command", "c", []string{}, "Command to add to the set (can be repeated)")
5858
if err := local.Flags().Set("command", "systeminfo | findstr /C:"); err != nil {
5959
t.Fatalf("set flag: %v", err)
6060
}
@@ -86,3 +86,41 @@ func TestSaveWithSplitArgs_MergeIntoSingle(t *testing.T) {
8686
t.Fatalf("expected merged and normalized command %q, got %q", expected, cs.Commands[0].Command)
8787
}
8888
}
89+
90+
func TestSaveCommand_PreservesCommasInFlag(t *testing.T) {
91+
_ = setupTempDB(t)
92+
// Ensure no pre-existing set with the same name
93+
dbConn, err := db.InitDB()
94+
if err != nil {
95+
t.Fatalf("InitDB(): %v", err)
96+
}
97+
defer func() { _ = dbConn.Close() }()
98+
r2 := registry.NewRepository(dbConn)
99+
_ = r2.DeleteCommandSet("PS-preserve-comma")
100+
101+
// Simulate: krnr save PS-preserve-comma -c "Get-ComputerInfo | Select-Object OsName, OsVersion, OsArchitecture"
102+
rootCmd.SetArgs([]string{"save", "PS-preserve-comma", "-c", "Get-ComputerInfo | Select-Object OsName, OsVersion, OsArchitecture"})
103+
if err := rootCmd.Execute(); err != nil {
104+
t.Fatalf("save failed: %v", err)
105+
}
106+
107+
// Verify the command set exists and the command was preserved as a single entry
108+
cs, err := r2.GetCommandSetByName("PS-preserve-comma")
109+
if err != nil {
110+
t.Fatalf("GetCommandSetByName: %v", err)
111+
}
112+
if cs == nil {
113+
t.Fatalf("expected saved command set 'PS-preserve-comma' in DB")
114+
}
115+
expected := "Get-ComputerInfo | Select-Object OsName, OsVersion, OsArchitecture"
116+
found := false
117+
for _, c := range cs.Commands {
118+
if c.Command == expected {
119+
found = true
120+
break
121+
}
122+
}
123+
if !found {
124+
t.Fatalf("expected preserved command %q to be present in commands, got: %+v", expected, cs.Commands)
125+
}
126+
}

cmd/save_test.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package cmd
22

33
import (
44
"bytes"
5-
"strings"
65
"testing"
76

87
"github.com/spf13/cobra"
@@ -24,10 +23,13 @@ func TestSaveCommand_SavesCommands(t *testing.T) {
2423
// use a fresh command with its own FlagSet to avoid global flag state
2524
local := &cobra.Command{RunE: saveCmd.RunE, Args: saveCmd.Args}
2625
local.Flags().StringP("description", "d", "", "Description for the command set")
27-
local.Flags().StringSliceP("command", "c", []string{}, "Command to add to the set (can be repeated)")
26+
local.Flags().StringArrayP("command", "c", []string{}, "Command to add to the set (can be repeated)")
2827
local.Flags().StringP("author", "a", "", "Author name for this command set (overrides stored whoami)")
2928
local.Flags().StringP("author-email", "e", "", "Author email for this command set (optional)")
30-
if err := local.Flags().Set("command", "echo save1,echo save2"); err != nil {
29+
if err := local.Flags().Set("command", "echo save1"); err != nil {
30+
t.Fatalf("set flag: %v", err)
31+
}
32+
if err := local.Flags().Set("command", "echo save2"); err != nil {
3133
t.Fatalf("set flag: %v", err)
3234
}
3335

@@ -70,12 +72,14 @@ func runSaveWithInput(t *testing.T, initialName string, stdin string, commands [
7072

7173
local := &cobra.Command{RunE: saveCmd.RunE, Args: saveCmd.Args}
7274
local.Flags().StringP("description", "d", "", "Description for the command set")
73-
local.Flags().StringSliceP("command", "c", []string{}, "Command to add to the set (can be repeated)")
75+
local.Flags().StringArrayP("command", "c", []string{}, "Command to add to the set (can be repeated)")
7476
local.Flags().StringP("author", "a", "", "Author name for this command set (overrides stored whoami)")
7577
local.Flags().StringP("author-email", "e", "", "Author email for this command set (optional)")
7678
local.SetIn(bytes.NewBufferString(stdin))
77-
if err := local.Flags().Set("command", strings.Join(commands, ",")); err != nil {
78-
t.Fatalf("set flag: %v", err)
79+
for _, c := range commands {
80+
if err := local.Flags().Set("command", c); err != nil {
81+
t.Fatalf("set flag: %v", err)
82+
}
7983
}
8084

8185
if err := local.RunE(local, []string{initialName}); err != nil {

docs/cli.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Author metadata:
1616
- `--author-email` (`-e`) optionally sets the author email.
1717
- If `--author` is not provided, `krnr save` will use the stored `whoami` identity if present.
1818

19-
Quoting & save behavior: The `save` command (v1.2.1) is more tolerant of common shell quoting mistakes. When leftover tokens are detected (for example, when shells split quoted arguments), `save` will join leftover tokens into a single `-c` command or merge them into an existing single `-c` value when appropriate. For simple `findstr /C:` patterns it will attempt to reinsert expected quotes so the saved command better matches user intent. Prefer providing command values as a single quoted `-c` when possible; see `docs/releases/v1.2.1.md` for details.
19+
Quoting & save behavior: The `save` command (v1.2.2) is more tolerant of common shell quoting mistakes. When leftover tokens are detected (for example, when shells split quoted arguments), `save` will join leftover tokens into a single `-c` command or merge them into an existing single `-c` value when appropriate. For simple `findstr /C:` patterns it will attempt to reinsert expected quotes so the saved command better matches user intent. Prefer providing command values as a single quoted `-c` when possible; see `docs/releases/v1.2.2.md` for details.
2020

2121
## whoami
2222

docs/releases/v1.2.2.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# v1.2.2 - 2026-01-17
2+
3+
This patch release fixes a subtle behavior where comma-containing commands (common in PowerShell cmdlets like `Select-Object`) could be split into multiple saved commands when supplied via a single `-c` flag. The CLI now preserves a single quoted `-c` value exactly (it no longer splits on commas).
4+
5+
Highlights
6+
7+
- Fix: Preserve comma-containing `-c` values (e.g., `Get-ComputerInfo | Select-Object OsName, OsVersion, OsArchitecture`) as a single saved command.
8+
- Internal: Use `StringArray` for the repeatable `-c`/`--command` flag to avoid unintended comma splitting caused by `StringSlice`.
9+
- Tests: Added unit tests to assert preservation of comma-containing commands and improved save-related tests to be robust to shell tokenization edge cases.
10+
- Docs: Updated `docs/cli.md` and `CHANGELOG.md` to document the fix and provide upgrade guidance.
11+
12+
Upgrade guidance: Simply upgrade to v1.2.2; no DB schema changes are required. When using Windows shells, prefer quoting `-c` values fully (e.g., `-c 'Get-ComputerInfo | Select-Object OsName, OsVersion, OsArchitecture'`) to avoid any shell-level splitting. If you rely on previously-split behavior, re-save the affected command sets after upgrading.

internal/version/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ package version
33

44
// Version is set at build time via -ldflags "-X github.com/VoxDroid/krnr/internal/version.Version=<value>"
55
// The default is a development placeholder.
6-
var Version = "v1.2.1"
6+
var Version = "v1.2.2"

0 commit comments

Comments
 (0)