Properly skip recording of commands prefixed with a space to match bash's history behavior

This commit is contained in:
David Dworken 2022-04-15 00:04:49 -07:00
parent 2fdfbb9d20
commit b09b725f49
5 changed files with 78 additions and 6 deletions

View File

@ -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")

View File

@ -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) {

View File

@ -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) {

View File

@ -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()

View File

@ -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())
}
}