Untested: ctx wired through

This commit is contained in:
David Dworken 2022-09-20 22:28:40 -07:00
parent e47bcfc993
commit 694c2e2679
5 changed files with 115 additions and 195 deletions

View File

@ -18,8 +18,8 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/google/uuid"
"github.com/ddworken/hishtory/client/ctx"
"github.com/ddworken/hishtory/client/data"
"github.com/ddworken/hishtory/client/hctx"
"github.com/ddworken/hishtory/client/lib"
"github.com/ddworken/hishtory/shared"
)
@ -959,10 +959,7 @@ func testRequestAndReceiveDbDump(t *testing.T, tester shellTester) {
secretKey := installHishtory(t, tester, "")
// Confirm there are no pending dump requests
config, err := ctx.GetConfig()
if err != nil {
t.Fatal(err)
}
config := hctx.GetConf(hctx.MakeContext())
deviceId1 := config.DeviceId
resp, err := lib.ApiGet("/api/v1/get-dump-requests?user_id=" + data.UserId(secretKey) + "&device_id=" + deviceId1)
if err != nil {

View File

@ -1,4 +1,4 @@
package ctx
package hctx
import (
"context"
@ -77,7 +77,7 @@ func OpenLocalSqliteDb() (*gorm.DB, error) {
type hishtoryContextKey string
func MakeContext() context.Context {
func MakeContext() *context.Context {
ctx := context.Background()
config, err := GetConfig()
if err != nil {
@ -89,11 +89,20 @@ func MakeContext() context.Context {
GetLogger().Fatalf("failed to open local DB: %v", err)
}
ctx = context.WithValue(ctx, hishtoryContextKey("db"), db)
return ctx
return &ctx
}
func GetDbFromContext(ctx context.Context) *gorm.DB {
v := ctx.Value(hishtoryContextKey("db"))
func GetConf(ctx *context.Context) ClientConfig {
v := (*ctx).Value(hishtoryContextKey("config"))
if v != nil {
return v.(ClientConfig)
}
GetLogger().Fatalf("failed to find config in ctx")
return ClientConfig{}
}
func GetDb(ctx *context.Context) *gorm.DB {
v := (*ctx).Value(hishtoryContextKey("db"))
if v != nil {
return v.(*gorm.DB)
}

View File

@ -3,6 +3,7 @@ package lib
import (
"bufio"
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
@ -32,8 +33,8 @@ import (
"github.com/google/uuid"
"github.com/rodaine/table"
"github.com/ddworken/hishtory/client/ctx"
"github.com/ddworken/hishtory/client/data"
"github.com/ddworken/hishtory/client/hctx"
"github.com/ddworken/hishtory/shared"
)
@ -72,9 +73,9 @@ func getCwd() (string, string, error) {
return cwd, homedir, nil
}
func BuildHistoryEntry(args []string) (*data.HistoryEntry, error) {
func BuildHistoryEntry(ctx *context.Context, args []string) (*data.HistoryEntry, error) {
if len(args) < 6 {
ctx.GetLogger().Printf("BuildHistoryEntry called with args=%#v, which has too few entries! This can happen in specific edge cases for newly opened terminals and is likely not a problem.", args)
hctx.GetLogger().Printf("BuildHistoryEntry called with args=%#v, which has too few entries! This can happen in specific edge cases for newly opened terminals and is likely not a problem.", args)
return nil, nil
}
shell := args[2]
@ -119,7 +120,7 @@ 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[4])
shouldBeSkipped, err := shouldSkipHiddenCommand(ctx, args[4])
if err != nil {
return nil, fmt.Errorf("failed to check if command was hidden: %v", err)
}
@ -151,10 +152,7 @@ func BuildHistoryEntry(args []string) (*data.HistoryEntry, error) {
entry.Hostname = hostname
// device ID
config, err := ctx.GetConfig()
if err != nil {
return nil, fmt.Errorf("failed to get device ID when building history entry: %v", err)
}
config := hctx.GetConf(ctx)
entry.DeviceId = config.DeviceId
return &entry, nil
@ -263,31 +261,20 @@ func getLastCommand(history string) (string, error) {
return strings.SplitN(strings.SplitN(strings.TrimSpace(history), " ", 2)[1], " ", 2)[1], nil
}
func shouldSkipHiddenCommand(historyLine string) (bool, error) {
config, err := ctx.GetConfig()
if err != nil {
return false, err
}
func shouldSkipHiddenCommand(ctx *context.Context, historyLine string) (bool, error) {
config := hctx.GetConf(ctx)
if config.LastSavedHistoryLine == historyLine {
return true, nil
}
config.LastSavedHistoryLine = historyLine
err = ctx.SetConfig(config)
err := hctx.SetConfig(config)
if err != nil {
return false, err
}
return false, nil
}
func GetUserSecret() (string, error) {
config, err := ctx.GetConfig()
if err != nil {
return "", err
}
return config.UserSecret, nil
}
func Setup(args []string) error {
func Setup(ctx *context.Context, args []string) error {
userSecret := uuid.Must(uuid.NewRandom()).String()
if len(args) > 2 && args[2] != "" {
userSecret = args[2]
@ -295,20 +282,17 @@ func Setup(args []string) error {
fmt.Println("Setting secret hishtory key to " + string(userSecret))
// Create and set the config
var config ctx.ClientConfig
var config hctx.ClientConfig
config.UserSecret = userSecret
config.IsEnabled = true
config.DeviceId = uuid.Must(uuid.NewRandom()).String()
err := ctx.SetConfig(config)
err := hctx.SetConfig(config)
if err != nil {
return fmt.Errorf("failed to persist config to disk: %v", err)
}
// Drop all existing data
db, err := ctx.OpenLocalSqliteDb()
if err != nil {
return fmt.Errorf("failed to open DB: %v", err)
}
db := hctx.GetDb(ctx)
db.Exec("DELETE FROM history_entries")
// Bootstrap from remote date
@ -367,30 +351,20 @@ func DisplayResults(results []*data.HistoryEntry) {
tbl.Print()
}
func IsEnabled() (bool, error) {
config, err := ctx.GetConfig()
if err != nil {
return false, err
}
return config.IsEnabled, nil
func IsEnabled(ctx *context.Context) (bool, error) {
return hctx.GetConf(ctx).IsEnabled, nil
}
func Enable() error {
config, err := ctx.GetConfig()
if err != nil {
return err
}
func Enable(ctx *context.Context) error {
config := hctx.GetConf(ctx)
config.IsEnabled = true
return ctx.SetConfig(config)
return hctx.SetConfig(config)
}
func Disable() error {
config, err := ctx.GetConfig()
if err != nil {
return err
}
func Disable(ctx *context.Context) error {
config := hctx.GetConf(ctx)
config.IsEnabled = false
return ctx.SetConfig(config)
return hctx.SetConfig(config)
}
func CheckFatalError(err error) {
@ -400,11 +374,8 @@ func CheckFatalError(err error) {
}
}
func ImportHistory() (int, error) {
config, err := ctx.GetConfig()
if err != nil {
return 0, err
}
func ImportHistory(ctx *context.Context) (int, error) {
config := hctx.GetConf(ctx)
if config.HaveCompletedInitialImport {
// Don't run an import if we already have run one. This avoids importing the same entry multiple times.
return 0, nil
@ -422,10 +393,7 @@ func ImportHistory() (int, error) {
return 0, fmt.Errorf("failed to parse zsh history: %v", err)
}
historyEntries = append(historyEntries, extraEntries...)
db, err := ctx.OpenLocalSqliteDb()
if err != nil {
return 0, nil
}
db := hctx.GetDb(ctx)
currentUser, err := user.Current()
if err != nil {
return 0, err
@ -453,7 +421,7 @@ func ImportHistory() (int, error) {
}
}
config.HaveCompletedInitialImport = true
err = ctx.SetConfig(config)
err = hctx.SetConfig(config)
if err != nil {
return 0, fmt.Errorf("failed to mark initial import as completed, this may lead to duplicate history entries: %v", err)
}
@ -497,7 +465,7 @@ func parseZshHistory(homedir string) ([]string, error) {
return readFileToArray(histfile)
}
func Install() error {
func Install(ctx *context.Context) error {
homedir, err := os.UserHomeDir()
if err != nil {
return fmt.Errorf("failed to get user's home directory: %v", err)
@ -519,10 +487,10 @@ func Install() error {
if err != nil {
return err
}
_, err = ctx.GetConfig()
_, err = hctx.GetConfig()
if err != nil {
// No config, so set up a new installation
return Setup(os.Args)
return Setup(ctx, os.Args)
}
return nil
}
@ -798,7 +766,7 @@ func assertIdenticalBinaries(bin1Path, bin2Path string) error {
differences = append(differences, fmt.Sprintf("diff at index %d: %s[%d]=%x, %s[%d]=%x", i, bin1Path, i, b1, bin2Path, i, b2))
}
}
logger := ctx.GetLogger()
logger := hctx.GetLogger()
for _, d := range differences {
logger.Printf("comparing binaries: %#v\n", d)
}
@ -907,7 +875,7 @@ func ApiGet(path string) ([]byte, error) {
return nil, fmt.Errorf("failed to read response body from GET %s%s: %v", getServerHostname(), path, err)
}
duration := time.Since(start)
ctx.GetLogger().Printf("ApiGet(%#v): %s\n", path, duration.String())
hctx.GetLogger().Printf("ApiGet(%#v): %s\n", path, duration.String())
return respBody, nil
}
@ -929,7 +897,7 @@ func ApiPost(path, contentType string, data []byte) ([]byte, error) {
return nil, fmt.Errorf("failed to read response body from POST %s: %v", path, err)
}
duration := time.Since(start)
ctx.GetLogger().Printf("ApiPost(%#v): %s\n", path, duration.String())
hctx.GetLogger().Printf("ApiPost(%#v): %s\n", path, duration.String())
return respBody, nil
}
@ -968,7 +936,7 @@ func ReliableDbCreate(db *gorm.DB, entry interface{}) error {
return fmt.Errorf("failed to create DB entry even with %d retries: %v", i, err)
}
func EncryptAndMarshal(config ctx.ClientConfig, entry *data.HistoryEntry) ([]byte, error) {
func EncryptAndMarshal(config hctx.ClientConfig, entry *data.HistoryEntry) ([]byte, error) {
encEntry, err := data.EncryptHistoryEntry(config.UserSecret, *entry)
if err != nil {
return nil, fmt.Errorf("failed to encrypt history entry")
@ -981,8 +949,8 @@ func EncryptAndMarshal(config ctx.ClientConfig, entry *data.HistoryEntry) ([]byt
return jsonValue, nil
}
func Redact(db *gorm.DB, query string, force bool) error {
tx, err := data.MakeWhereQueryFromSearch(db, query)
func Redact(ctx *context.Context, query string, force bool) error {
tx, err := data.MakeWhereQueryFromSearch(hctx.GetDb(ctx), query)
if err != nil {
return err
}
@ -1006,7 +974,7 @@ func Redact(db *gorm.DB, query string, force bool) error {
return nil
}
}
tx, err = data.MakeWhereQueryFromSearch(db, query)
tx, err = data.MakeWhereQueryFromSearch(hctx.GetDb(ctx), query)
if err != nil {
return err
}
@ -1017,18 +985,15 @@ func Redact(db *gorm.DB, query string, force bool) error {
if res.RowsAffected != int64(len(historyEntries)) {
return fmt.Errorf("DB deleted %d rows, when we only expected to delete %d rows, something may have gone wrong", res.RowsAffected, len(historyEntries))
}
err = deleteOnRemoteInstances(historyEntries)
err = deleteOnRemoteInstances(ctx, historyEntries)
if err != nil {
return err
}
return nil
}
func deleteOnRemoteInstances(historyEntries []*data.HistoryEntry) error {
config, err := ctx.GetConfig()
if err != nil {
return err
}
func deleteOnRemoteInstances(ctx *context.Context, historyEntries []*data.HistoryEntry) error {
config := hctx.GetConf(ctx)
var deletionRequest shared.DeletionRequest
deletionRequest.SendTime = time.Now()

View File

@ -8,8 +8,8 @@ import (
"testing"
"time"
"github.com/ddworken/hishtory/client/ctx"
"github.com/ddworken/hishtory/client/data"
"github.com/ddworken/hishtory/client/hctx"
"github.com/ddworken/hishtory/shared"
)
@ -21,7 +21,7 @@ func TestSetup(t *testing.T) {
if _, err := os.Stat(path.Join(homedir, shared.HISHTORY_PATH, shared.CONFIG_PATH)); err == nil {
t.Fatalf("hishtory secret file already exists!")
}
shared.Check(t, Setup([]string{}))
shared.Check(t, Setup(hctx.MakeContext(), []string{}))
if _, err := os.Stat(path.Join(homedir, shared.HISHTORY_PATH, shared.CONFIG_PATH)); err != nil {
t.Fatalf("hishtory secret file does not exist after Setup()!")
}
@ -35,10 +35,10 @@ func TestSetup(t *testing.T) {
func TestBuildHistoryEntry(t *testing.T) {
defer shared.BackupAndRestore(t)()
defer shared.RunTestServer()()
shared.Check(t, Setup([]string{}))
shared.Check(t, Setup(hctx.MakeContext(), []string{}))
// Test building an actual entry for bash
entry, err := BuildHistoryEntry([]string{"unused", "saveHistoryEntry", "bash", "120", " 123 ls /foo ", "1641774958"})
entry, err := BuildHistoryEntry(hctx.MakeContext(), []string{"unused", "saveHistoryEntry", "bash", "120", " 123 ls /foo ", "1641774958"})
shared.Check(t, err)
if entry.ExitCode != 120 {
t.Fatalf("history entry has unexpected exit code: %v", entry.ExitCode)
@ -67,7 +67,7 @@ func TestBuildHistoryEntry(t *testing.T) {
}
// Test building an entry for zsh
entry, err = BuildHistoryEntry([]string{"unused", "saveHistoryEntry", "zsh", "120", "ls /foo\n", "1641774958"})
entry, err = BuildHistoryEntry(hctx.MakeContext(), []string{"unused", "saveHistoryEntry", "zsh", "120", "ls /foo\n", "1641774958"})
shared.Check(t, err)
if entry.ExitCode != 120 {
t.Fatalf("history entry has unexpected exit code: %v", entry.ExitCode)
@ -92,29 +92,9 @@ func TestBuildHistoryEntry(t *testing.T) {
}
}
func TestGetUserSecret(t *testing.T) {
defer shared.BackupAndRestore(t)()
defer shared.RunTestServer()()
shared.Check(t, Setup([]string{}))
secret1, err := GetUserSecret()
shared.Check(t, err)
if len(secret1) < 10 || strings.Contains(secret1, " ") || strings.Contains(secret1, "\n") {
t.Fatalf("unexpected secret: %v", secret1)
}
shared.Check(t, Setup([]string{}))
secret2, err := GetUserSecret()
shared.Check(t, err)
if secret1 == secret2 {
t.Fatalf("GetUserSecret() returned the same values for different setups! val=%v", secret1)
}
}
func TestPersist(t *testing.T) {
defer shared.BackupAndRestore(t)()
db, err := ctx.OpenLocalSqliteDb()
shared.Check(t, err)
db := hctx.GetDb(hctx.MakeContext())
entry := data.MakeFakeHistoryEntry("ls ~/")
db.Create(entry)
@ -132,8 +112,7 @@ func TestPersist(t *testing.T) {
func TestSearch(t *testing.T) {
defer shared.BackupAndRestore(t)()
db, err := ctx.OpenLocalSqliteDb()
shared.Check(t, err)
db := hctx.GetDb(hctx.MakeContext())
// Insert data
entry1 := data.MakeFakeHistoryEntry("ls /foo")
@ -158,8 +137,7 @@ func TestSearch(t *testing.T) {
func TestAddToDbIfNew(t *testing.T) {
// Set up
defer shared.BackupAndRestore(t)()
db, err := ctx.OpenLocalSqliteDb()
shared.Check(t, err)
db := hctx.GetDb(hctx.MakeContext())
// Add duplicate entries
entry1 := data.MakeFakeHistoryEntry("ls /foo")

View File

@ -1,15 +1,15 @@
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"os"
"strings"
"time"
"github.com/ddworken/hishtory/client/ctx"
"github.com/ddworken/hishtory/client/data"
"github.com/ddworken/hishtory/client/hctx"
"github.com/ddworken/hishtory/client/lib"
"github.com/ddworken/hishtory/shared"
)
@ -21,37 +21,36 @@ func main() {
fmt.Println("Must specify a command! Do you mean `hishtory query`?")
return
}
ctx := hctx.MakeContext()
switch os.Args[1] {
case "saveHistoryEntry":
lib.CheckFatalError(maybeUploadSkippedHistoryEntries())
saveHistoryEntry()
lib.CheckFatalError(processDeletionRequests())
lib.CheckFatalError(maybeUploadSkippedHistoryEntries(ctx))
saveHistoryEntry(ctx)
lib.CheckFatalError(processDeletionRequests(ctx))
case "query":
lib.CheckFatalError(processDeletionRequests())
query(strings.Join(os.Args[2:], " "))
lib.CheckFatalError(processDeletionRequests(ctx))
query(ctx, strings.Join(os.Args[2:], " "))
case "export":
lib.CheckFatalError(processDeletionRequests())
export(strings.Join(os.Args[2:], " "))
lib.CheckFatalError(processDeletionRequests(ctx))
export(ctx, strings.Join(os.Args[2:], " "))
case "redact":
fallthrough
case "delete":
lib.CheckFatalError(retrieveAdditionalEntriesFromRemote())
lib.CheckFatalError(processDeletionRequests())
db, err := ctx.OpenLocalSqliteDb()
lib.CheckFatalError(err)
lib.CheckFatalError(retrieveAdditionalEntriesFromRemote(ctx))
lib.CheckFatalError(processDeletionRequests(ctx))
query := strings.Join(os.Args[2:], " ")
force := false
if os.Args[2] == "--force" {
query = strings.Join(os.Args[3:], " ")
force = true
}
lib.CheckFatalError(lib.Redact(db, query, force))
lib.CheckFatalError(lib.Redact(ctx, query, force))
case "init":
lib.CheckFatalError(lib.Setup(os.Args))
lib.CheckFatalError(lib.Setup(ctx, os.Args))
case "install":
lib.CheckFatalError(lib.Install())
lib.CheckFatalError(lib.Install(ctx))
if os.Getenv("HISHTORY_TEST") == "" {
numImported, err := lib.ImportHistory()
numImported, err := lib.ImportHistory(ctx)
lib.CheckFatalError(err)
if numImported > 0 {
fmt.Printf("Imported %v history entries from your existing shell history", numImported)
@ -61,20 +60,19 @@ func main() {
if os.Getenv("HISHTORY_TEST") == "" {
lib.CheckFatalError(fmt.Errorf("the hishtory import command is only meant to be for testing purposes"))
}
numImported, err := lib.ImportHistory()
numImported, err := lib.ImportHistory(ctx)
lib.CheckFatalError(err)
if numImported > 0 {
fmt.Printf("Imported %v history entries from your existing shell history", numImported)
}
case "enable":
lib.CheckFatalError(lib.Enable())
lib.CheckFatalError(lib.Enable(ctx))
case "disable":
lib.CheckFatalError(lib.Disable())
lib.CheckFatalError(lib.Disable(ctx))
case "version":
fallthrough
case "status":
config, err := ctx.GetConfig()
lib.CheckFatalError(err)
config := hctx.GetConf(ctx)
fmt.Printf("Hishtory: v0.%s\nEnabled: %v\n", lib.Version, config.IsEnabled)
fmt.Printf("Secret Key: %s\n", config.UserSecret)
if len(os.Args) == 3 && os.Args[2] == "-v" {
@ -117,7 +115,7 @@ Supported commands:
}
}
func printDumpStatus(config ctx.ClientConfig) {
func printDumpStatus(config hctx.ClientConfig) {
dumpRequests, err := getDumpRequests(config)
lib.CheckFatalError(err)
fmt.Printf("Dump Requests: ")
@ -127,7 +125,7 @@ func printDumpStatus(config ctx.ClientConfig) {
fmt.Print("\n")
}
func getDumpRequests(config ctx.ClientConfig) ([]*shared.DumpRequest, error) {
func getDumpRequests(config hctx.ClientConfig) ([]*shared.DumpRequest, error) {
resp, err := lib.ApiGet("/api/v1/get-dump-requests?user_id=" + data.UserId(config.UserSecret) + "&device_id=" + config.DeviceId)
if lib.IsOfflineError(err) {
return []*shared.DumpRequest{}, nil
@ -140,11 +138,8 @@ func getDumpRequests(config ctx.ClientConfig) ([]*shared.DumpRequest, error) {
return dumpRequests, err
}
func processDeletionRequests() error {
config, err := ctx.GetConfig()
if err != nil {
return err
}
func processDeletionRequests(ctx *context.Context) error {
config := hctx.GetConf(ctx)
resp, err := lib.ApiGet("/api/v1/get-deletion-requests?user_id=" + data.UserId(config.UserSecret) + "&device_id=" + config.DeviceId)
if lib.IsOfflineError(err) {
@ -158,10 +153,7 @@ func processDeletionRequests() error {
if err != nil {
return err
}
db, err := ctx.OpenLocalSqliteDb()
if err != nil {
return err
}
db := hctx.GetDb(ctx)
for _, request := range deletionRequests {
for _, entry := range request.Messages.Ids {
res := db.Where("device_id = ? AND end_time = ?", entry.DeviceId, entry.Date).Delete(&data.HistoryEntry{})
@ -173,15 +165,9 @@ func processDeletionRequests() error {
return nil
}
func retrieveAdditionalEntriesFromRemote() error {
db, err := ctx.OpenLocalSqliteDb()
if err != nil {
return err
}
config, err := ctx.GetConfig()
if err != nil {
return err
}
func retrieveAdditionalEntriesFromRemote(ctx *context.Context) error {
db := hctx.GetDb(ctx)
config := hctx.GetConf(ctx)
respBody, err := lib.ApiGet("/api/v1/query?device_id=" + config.DeviceId + "&user_id=" + data.UserId(config.UserSecret))
if lib.IsOfflineError(err) {
return nil
@ -201,13 +187,12 @@ func retrieveAdditionalEntriesFromRemote() error {
}
lib.AddToDbIfNew(db, decEntry)
}
return processDeletionRequests()
return processDeletionRequests(ctx)
}
func query(query string) {
db, err := ctx.OpenLocalSqliteDb()
lib.CheckFatalError(err)
err = retrieveAdditionalEntriesFromRemote()
func query(ctx *context.Context, query string) {
db := hctx.GetDb(ctx)
err := retrieveAdditionalEntriesFromRemote(ctx)
if err != nil {
if lib.IsOfflineError(err) {
fmt.Println("Warning: hishtory is offline so this may be missing recent results from your other machines!")
@ -215,17 +200,14 @@ func query(query string) {
lib.CheckFatalError(err)
}
}
lib.CheckFatalError(displayBannerIfSet())
lib.CheckFatalError(displayBannerIfSet(ctx))
data, err := data.Search(db, query, 25)
lib.CheckFatalError(err)
lib.DisplayResults(data)
}
func displayBannerIfSet() error {
config, err := ctx.GetConfig()
if err != nil {
return fmt.Errorf("failed to get config: %v", err)
}
func displayBannerIfSet(ctx *context.Context) error {
config := hctx.GetConf(ctx)
url := "/api/v1/banner?commit_hash=" + GitCommit + "&user_id=" + data.UserId(config.UserSecret) + "&device_id=" + config.DeviceId + "&version=" + lib.Version + "&forced_banner=" + os.Getenv("FORCED_BANNER")
respBody, err := lib.ApiGet(url)
if lib.IsOfflineError(err) {
@ -240,26 +222,20 @@ func displayBannerIfSet() error {
return nil
}
func maybeUploadSkippedHistoryEntries() error {
config, err := ctx.GetConfig()
if err != nil {
return err
}
func maybeUploadSkippedHistoryEntries(ctx *context.Context) error {
config := hctx.GetConf(ctx)
if !config.HaveMissedUploads {
return nil
}
// Upload the missing entries
db, err := ctx.OpenLocalSqliteDb()
if err != nil {
return nil
}
db := hctx.GetDb(ctx)
query := fmt.Sprintf("after:%s", time.Unix(config.MissedUploadTimestamp, 0).Format("2006-01-02"))
entries, err := data.Search(db, query, 0)
if err != nil {
return fmt.Errorf("failed to retrieve history entries that haven't been uploaded yet: %v", err)
}
ctx.GetLogger().Printf("Uploading %d history entries that previously failed to upload (query=%#v)\n", len(entries), query)
hctx.GetLogger().Printf("Uploading %d history entries that previously failed to upload (query=%#v)\n", len(entries), query)
for _, entry := range entries {
jsonValue, err := lib.EncryptAndMarshal(config, entry)
if err != nil {
@ -275,32 +251,28 @@ func maybeUploadSkippedHistoryEntries() error {
// Mark down that we persisted it
config.HaveMissedUploads = false
config.MissedUploadTimestamp = 0
err = ctx.SetConfig(config)
err = hctx.SetConfig(config)
if err != nil {
return fmt.Errorf("failed to mark a history entry as uploaded: %v", err)
}
return nil
}
func saveHistoryEntry() {
config, err := ctx.GetConfig()
if err != nil {
log.Fatalf("hishtory cannot save an entry because the hishtory config file does not exist, try running `hishtory init` (err=%v)", err)
}
func saveHistoryEntry(ctx *context.Context) {
config := hctx.GetConf(ctx)
if !config.IsEnabled {
ctx.GetLogger().Printf("Skipping saving a history entry because hishtory is disabled\n")
hctx.GetLogger().Printf("Skipping saving a history entry because hishtory is disabled\n")
return
}
entry, err := lib.BuildHistoryEntry(os.Args)
entry, err := lib.BuildHistoryEntry(ctx, os.Args)
lib.CheckFatalError(err)
if entry == nil {
ctx.GetLogger().Printf("Skipping saving a history entry because we failed to build a history entry (was the command prefixed with a space?)\n")
hctx.GetLogger().Printf("Skipping saving a history entry because we failed to build a history entry (was the command prefixed with a space?)\n")
return
}
// Persist it locally
db, err := ctx.OpenLocalSqliteDb()
lib.CheckFatalError(err)
db := hctx.GetDb(ctx)
err = lib.ReliableDbCreate(db, entry)
lib.CheckFatalError(err)
@ -310,11 +282,11 @@ func saveHistoryEntry() {
_, err = lib.ApiPost("/api/v1/submit", "application/json", jsonValue)
if err != nil {
if lib.IsOfflineError(err) {
ctx.GetLogger().Printf("Failed to remotely persist hishtory entry because the device is offline!")
hctx.GetLogger().Printf("Failed to remotely persist hishtory entry because the device is offline!")
if !config.HaveMissedUploads {
config.HaveMissedUploads = true
config.MissedUploadTimestamp = time.Now().Unix()
lib.CheckFatalError(ctx.SetConfig(config))
lib.CheckFatalError(hctx.SetConfig(config))
}
} else {
lib.CheckFatalError(err)
@ -327,13 +299,13 @@ func saveHistoryEntry() {
if lib.IsOfflineError(err) {
// It is fine to just ignore this, the next command will retry the API and eventually we will respond to any pending dump requests
dumpRequests = []*shared.DumpRequest{}
ctx.GetLogger().Printf("Failed to check for dump requests because the device is offline!")
hctx.GetLogger().Printf("Failed to check for dump requests because the device is offline!")
} else {
lib.CheckFatalError(err)
}
}
if len(dumpRequests) > 0 {
lib.CheckFatalError(retrieveAdditionalEntriesFromRemote())
lib.CheckFatalError(retrieveAdditionalEntriesFromRemote(ctx))
entries, err := data.Search(db, "", 0)
lib.CheckFatalError(err)
var encEntries []*shared.EncHistoryEntry
@ -351,10 +323,9 @@ func saveHistoryEntry() {
}
}
func export(query string) {
db, err := ctx.OpenLocalSqliteDb()
lib.CheckFatalError(err)
err = retrieveAdditionalEntriesFromRemote()
func export(ctx *context.Context, query string) {
db := hctx.GetDb(ctx)
err := retrieveAdditionalEntriesFromRemote(ctx)
if err != nil {
if lib.IsOfflineError(err) {
fmt.Println("Warning: hishtory is offline so this may be missing recent results from your other machines!")