mirror of
https://github.com/ddworken/hishtory.git
synced 2024-12-23 23:39:02 +01:00
Add uninstall command + tests for uninstall
This commit is contained in:
parent
422556f812
commit
17ae676da0
@ -156,6 +156,7 @@ func TestParameterized(t *testing.T) {
|
||||
t.Run("testControlR/"+tester.ShellName(), func(t *testing.T) { testControlR(t, tester, tester.ShellName()) })
|
||||
t.Run("testHandleUpgradedFeatures/"+tester.ShellName(), func(t *testing.T) { testHandleUpgradedFeatures(t, tester) })
|
||||
t.Run("testCustomColumns/"+tester.ShellName(), func(t *testing.T) { testCustomColumns(t, tester) })
|
||||
t.Run("testUninstall/"+tester.ShellName(), func(t *testing.T) { testUninstall(t, tester) })
|
||||
}
|
||||
t.Run("testControlR/fish", func(t *testing.T) { testControlR(t, bashTester{}, "fish") })
|
||||
}
|
||||
@ -2003,6 +2004,40 @@ echo bar`)
|
||||
compareGoldens(t, out, fmt.Sprintf("testCustomColumns-tquery-%s-isAction=%v", tester.ShellName(), (os.Getenv("GITHUB_ACTION") != "")))
|
||||
}
|
||||
|
||||
func testUninstall(t *testing.T, tester shellTester) {
|
||||
// Setup
|
||||
defer testutils.BackupAndRestore(t)()
|
||||
installHishtory(t, tester, "")
|
||||
|
||||
// Record a few commands and check that they get recorded
|
||||
tester.RunInteractiveShell(t, `echo foo
|
||||
echo baz`)
|
||||
out := tester.RunInteractiveShell(t, `hishtory export -pipefail`)
|
||||
compareGoldens(t, out, "testUninstall-recorded")
|
||||
|
||||
// And then uninstall
|
||||
out, err := tester.RunInteractiveShellRelaxed(t, `yes | hishtory uninstall`)
|
||||
testutils.Check(t, err)
|
||||
compareGoldens(t, out, "testUninstall-uninstall")
|
||||
|
||||
// And check that hishtory has been uninstalled
|
||||
out, err = tester.RunInteractiveShellRelaxed(t, `echo foo
|
||||
hishtory
|
||||
echo bar`)
|
||||
testutils.Check(t, err)
|
||||
compareGoldens(t, out, "testUninstall-post-uninstall")
|
||||
|
||||
// And check again, but in a way that shows the full terminal output
|
||||
if os.Getenv("GITHUB_ACTION") == "" {
|
||||
out = captureTerminalOutput(t, tester, []string{
|
||||
"echo SPACE foo ENTER",
|
||||
"hishtory ENTER",
|
||||
"echo SPACE bar ENTER",
|
||||
})
|
||||
compareGoldens(t, out, "testUninstall-post-uninstall-"+tester.ShellName())
|
||||
}
|
||||
}
|
||||
|
||||
type deviceSet struct {
|
||||
deviceMap *map[device]deviceOp
|
||||
currentDevice *device
|
||||
|
2
client/lib/goldens/testUninstall-post-uninstall
Normal file
2
client/lib/goldens/testUninstall-post-uninstall
Normal file
@ -0,0 +1,2 @@
|
||||
foo
|
||||
bar
|
8
client/lib/goldens/testUninstall-post-uninstall-bash
Normal file
8
client/lib/goldens/testUninstall-post-uninstall-bash
Normal file
@ -0,0 +1,8 @@
|
||||
bash-5.2$ source /Users/david/.bashrc
|
||||
bash-5.2$ echo foo
|
||||
foo
|
||||
bash-5.2$ hishtory
|
||||
bash: hishtory: command not found
|
||||
bash-5.2$ echo bar
|
||||
bar
|
||||
bash-5.2$
|
7
client/lib/goldens/testUninstall-post-uninstall-zsh
Normal file
7
client/lib/goldens/testUninstall-post-uninstall-zsh
Normal file
@ -0,0 +1,7 @@
|
||||
david@Davids-MacBook-Air hishtory % echo foo
|
||||
foo
|
||||
david@Davids-MacBook-Air hishtory % hishtory
|
||||
zsh: command not found: hishtory
|
||||
david@Davids-MacBook-Air hishtory % echo bar
|
||||
bar
|
||||
david@Davids-MacBook-Air hishtory %
|
2
client/lib/goldens/testUninstall-recorded
Normal file
2
client/lib/goldens/testUninstall-recorded
Normal file
@ -0,0 +1,2 @@
|
||||
echo foo
|
||||
echo baz
|
1
client/lib/goldens/testUninstall-uninstall
Normal file
1
client/lib/goldens/testUninstall-uninstall
Normal file
@ -0,0 +1 @@
|
||||
Are you sure you want to uninstall hiSHtory and delete all locally saved history data [y/N]Successfully uninstalled hishtory, please restart your terminal...
|
@ -672,6 +672,10 @@ func handleUpgradedFeatures() error {
|
||||
return hctx.SetConfig(config)
|
||||
}
|
||||
|
||||
func getFishConfigPath(homedir string) string {
|
||||
return path.Join(homedir, data.HISHTORY_PATH, "config.fish")
|
||||
}
|
||||
|
||||
func configureFish(homedir, binaryPath string) error {
|
||||
// Check if fish is installed
|
||||
_, err := exec.LookPath("fish")
|
||||
@ -679,7 +683,6 @@ func configureFish(homedir, binaryPath string) error {
|
||||
return nil
|
||||
}
|
||||
// Create the file we're going to source. Do this no matter what in case there are updates to it.
|
||||
fishConfigPath := path.Join(homedir, data.HISHTORY_PATH, "config.fish")
|
||||
configContents := ConfigFishContents
|
||||
if os.Getenv("HISHTORY_TEST") != "" {
|
||||
testConfig, err := tweakConfigForTests(ConfigFishContents)
|
||||
@ -688,7 +691,7 @@ func configureFish(homedir, binaryPath string) error {
|
||||
}
|
||||
configContents = testConfig
|
||||
}
|
||||
err = ioutil.WriteFile(fishConfigPath, []byte(configContents), 0o644)
|
||||
err = ioutil.WriteFile(getFishConfigPath(homedir), []byte(configContents), 0o644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write config.zsh file: %v", err)
|
||||
}
|
||||
@ -710,28 +713,35 @@ func configureFish(homedir, binaryPath string) error {
|
||||
return fmt.Errorf("failed to append to ~/.config/fish/config.fish: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
_, err = f.WriteString("\n# Hishtory Config:\nexport PATH=\"$PATH:" + path.Join(homedir, data.HISHTORY_PATH) + "\"\nsource " + fishConfigPath + "\n")
|
||||
_, err = f.WriteString(getFishConfigFragment(homedir))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to append to zshrc: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getFishConfigFragment(homedir string) string {
|
||||
return "\n# Hishtory Config:\nexport PATH=\"$PATH:" + path.Join(homedir, data.HISHTORY_PATH) + "\"\nsource " + getFishConfigPath(homedir) + "\n"
|
||||
}
|
||||
|
||||
func isFishConfigured(homedir string) (bool, error) {
|
||||
_, err := os.Stat(path.Join(homedir, ".config/fish/config.fish"))
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return false, nil
|
||||
}
|
||||
bashrc, err := ioutil.ReadFile(path.Join(homedir, ".config/fish/config.fish"))
|
||||
fishConfig, err := ioutil.ReadFile(path.Join(homedir, ".config/fish/config.fish"))
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to read ~/.config/fish/config.fish: %v", err)
|
||||
}
|
||||
return strings.Contains(string(bashrc), "# Hishtory Config:"), nil
|
||||
return strings.Contains(string(fishConfig), "# Hishtory Config:"), nil
|
||||
}
|
||||
|
||||
func getZshConfigPath(homedir string) string {
|
||||
return path.Join(homedir, data.HISHTORY_PATH, "config.zsh")
|
||||
}
|
||||
|
||||
func configureZshrc(homedir, binaryPath string) error {
|
||||
// Create the file we're going to source in our zshrc. Do this no matter what in case there are updates to it.
|
||||
zshConfigPath := path.Join(homedir, data.HISHTORY_PATH, "config.zsh")
|
||||
configContents := ConfigZshContents
|
||||
if os.Getenv("HISHTORY_TEST") != "" {
|
||||
testConfig, err := tweakConfigForTests(configContents)
|
||||
@ -740,7 +750,7 @@ func configureZshrc(homedir, binaryPath string) error {
|
||||
}
|
||||
configContents = testConfig
|
||||
}
|
||||
err := ioutil.WriteFile(zshConfigPath, []byte(configContents), 0o644)
|
||||
err := ioutil.WriteFile(getZshConfigPath(homedir), []byte(configContents), 0o644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write config.zsh file: %v", err)
|
||||
}
|
||||
@ -758,13 +768,17 @@ func configureZshrc(homedir, binaryPath string) error {
|
||||
return fmt.Errorf("failed to append to zshrc: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
_, err = f.WriteString("\n# Hishtory Config:\nexport PATH=\"$PATH:" + path.Join(homedir, data.HISHTORY_PATH) + "\"\nsource " + zshConfigPath + "\n")
|
||||
_, err = f.WriteString(getZshConfigFragment(homedir))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to append to zshrc: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getZshConfigFragment(homedir string) string {
|
||||
return "\n# Hishtory Config:\nexport PATH=\"$PATH:" + path.Join(homedir, data.HISHTORY_PATH) + "\"\nsource " + getZshConfigPath(homedir) + "\n"
|
||||
}
|
||||
|
||||
func isZshConfigured(homedir string) (bool, error) {
|
||||
_, err := os.Stat(path.Join(homedir, ".zshrc"))
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
@ -777,9 +791,12 @@ func isZshConfigured(homedir string) (bool, error) {
|
||||
return strings.Contains(string(bashrc), "# Hishtory Config:"), nil
|
||||
}
|
||||
|
||||
func getBashConfigPath(homedir string) string {
|
||||
return path.Join(homedir, data.HISHTORY_PATH, "config.sh")
|
||||
}
|
||||
|
||||
func configureBashrc(homedir, binaryPath string) error {
|
||||
// Create the file we're going to source in our bashrc. Do this no matter what in case there are updates to it.
|
||||
bashConfigPath := path.Join(homedir, data.HISHTORY_PATH, "config.sh")
|
||||
configContents := ConfigShContents
|
||||
if os.Getenv("HISHTORY_TEST") != "" {
|
||||
testConfig, err := tweakConfigForTests(ConfigShContents)
|
||||
@ -788,7 +805,7 @@ func configureBashrc(homedir, binaryPath string) error {
|
||||
}
|
||||
configContents = testConfig
|
||||
}
|
||||
err := ioutil.WriteFile(bashConfigPath, []byte(configContents), 0o644)
|
||||
err := ioutil.WriteFile(getBashConfigPath(homedir), []byte(configContents), 0o644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write config.sh file: %v", err)
|
||||
}
|
||||
@ -806,13 +823,17 @@ func configureBashrc(homedir, binaryPath string) error {
|
||||
return fmt.Errorf("failed to append to bashrc: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
_, err = f.WriteString("\n# Hishtory Config:\nexport PATH=\"$PATH:" + path.Join(homedir, data.HISHTORY_PATH) + "\"\nsource " + bashConfigPath + "\n")
|
||||
_, err = f.WriteString(getBashConfigFragment(homedir))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to append to bashrc: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getBashConfigFragment(homedir string) string {
|
||||
return "\n# Hishtory Config:\nexport PATH=\"$PATH:" + path.Join(homedir, data.HISHTORY_PATH) + "\"\nsource " + getBashConfigPath(homedir) + "\n"
|
||||
}
|
||||
|
||||
func isBashConfigured(homedir string) (bool, error) {
|
||||
_, err := os.Stat(path.Join(homedir, ".bashrc"))
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
@ -1551,3 +1572,46 @@ func tokenize(query string) ([]string, error) {
|
||||
}
|
||||
return strings.Split(query, " "), nil
|
||||
}
|
||||
|
||||
func stripLines(filePath, lines string) error {
|
||||
origContents, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
linesToBeRemoved := make(map[string]bool, 0)
|
||||
for _, line := range strings.Split(lines, "\n") {
|
||||
if strings.TrimSpace(line) != "" {
|
||||
linesToBeRemoved[line] = true
|
||||
}
|
||||
}
|
||||
ret := ""
|
||||
for _, line := range strings.Split(string(origContents), "\n") {
|
||||
if !linesToBeRemoved[line] {
|
||||
ret += line
|
||||
ret += "\n"
|
||||
}
|
||||
}
|
||||
return os.WriteFile(filePath, []byte(ret), 0644)
|
||||
}
|
||||
|
||||
func Uninstall(ctx *context.Context) error {
|
||||
homedir := hctx.GetHome(ctx)
|
||||
err := stripLines(path.Join(homedir, ".bashrc"), getBashConfigFragment(homedir))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = stripLines(path.Join(homedir, ".zshrc"), getZshConfigFragment(homedir))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = stripLines(path.Join(homedir, ".config/fish/config.fish"), getFishConfigFragment(homedir))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.RemoveAll(path.Join(homedir, ".hishtory"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("Successfully uninstalled hishtory, please restart your terminal...")
|
||||
return nil
|
||||
}
|
||||
|
10
hishtory.go
10
hishtory.go
@ -87,6 +87,16 @@ func main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
case "uninstall":
|
||||
fmt.Printf("Are you sure you want to uninstall hiSHtory and delete all locally saved history data [y/N]")
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
resp, err := reader.ReadString('\n')
|
||||
lib.CheckFatalError(err)
|
||||
if strings.TrimSpace(resp) != "y" {
|
||||
fmt.Printf("Aborting uninstall per user response of %#v\n", strings.TrimSpace(resp))
|
||||
return
|
||||
}
|
||||
lib.CheckFatalError(lib.Uninstall(hctx.MakeContext()))
|
||||
case "import":
|
||||
ctx := hctx.MakeContext()
|
||||
numImported, err := lib.ImportHistory(ctx, true)
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -43,17 +42,8 @@ func BackupAndRestore(t *testing.T) func() {
|
||||
return BackupAndRestoreWithId(t, "")
|
||||
}
|
||||
|
||||
func DeleteBakFiles(t *testing.T) {
|
||||
homedir, err := os.UserHomeDir()
|
||||
checkError(err)
|
||||
entries, err := ioutil.ReadDir(path.Join(homedir, data.HISHTORY_PATH))
|
||||
checkError(err)
|
||||
for _, entry := range entries {
|
||||
fmt.Println(entry.Name())
|
||||
if strings.HasSuffix(entry.Name(), ".bak") {
|
||||
checkError(os.Remove(path.Join(homedir, data.HISHTORY_PATH, entry.Name())))
|
||||
}
|
||||
}
|
||||
func getBackPath(file, id string) string {
|
||||
return strings.Replace(file, data.HISHTORY_PATH, data.HISHTORY_PATH+".test", 1) + id
|
||||
}
|
||||
|
||||
func BackupAndRestoreWithId(t *testing.T, id string) func() {
|
||||
@ -62,6 +52,7 @@ func BackupAndRestoreWithId(t *testing.T, id string) func() {
|
||||
Check(t, err)
|
||||
initialWd, err := os.Getwd()
|
||||
Check(t, err)
|
||||
Check(t, os.MkdirAll(path.Join(homedir, data.HISHTORY_PATH+".test"), os.ModePerm))
|
||||
|
||||
renameFiles := []string{
|
||||
path.Join(homedir, data.HISHTORY_PATH, data.DB_PATH),
|
||||
@ -77,7 +68,7 @@ func BackupAndRestoreWithId(t *testing.T, id string) func() {
|
||||
}
|
||||
for _, file := range renameFiles {
|
||||
touchFile(file)
|
||||
_ = os.Rename(file, file+id+".bak")
|
||||
_ = os.Rename(file, getBackPath(file, id))
|
||||
}
|
||||
copyFiles := []string{
|
||||
path.Join(homedir, ".zshrc"),
|
||||
@ -85,17 +76,18 @@ func BackupAndRestoreWithId(t *testing.T, id string) func() {
|
||||
}
|
||||
for _, file := range copyFiles {
|
||||
touchFile(file)
|
||||
_ = copy(file, file+id+".bak")
|
||||
_ = copy(file, getBackPath(file, id))
|
||||
}
|
||||
configureZshrc(homedir)
|
||||
touchFile(path.Join(homedir, ".bash_history"))
|
||||
touchFile(path.Join(homedir, ".zsh_history"))
|
||||
return func() {
|
||||
Check(t, os.MkdirAll(path.Join(homedir, data.HISHTORY_PATH), os.ModePerm))
|
||||
for _, file := range renameFiles {
|
||||
checkError(os.Rename(file+id+".bak", file))
|
||||
checkError(os.Rename(getBackPath(file, id), file))
|
||||
}
|
||||
for _, file := range copyFiles {
|
||||
checkError(copy(file+id+".bak", file))
|
||||
checkError(copy(getBackPath(file, id), file))
|
||||
}
|
||||
cmd := exec.Command("killall", "hishtory")
|
||||
stdout, err := cmd.Output()
|
||||
|
Loading…
Reference in New Issue
Block a user