diff --git a/client/client_test.go b/client/client_test.go index 40e2c51..c035811 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -19,6 +19,8 @@ import ( "github.com/ddworken/hishtory/shared" ) +// TODO: Change this to only start the server once for this entire file + func RunInteractiveBashCommands(t *testing.T, script string) string { out, err := RunInteractiveBashCommandsWithoutStrictMode(t, "set -emo pipefail\n"+script) if err != nil { @@ -537,6 +539,41 @@ hishtory enable`, i)) } } +func TestExcludeHiddenCommand(t *testing.T) { + // Set up + defer shared.BackupAndRestore(t)() + defer shared.RunTestServer(t)() + installHishtory(t, "") + + RunInteractiveBashCommands(t, `echo hello1 + echo hidden +echo hello2 + echo hidden`) + RunInteractiveBashCommands(t, " echo hidden") + out := hishtoryQuery(t, "") + if strings.Count(out, "\n") != 6 { + t.Fatalf("hishtory query has the wrong number of lines=%d, out=%#v", strings.Count(out, "\n"), out) + } + if strings.Count(out, "echo hello") != 2 { + t.Fatalf("hishtory query has the wrong number of commands=%d, out=%#v", strings.Count(out, "echo mycommand"), out) + } + if strings.Count(out, "echo hello1") != 1 { + t.Fatalf("hishtory query has the wrong number of commands=%d, out=%#v", strings.Count(out, "echo mycommand"), out) + } + if strings.Count(out, "echo hello2") != 1 { + t.Fatalf("hishtory query has the wrong number of commands=%d, out=%#v", strings.Count(out, "echo mycommand"), out) + } + if strings.Contains(out, "hidden") { + t.Fatalf("hishtory query contains a result that should not have been recorded, out=%#v", out) + } + + out = RunInteractiveBashCommands(t, "hishtory export") + expectedOutput := "set -emo pipefail\necho hello1\necho hello2\nset -emo pipefail\nset -emo pipefail\nhishtory query\nset -emo pipefail\n" + if out != expectedOutput { + t.Fatalf("hishtory export has unexpected output=%#v", out) + } +} + func waitForBackgroundSavesToComplete(t *testing.T) { for i := 0; i < 20; i++ { cmd := exec.Command("pidof", "hishtory") diff --git a/client/lib/lib.go b/client/lib/lib.go index 165b11e..9008c15 100644 --- a/client/lib/lib.go +++ b/client/lib/lib.go @@ -96,6 +96,17 @@ func BuildHistoryEntry(args []string) (*data.HistoryEntry, error) { if err != nil { return nil, fmt.Errorf("failed to build history entry: %v", err) } + shouldBeSkipped, err := shouldSkipHiddenCommand(args[3]) + if err != nil { + return nil, fmt.Errorf("failed to check if command was hidden: %v", err) + } + if shouldBeSkipped { + return nil, nil + } + if strings.HasPrefix(cmd, " ") { + // Don't save commands that start with a space + return nil, nil + } entry.Command = cmd // hostname @@ -109,7 +120,23 @@ func BuildHistoryEntry(args []string) (*data.HistoryEntry, error) { } func getLastCommand(history string) (string, error) { - return strings.TrimSpace(strings.SplitN(strings.TrimSpace(history), " ", 2)[1]), nil + return strings.SplitN(strings.TrimSpace(history), " ", 2)[1][1:], nil +} + +func shouldSkipHiddenCommand(historyLine string) (bool, error) { + config, err := GetConfig() + if err != nil { + return false, err + } + if config.LastSavedHistoryLine == historyLine { + return true, nil + } + config.LastSavedHistoryLine = historyLine + err = SetConfig(config) + if err != nil { + return false, err + } + return false, nil } func GetUserSecret() (string, error) { @@ -211,9 +238,10 @@ func DisplayResults(results []*data.HistoryEntry) { } type ClientConfig struct { - UserSecret string `json:"user_secret"` - IsEnabled bool `json:"is_enabled"` - DeviceId string `json:"device_id"` + UserSecret string `json:"user_secret"` + IsEnabled bool `json:"is_enabled"` + DeviceId string `json:"device_id"` + LastSavedHistoryLine string `json:"last_saved_history_line"` } func GetConfig() (ClientConfig, error) { diff --git a/client/lib/lib_test.go b/client/lib/lib_test.go index 5357299..9a3f368 100644 --- a/client/lib/lib_test.go +++ b/client/lib/lib_test.go @@ -35,6 +35,8 @@ func TestBuildHistoryEntry(t *testing.T) { defer shared.BackupAndRestore(t)() defer shared.RunTestServer(t)() shared.Check(t, Setup([]string{})) + + // Test building an actual entry entry, err := BuildHistoryEntry([]string{"unused", "saveHistoryEntry", "120", " 123 ls / ", "1641774958326745663"}) shared.Check(t, err) if entry.ExitCode != 120 { @@ -59,6 +61,9 @@ func TestBuildHistoryEntry(t *testing.T) { if entry.StartTime.Unix() != 1641774958 { t.Fatalf("history entry has incorrect Unix time in the start time: %v", entry.StartTime.Unix()) } + + // Test the behavior when the command is prefixed with a space + // TODO: write a test for this } func TestGetUserSecret(t *testing.T) { diff --git a/hishtory.go b/hishtory.go index e1e95fc..a09cbdf 100644 --- a/hishtory.go +++ b/hishtory.go @@ -136,6 +136,9 @@ func saveHistoryEntry() { } entry, err := lib.BuildHistoryEntry(os.Args) lib.CheckFatalError(err) + if entry == nil { + return + } // Persist it locally db, err := lib.OpenLocalSqliteDb() diff --git a/shared/testutils.go b/shared/testutils.go index 00cc2d8..88d0037 100644 --- a/shared/testutils.go +++ b/shared/testutils.go @@ -2,7 +2,6 @@ package shared import ( "bytes" - "fmt" "os" "os/exec" "path" @@ -100,7 +99,7 @@ func RunTestServer(t *testing.T) func() { if strings.Contains(stderr.String()+stdout.String(), "failed to") { t.Fatalf("server failed to do something: stderr=%#v, stdout=%#v", stderr.String(), stdout.String()) } - fmt.Printf("stderr=%#v, stdout=%#v\n", stderr.String(), stdout.String()) + // fmt.Printf("stderr=%#v, stdout=%#v\n", stderr.String(), stdout.String()) } }