From 0c6ce3c8e9c1126a7a410a637363556640caacfd Mon Sep 17 00:00:00 2001 From: Simon Let Date: Tue, 18 Oct 2022 02:24:24 +0200 Subject: [PATCH] get resh to compile and run --- .goreleaser.yml | 9 + Makefile | 2 +- cmd/cli/main.go | 10 +- cmd/collect/main.go | 180 +++----------- cmd/daemon/dump.go | 2 +- cmd/daemon/main.go | 8 +- cmd/daemon/record.go | 16 +- cmd/daemon/run-server.go | 12 +- cmd/daemon/session-init.go | 14 +- cmd/install-utils/main.go | 4 +- cmd/postcollect/main.go | 113 ++------- cmd/session-init/main.go | 145 +---------- go.mod | 1 - go.sum | 2 - internal/cfg/cfg.go | 1 + internal/collect/collect.go | 33 ++- internal/histcli/histcli.go | 11 +- internal/histfile/histfile.go | 127 +++++----- internal/msg/msg.go | 4 +- internal/output/output.go | 20 +- internal/recconv/recconv.go | 28 ++- internal/recio/read.go | 2 +- internal/recio/write.go | 38 ++- internal/record/v1.go | 10 +- internal/recordint/collect.go | 13 + internal/recordint/enriched.go | 51 ---- internal/recordint/searchapp.go | 53 +++- internal/records/records.go | 256 -------------------- internal/records/records_test.go | 85 ------- internal/records/testdata/resh_history.json | 27 --- internal/recutil/recutil.go | 109 +++------ internal/searchapp/item.go | 22 +- internal/searchapp/test.go | 12 +- internal/sesswatch/sesswatch.go | 26 +- scripts/hooks.sh | 75 +----- scripts/install.sh | 5 +- scripts/reshctl.sh | 4 +- scripts/shellrc.sh | 3 +- scripts/util.sh | 42 +--- scripts/widgets.sh | 6 +- 40 files changed, 447 insertions(+), 1134 deletions(-) delete mode 100644 internal/recordint/enriched.go delete mode 100644 internal/records/records_test.go delete mode 100644 internal/records/testdata/resh_history.json diff --git a/.goreleaser.yml b/.goreleaser.yml index c2e2bf5..4cc663d 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -102,6 +102,15 @@ builds: - amd64 - arm - arm64 + - + id: "install-utils" + main: ./cmd/install-utils + binary: bin/resh-install-utils + goarch: + - 386 + - amd64 + - arm + - arm64 # signs: # - artifacts: checksum diff --git a/Makefile b/Makefile index 249cd43..e5b5c87 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ GOFLAGS=-ldflags "-X main.version=${VERSION} -X main.commit=${COMMIT} -X main.de build: submodules bin/resh-session-init bin/resh-collect bin/resh-postcollect\ bin/resh-daemon bin/resh-control bin/resh-config bin/resh-cli\ - bin/installutil + bin/resh-install-utils install: build scripts/install.sh diff --git a/cmd/cli/main.go b/cmd/cli/main.go index fbd0219..5d588f9 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -19,7 +19,7 @@ import ( "github.com/curusarn/resh/internal/logger" "github.com/curusarn/resh/internal/msg" "github.com/curusarn/resh/internal/output" - "github.com/curusarn/resh/internal/records" + "github.com/curusarn/resh/internal/recordint" "github.com/curusarn/resh/internal/searchapp" "go.uber.org/zap" @@ -96,7 +96,7 @@ func runReshCli(out *output.Output, config cfg.Config) (string, int) { st := state{ // lock sync.Mutex - cliRecords: resp.CliRecords, + cliRecords: resp.Records, initialQuery: *query, } @@ -106,7 +106,7 @@ func runReshCli(out *output.Output, config cfg.Config) (string, int) { sessionID: *sessionID, host: *host, pwd: *pwd, - gitOriginRemote: records.NormalizeGitRemote(*gitOriginRemote), + gitOriginRemote: *gitOriginRemote, s: &st, } g.SetManager(layout) @@ -159,7 +159,7 @@ func runReshCli(out *output.Output, config cfg.Config) (string, int) { type state struct { lock sync.Mutex - cliRecords []records.CliRecord + cliRecords []recordint.SearchApp data []searchapp.Item rawData []searchapp.RawItem highlightedItem int @@ -600,7 +600,7 @@ func SendCliMsg(out *output.Output, m msg.CliMsg, port string) msg.CliResponse { out.Fatal("Failed decode response", err) } sugar.Debugw("Recieved records from daemon", - "recordCount", len(response.CliRecords), + "recordCount", len(response.Records), ) return response } diff --git a/cmd/collect/main.go b/cmd/collect/main.go index aac282c..7f19e0a 100644 --- a/cmd/collect/main.go +++ b/cmd/collect/main.go @@ -9,7 +9,8 @@ import ( "github.com/curusarn/resh/internal/collect" "github.com/curusarn/resh/internal/logger" "github.com/curusarn/resh/internal/output" - "github.com/curusarn/resh/internal/records" + "github.com/curusarn/resh/internal/record" + "github.com/curusarn/resh/internal/recordint" "go.uber.org/zap" // "os/exec" @@ -32,14 +33,6 @@ func main() { } out := output.New(logger, "resh-collect ERROR") - homeDir, err := os.UserHomeDir() - if err != nil { - out.Fatal("Could not get user home dir", err) - } - - reshUUIDPath := filepath.Join(homeDir, "/.resh/resh-uuid") - machineIDPath := "/etc/machine-id" - // version showVersion := flag.Bool("version", false, "Show version and exit") showRevision := flag.Bool("revision", false, "Show git revision and exit") @@ -49,55 +42,27 @@ func main() { // core cmdLine := flag.String("cmdLine", "", "command line") - exitCode := flag.Int("exitCode", -1, "exit code") - shell := flag.String("shell", "", "actual shell") - uname := flag.String("uname", "", "uname") - sessionID := flag.String("sessionId", "", "resh generated session id") - recordID := flag.String("recordId", "", "resh generated record id") - - // posix variables - cols := flag.String("cols", "-1", "$COLUMNS") - lines := flag.String("lines", "-1", "$LINES") + home := flag.String("home", "", "$HOME") - lang := flag.String("lang", "", "$LANG") - lcAll := flag.String("lcAll", "", "$LC_ALL") - login := flag.String("login", "", "$LOGIN") - // path := flag.String("path", "", "$PATH") pwd := flag.String("pwd", "", "$PWD - present working directory") - shellEnv := flag.String("shellEnv", "", "$SHELL") - term := flag.String("term", "", "$TERM") + + // FIXME: get device ID + deviceID := flag.String("deviceID", "", "RESH device ID") + sessionID := flag.String("sessionID", "", "resh generated session ID") + recordID := flag.String("recordID", "", "resh generated record ID") + sessionPID := flag.Int("sessionPID", -1, "PID at the start of the terminal session") + + shell := flag.String("shell", "", "current shell") + + logname := flag.String("logname", "", "$LOGNAME") + hostname := flag.String("hostname", "", "$HOSTNAME") // non-posix - pid := flag.Int("pid", -1, "$$") - sessionPid := flag.Int("sessionPid", -1, "$$ at session start") shlvl := flag.Int("shlvl", -1, "$SHLVL") - host := flag.String("host", "", "$HOSTNAME") - hosttype := flag.String("hosttype", "", "$HOSTTYPE") - ostype := flag.String("ostype", "", "$OSTYPE") - machtype := flag.String("machtype", "", "$MACHTYPE") - gitCdup := flag.String("gitCdup", "", "git rev-parse --show-cdup") gitRemote := flag.String("gitRemote", "", "git remote get-url origin") - gitCdupExitCode := flag.Int("gitCdupExitCode", -1, "... $?") - gitRemoteExitCode := flag.Int("gitRemoteExitCode", -1, "... $?") - - // before after - timezoneBefore := flag.String("timezoneBefore", "", "") - - osReleaseID := flag.String("osReleaseId", "", "/etc/os-release ID") - osReleaseVersionID := flag.String("osReleaseVersionId", "", - "/etc/os-release ID") - osReleaseIDLike := flag.String("osReleaseIdLike", "", "/etc/os-release ID") - osReleaseName := flag.String("osReleaseName", "", "/etc/os-release ID") - osReleasePrettyName := flag.String("osReleasePrettyName", "", - "/etc/os-release ID") - - rtb := flag.String("realtimeBefore", "-1", "before $EPOCHREALTIME") - rtsess := flag.String("realtimeSession", "-1", - "on session start $EPOCHREALTIME") - rtsessboot := flag.String("realtimeSessSinceBoot", "-1", - "on session start $EPOCHREALTIME") + time_ := flag.String("time", "-1", "$EPOCHREALTIME") flag.Parse() if *showVersion == true { @@ -109,37 +74,17 @@ func main() { os.Exit(0) } if *requireVersion != "" && *requireVersion != version { - fmt.Println("Please restart/reload this terminal session " + - "(resh version: " + version + - "; resh version of this terminal session: " + *requireVersion + - ")") - os.Exit(3) + out.FatalVersionMismatch(version, *requireVersion) } if *requireRevision != "" && *requireRevision != commit { - fmt.Println("Please restart/reload this terminal session " + - "(resh revision: " + commit + - "; resh revision of this terminal session: " + *requireRevision + - ")") - os.Exit(3) + // this is only relevant for dev versions so we can reuse FatalVersionMismatch() + out.FatalVersionMismatch("revision "+commit, "revision "+*requireVersion) } - realtimeBefore, err := strconv.ParseFloat(*rtb, 64) - if err != nil { - out.Fatal("Error while parsing flag --realtimeBefore", err) - } - realtimeSessionStart, err := strconv.ParseFloat(*rtsess, 64) + time, err := strconv.ParseFloat(*time_, 64) if err != nil { - out.Fatal("Error while parsing flag --realtimeSession", err) + out.Fatal("Error while parsing flag --time", err) } - realtimeSessSinceBoot, err := strconv.ParseFloat(*rtsessboot, 64) - if err != nil { - out.Fatal("Error while parsing flag --realtimeSessSinceBoot", err) - } - realtimeSinceSessionStart := realtimeBefore - realtimeSessionStart - realtimeSinceBoot := realtimeSessSinceBoot + realtimeSinceSessionStart - - timezoneBeforeOffset := collect.GetTimezoneOffsetInSeconds(logger, *timezoneBefore) - realtimeBeforeLocal := realtimeBefore + timezoneBeforeOffset realPwd, err := filepath.EvalSymlinks(*pwd) if err != nil { @@ -147,79 +92,34 @@ func main() { realPwd = "" } - gitDir, gitRealDir := collect.GetGitDirs(logger, *gitCdup, *gitCdupExitCode, *pwd) - if *gitRemoteExitCode != 0 { - *gitRemote = "" - } + rec := recordint.Collect{ + SessionID: *sessionID, + Shlvl: *shlvl, + SessionPID: *sessionPID, + + Shell: *shell, - // if *osReleaseID == "" { - // *osReleaseID = "linux" - // } - // if *osReleaseName == "" { - // *osReleaseName = "Linux" - // } - // if *osReleasePrettyName == "" { - // *osReleasePrettyName = "Linux" - // } - - rec := records.Record{ - // posix - Cols: *cols, - Lines: *lines, - // core - BaseRecord: records.BaseRecord{ - CmdLine: *cmdLine, - ExitCode: *exitCode, - Shell: *shell, - Uname: *uname, + Rec: record.V1{ + DeviceID: *deviceID, SessionID: *sessionID, RecordID: *recordID, + CmdLine: *cmdLine, + // posix - Home: *home, - Lang: *lang, - LcAll: *lcAll, - Login: *login, - // Path: *path, - Pwd: *pwd, - ShellEnv: *shellEnv, - Term: *term, - - // non-posix - RealPwd: realPwd, - Pid: *pid, - SessionPID: *sessionPid, - Host: *host, - Hosttype: *hosttype, - Ostype: *ostype, - Machtype: *machtype, - Shlvl: *shlvl, - - // before after - TimezoneBefore: *timezoneBefore, - - RealtimeBefore: realtimeBefore, - RealtimeBeforeLocal: realtimeBeforeLocal, - - RealtimeSinceSessionStart: realtimeSinceSessionStart, - RealtimeSinceBoot: realtimeSinceBoot, - - GitDir: gitDir, - GitRealDir: gitRealDir, - GitOriginRemote: *gitRemote, - MachineID: collect.ReadFileContent(out.Logger, machineIDPath), + Home: *home, + Pwd: *pwd, + RealPwd: realPwd, - OsReleaseID: *osReleaseID, - OsReleaseVersionID: *osReleaseVersionID, - OsReleaseIDLike: *osReleaseIDLike, - OsReleaseName: *osReleaseName, - OsReleasePrettyName: *osReleasePrettyName, + Logname: *logname, + Hostname: *hostname, + + GitOriginRemote: *gitRemote, - PartOne: true, + Time: time, - ReshUUID: collect.ReadFileContent(out.Logger, reshUUIDPath), - ReshVersion: version, - ReshRevision: commit, + PartOne: true, + PartsNotMerged: true, }, } collect.SendRecord(out, rec, strconv.Itoa(config.Port), "/record") diff --git a/cmd/daemon/dump.go b/cmd/daemon/dump.go index c038705..b3a154f 100644 --- a/cmd/daemon/dump.go +++ b/cmd/daemon/dump.go @@ -40,7 +40,7 @@ func (h *dumpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { sugar.Errorw("Error when getting records", "error", err) } - resp := msg.CliResponse{CliRecords: fullRecords.List} + resp := msg.CliResponse{Records: fullRecords.List} jsn, err = json.Marshal(&resp) if err != nil { sugar.Errorw("Error when marshaling", "error", err) diff --git a/cmd/daemon/main.go b/cmd/daemon/main.go index 9338d0b..6a6feff 100644 --- a/cmd/daemon/main.go +++ b/cmd/daemon/main.go @@ -22,7 +22,10 @@ var developement bool func main() { config, errCfg := cfg.New() - logger, _ := logger.New("daemon", config.LogLevel, developement) + logger, err := logger.New("daemon", config.LogLevel, developement) + if err != nil { + fmt.Printf("Error while creating logger: %v", err) + } defer logger.Sync() // flushes buffer, if any if errCfg != nil { logger.Error("Error while getting configuration", zap.Error(errCfg)) @@ -34,9 +37,6 @@ func main() { "commit", commit, ) - // xdgCacheHome := d.getEnvOrPanic("__RESH_XDG_CACHE_HOME") - // xdgDataHome := d.getEnvOrPanic("__RESH_XDG_DATA_HOME") - // TODO: rethink PID file and logs location homeDir, err := os.UserHomeDir() if err != nil { diff --git a/cmd/daemon/record.go b/cmd/daemon/record.go index e9acfcc..34e9c1c 100644 --- a/cmd/daemon/record.go +++ b/cmd/daemon/record.go @@ -5,11 +5,11 @@ import ( "io/ioutil" "net/http" - "github.com/curusarn/resh/internal/records" + "github.com/curusarn/resh/internal/recordint" "go.uber.org/zap" ) -func NewRecordHandler(sugar *zap.SugaredLogger, subscribers []chan records.Record) recordHandler { +func NewRecordHandler(sugar *zap.SugaredLogger, subscribers []chan recordint.Collect) recordHandler { return recordHandler{ sugar: sugar.With(zap.String("endpoint", "/record")), subscribers: subscribers, @@ -18,7 +18,7 @@ func NewRecordHandler(sugar *zap.SugaredLogger, subscribers []chan records.Recor type recordHandler struct { sugar *zap.SugaredLogger - subscribers []chan records.Record + subscribers []chan recordint.Collect } func (h *recordHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -34,8 +34,8 @@ func (h *recordHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } sugar.Debugw("Unmarshaling record ...") - record := records.Record{} - err = json.Unmarshal(jsn, &record) + rec := recordint.Collect{} + err = json.Unmarshal(jsn, &rec) if err != nil { sugar.Errorw("Error during unmarshaling", "error", err, @@ -44,16 +44,16 @@ func (h *recordHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } part := "2" - if record.PartOne { + if rec.Rec.PartOne { part = "1" } sugar := sugar.With( - "cmdLine", record.CmdLine, + "cmdLine", rec.Rec.CmdLine, "part", part, ) sugar.Debugw("Got record, sending to subscribers ...") for _, sub := range h.subscribers { - sub <- record + sub <- rec } sugar.Debugw("Record sent to subscribers") }() diff --git a/cmd/daemon/run-server.go b/cmd/daemon/run-server.go index 7878f9a..00d9ede 100644 --- a/cmd/daemon/run-server.go +++ b/cmd/daemon/run-server.go @@ -8,7 +8,7 @@ import ( "github.com/curusarn/resh/internal/cfg" "github.com/curusarn/resh/internal/histfile" - "github.com/curusarn/resh/internal/records" + "github.com/curusarn/resh/internal/recordint" "github.com/curusarn/resh/internal/sesswatch" "github.com/curusarn/resh/internal/signalhandler" "go.uber.org/zap" @@ -26,15 +26,15 @@ type Server struct { } func (s *Server) Run() { - var recordSubscribers []chan records.Record - var sessionInitSubscribers []chan records.Record + var recordSubscribers []chan recordint.Collect + var sessionInitSubscribers []chan recordint.SessionInit var sessionDropSubscribers []chan string var signalSubscribers []chan os.Signal shutdown := make(chan string) // histfile - histfileRecords := make(chan records.Record) + histfileRecords := make(chan recordint.Collect) recordSubscribers = append(recordSubscribers, histfileRecords) histfileSessionsToDrop := make(chan string) sessionDropSubscribers = append(sessionDropSubscribers, histfileSessionsToDrop) @@ -48,9 +48,9 @@ func (s *Server) Run() { histfileSignals, shutdown) // sesswatch - sesswatchRecords := make(chan records.Record) + sesswatchRecords := make(chan recordint.Collect) recordSubscribers = append(recordSubscribers, sesswatchRecords) - sesswatchSessionsToWatch := make(chan records.Record) + sesswatchSessionsToWatch := make(chan recordint.SessionInit) sessionInitSubscribers = append(sessionInitSubscribers, sesswatchSessionsToWatch) sesswatch.Go( s.sugar, diff --git a/cmd/daemon/session-init.go b/cmd/daemon/session-init.go index 2015fb0..9ddd76f 100644 --- a/cmd/daemon/session-init.go +++ b/cmd/daemon/session-init.go @@ -5,13 +5,13 @@ import ( "io/ioutil" "net/http" - "github.com/curusarn/resh/internal/records" + "github.com/curusarn/resh/internal/recordint" "go.uber.org/zap" ) type sessionInitHandler struct { sugar *zap.SugaredLogger - subscribers []chan records.Record + subscribers []chan recordint.SessionInit } func (h *sessionInitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -28,8 +28,8 @@ func (h *sessionInitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } sugar.Debugw("Unmarshaling record ...") - record := records.Record{} - err = json.Unmarshal(jsn, &record) + rec := recordint.SessionInit{} + err = json.Unmarshal(jsn, &rec) if err != nil { sugar.Errorw("Error during unmarshaling", "error", err, @@ -38,12 +38,12 @@ func (h *sessionInitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } sugar := sugar.With( - "sessionID", record.SessionID, - "sessionPID", record.SessionPID, + "sessionID", rec.SessionID, + "sessionPID", rec.SessionPID, ) sugar.Infow("Got session, sending to subscribers ...") for _, sub := range h.subscribers { - sub <- record + sub <- rec } sugar.Debugw("Session sent to subscribers") }() diff --git a/cmd/install-utils/main.go b/cmd/install-utils/main.go index 4e83ec0..6c7209e 100644 --- a/cmd/install-utils/main.go +++ b/cmd/install-utils/main.go @@ -20,7 +20,9 @@ func main() { case "backup": backup() case "rollback": - rollback() + // FIXME + panic("Rollback not implemented yet!") + // rollback() case "migrate-config": migrateConfig() case "migrate-history": diff --git a/cmd/postcollect/main.go b/cmd/postcollect/main.go index 4d4fca8..41a3172 100644 --- a/cmd/postcollect/main.go +++ b/cmd/postcollect/main.go @@ -9,12 +9,12 @@ import ( "github.com/curusarn/resh/internal/collect" "github.com/curusarn/resh/internal/logger" "github.com/curusarn/resh/internal/output" - "github.com/curusarn/resh/internal/records" + "github.com/curusarn/resh/internal/record" + "github.com/curusarn/resh/internal/recordint" "go.uber.org/zap" // "os/exec" - "path/filepath" "strconv" ) @@ -32,44 +32,20 @@ func main() { } out := output.New(logger, "resh-postcollect ERROR") - homeDir, err := os.UserHomeDir() - if err != nil { - out.Fatal("Could not get user home dir", err) - } - reshUUIDPath := filepath.Join(homeDir, "/.resh/resh-uuid") - machineIDPath := "/etc/machine-id" - showVersion := flag.Bool("version", false, "Show version and exit") showRevision := flag.Bool("revision", false, "Show git revision and exit") requireVersion := flag.String("requireVersion", "", "abort if version doesn't match") requireRevision := flag.String("requireRevision", "", "abort if revision doesn't match") - cmdLine := flag.String("cmdLine", "", "command line") exitCode := flag.Int("exitCode", -1, "exit code") - sessionID := flag.String("sessionId", "", "resh generated session id") - recordID := flag.String("recordId", "", "resh generated record id") + sessionID := flag.String("sessionID", "", "resh generated session id") + recordID := flag.String("recordID", "", "resh generated record id") shlvl := flag.Int("shlvl", -1, "$SHLVL") - shell := flag.String("shell", "", "actual shell") - - // posix variables - pwdAfter := flag.String("pwdAfter", "", "$PWD after command") - - // non-posix - // sessionPid := flag.Int("sessionPid", -1, "$$ at session start") - - gitCdupAfter := flag.String("gitCdupAfter", "", "git rev-parse --show-cdup") - gitRemoteAfter := flag.String("gitRemoteAfter", "", "git remote get-url origin") - gitCdupExitCodeAfter := flag.Int("gitCdupExitCodeAfter", -1, "... $?") - gitRemoteExitCodeAfter := flag.Int("gitRemoteExitCodeAfter", -1, "... $?") - - // before after - timezoneAfter := flag.String("timezoneAfter", "", "") - - rtb := flag.String("realtimeBefore", "-1", "before $EPOCHREALTIME") - rta := flag.String("realtimeAfter", "-1", "after $EPOCHREALTIME") + rtb := flag.String("timeBefore", "-1", "before $EPOCHREALTIME") + rta := flag.String("timeAfter", "-1", "after $EPOCHREALTIME") flag.Parse() if *showVersion == true { @@ -81,77 +57,36 @@ func main() { os.Exit(0) } if *requireVersion != "" && *requireVersion != version { - fmt.Println("Please restart/reload this terminal session " + - "(resh version: " + version + - "; resh version of this terminal session: " + *requireVersion + - ")") - os.Exit(3) + out.FatalVersionMismatch(version, *requireVersion) } if *requireRevision != "" && *requireRevision != commit { - fmt.Println("Please restart/reload this terminal session " + - "(resh revision: " + commit + - "; resh revision of this terminal session: " + *requireRevision + - ")") - os.Exit(3) + // this is only relevant for dev versions so we can reuse FatalVersionMismatch() + out.FatalVersionMismatch("revision "+commit, "revision "+*requireVersion) } - realtimeAfter, err := strconv.ParseFloat(*rta, 64) - if err != nil { - out.Fatal("Error while parsing flag --realtimeAfter", err) - } - realtimeBefore, err := strconv.ParseFloat(*rtb, 64) + + timeAfter, err := strconv.ParseFloat(*rta, 64) if err != nil { - out.Fatal("Error while parsing flag --realtimeBefore", err) + out.Fatal("Error while parsing flag --timeAfter", err) } - realtimeDuration := realtimeAfter - realtimeBefore - - timezoneAfterOffset := collect.GetTimezoneOffsetInSeconds(logger, *timezoneAfter) - realtimeAfterLocal := realtimeAfter + timezoneAfterOffset - - realPwdAfter, err := filepath.EvalSymlinks(*pwdAfter) + timeBefore, err := strconv.ParseFloat(*rtb, 64) if err != nil { - logger.Error("Error while handling pwdAfter realpath", zap.Error(err)) - realPwdAfter = "" + out.Fatal("Error while parsing flag --timeBefore", err) } + duration := timeAfter - timeBefore - gitDirAfter, gitRealDirAfter := collect.GetGitDirs(logger, *gitCdupAfter, *gitCdupExitCodeAfter, *pwdAfter) - if *gitRemoteExitCodeAfter != 0 { - *gitRemoteAfter = "" - } + // FIXME: use recordint.Postollect + rec := recordint.Collect{ + SessionID: *sessionID, + Shlvl: *shlvl, - rec := records.Record{ - // core - BaseRecord: records.BaseRecord{ - CmdLine: *cmdLine, - ExitCode: *exitCode, - SessionID: *sessionID, + Rec: record.V1{ RecordID: *recordID, - Shlvl: *shlvl, - Shell: *shell, - - PwdAfter: *pwdAfter, - - // non-posix - RealPwdAfter: realPwdAfter, - - // before after - TimezoneAfter: *timezoneAfter, - - RealtimeBefore: realtimeBefore, - RealtimeAfter: realtimeAfter, - RealtimeAfterLocal: realtimeAfterLocal, - - RealtimeDuration: realtimeDuration, - - GitDirAfter: gitDirAfter, - GitRealDirAfter: gitRealDirAfter, - GitOriginRemoteAfter: *gitRemoteAfter, - MachineID: collect.ReadFileContent(out.Logger, machineIDPath), + SessionID: *sessionID, - PartOne: false, + ExitCode: *exitCode, + Duration: duration, - ReshUUID: collect.ReadFileContent(out.Logger, reshUUIDPath), - ReshVersion: version, - ReshRevision: commit, + PartsNotMerged: true, }, } collect.SendRecord(out, rec, strconv.Itoa(config.Port), "/record") diff --git a/cmd/session-init/main.go b/cmd/session-init/main.go index 59010f7..c966f23 100644 --- a/cmd/session-init/main.go +++ b/cmd/session-init/main.go @@ -9,10 +9,9 @@ import ( "github.com/curusarn/resh/internal/collect" "github.com/curusarn/resh/internal/logger" "github.com/curusarn/resh/internal/output" - "github.com/curusarn/resh/internal/records" + "github.com/curusarn/resh/internal/recordint" "go.uber.org/zap" - "path/filepath" "strconv" ) @@ -30,61 +29,15 @@ func main() { } out := output.New(logger, "resh-collect ERROR") - homeDir, err := os.UserHomeDir() - if err != nil { - out.Fatal("Could not get user home dir", err) - } - - reshUUIDPath := filepath.Join(homeDir, "/.resh/resh-uuid") - - machineIDPath := "/etc/machine-id" - showVersion := flag.Bool("version", false, "Show version and exit") showRevision := flag.Bool("revision", false, "Show git revision and exit") requireVersion := flag.String("requireVersion", "", "abort if version doesn't match") requireRevision := flag.String("requireRevision", "", "abort if revision doesn't match") - shell := flag.String("shell", "", "actual shell") - uname := flag.String("uname", "", "uname") sessionID := flag.String("sessionId", "", "resh generated session id") - // posix variables - cols := flag.String("cols", "-1", "$COLUMNS") - lines := flag.String("lines", "-1", "$LINES") - home := flag.String("home", "", "$HOME") - lang := flag.String("lang", "", "$LANG") - lcAll := flag.String("lcAll", "", "$LC_ALL") - login := flag.String("login", "", "$LOGIN") - shellEnv := flag.String("shellEnv", "", "$SHELL") - term := flag.String("term", "", "$TERM") - - // non-posix - pid := flag.Int("pid", -1, "$$") - sessionPid := flag.Int("sessionPid", -1, "$$ at session start") - shlvl := flag.Int("shlvl", -1, "$SHLVL") - - host := flag.String("host", "", "$HOSTNAME") - hosttype := flag.String("hosttype", "", "$HOSTTYPE") - ostype := flag.String("ostype", "", "$OSTYPE") - machtype := flag.String("machtype", "", "$MACHTYPE") - - // before after - timezoneBefore := flag.String("timezoneBefore", "", "") - - osReleaseID := flag.String("osReleaseId", "", "/etc/os-release ID") - osReleaseVersionID := flag.String("osReleaseVersionId", "", - "/etc/os-release ID") - osReleaseIDLike := flag.String("osReleaseIdLike", "", "/etc/os-release ID") - osReleaseName := flag.String("osReleaseName", "", "/etc/os-release ID") - osReleasePrettyName := flag.String("osReleasePrettyName", "", - "/etc/os-release ID") - - rtb := flag.String("realtimeBefore", "-1", "before $EPOCHREALTIME") - rtsess := flag.String("realtimeSession", "-1", - "on session start $EPOCHREALTIME") - rtsessboot := flag.String("realtimeSessSinceBoot", "-1", - "on session start $EPOCHREALTIME") + sessionPID := flag.Int("sessionPid", -1, "$$ at session start") flag.Parse() if *showVersion == true { @@ -96,96 +49,16 @@ func main() { os.Exit(0) } if *requireVersion != "" && *requireVersion != version { - fmt.Println("Please restart/reload this terminal session " + - "(resh version: " + version + - "; resh version of this terminal session: " + *requireVersion + - ")") - os.Exit(3) + out.FatalVersionMismatch(version, *requireVersion) } if *requireRevision != "" && *requireRevision != commit { - fmt.Println("Please restart/reload this terminal session " + - "(resh revision: " + commit + - "; resh revision of this terminal session: " + *requireRevision + - ")") - os.Exit(3) - } - realtimeBefore, err := strconv.ParseFloat(*rtb, 64) - if err != nil { - out.Fatal("Error while parsing flag --realtimeBefore", err) + // this is only relevant for dev versions so we can reuse FatalVersionMismatch() + out.FatalVersionMismatch("revision "+commit, "revision "+*requireVersion) } - realtimeSessionStart, err := strconv.ParseFloat(*rtsess, 64) - if err != nil { - out.Fatal("Error while parsing flag --realtimeSession", err) - } - realtimeSessSinceBoot, err := strconv.ParseFloat(*rtsessboot, 64) - if err != nil { - out.Fatal("Error while parsing flag --realtimeSessSinceBoot", err) - } - realtimeSinceSessionStart := realtimeBefore - realtimeSessionStart - realtimeSinceBoot := realtimeSessSinceBoot + realtimeSinceSessionStart - - timezoneBeforeOffset := collect.GetTimezoneOffsetInSeconds(logger, *timezoneBefore) - realtimeBeforeLocal := realtimeBefore + timezoneBeforeOffset - - if *osReleaseID == "" { - *osReleaseID = "linux" - } - if *osReleaseName == "" { - *osReleaseName = "Linux" - } - if *osReleasePrettyName == "" { - *osReleasePrettyName = "Linux" - } - - rec := records.Record{ - // posix - Cols: *cols, - Lines: *lines, - // core - BaseRecord: records.BaseRecord{ - Shell: *shell, - Uname: *uname, - SessionID: *sessionID, - - // posix - Home: *home, - Lang: *lang, - LcAll: *lcAll, - Login: *login, - // Path: *path, - ShellEnv: *shellEnv, - Term: *term, - - // non-posix - Pid: *pid, - SessionPID: *sessionPid, - Host: *host, - Hosttype: *hosttype, - Ostype: *ostype, - Machtype: *machtype, - Shlvl: *shlvl, - - // before after - TimezoneBefore: *timezoneBefore, - - RealtimeBefore: realtimeBefore, - RealtimeBeforeLocal: realtimeBeforeLocal, - - RealtimeSinceSessionStart: realtimeSinceSessionStart, - RealtimeSinceBoot: realtimeSinceBoot, - - MachineID: collect.ReadFileContent(out.Logger, machineIDPath), - - OsReleaseID: *osReleaseID, - OsReleaseVersionID: *osReleaseVersionID, - OsReleaseIDLike: *osReleaseIDLike, - OsReleaseName: *osReleaseName, - OsReleasePrettyName: *osReleasePrettyName, - ReshUUID: collect.ReadFileContent(out.Logger, reshUUIDPath), - ReshVersion: version, - ReshRevision: commit, - }, + rec := recordint.SessionInit{ + SessionID: *sessionID, + SessionPID: *sessionPID, } - collect.SendRecord(out, rec, strconv.Itoa(config.Port), "/session_init") + collect.SendSessionInit(out, rec, strconv.Itoa(config.Port)) } diff --git a/go.mod b/go.mod index c63b38f..db1e19f 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,6 @@ go 1.18 require ( github.com/BurntSushi/toml v0.4.1 github.com/awesome-gocui/gocui v1.0.0 - github.com/mattn/go-shellwords v1.0.12 github.com/mitchellh/go-ps v1.0.0 github.com/spf13/cobra v1.2.1 github.com/whilp/git-urls v1.0.0 diff --git a/go.sum b/go.sum index 2e9120d..ec1b8bf 100644 --- a/go.sum +++ b/go.sum @@ -193,8 +193,6 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= -github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= diff --git a/internal/cfg/cfg.go b/internal/cfg/cfg.go index 99f7c84..4df3d94 100644 --- a/internal/cfg/cfg.go +++ b/internal/cfg/cfg.go @@ -92,6 +92,7 @@ func getConfig() (*configFile, error) { return readConfig(path) } +// returned config is always usable, returned errors are informative func processAndFillDefaults(configF *configFile) (Config, error) { config := defaults diff --git a/internal/collect/collect.go b/internal/collect/collect.go index e9fc585..15d2bbb 100644 --- a/internal/collect/collect.go +++ b/internal/collect/collect.go @@ -11,14 +11,14 @@ import ( "time" "github.com/curusarn/resh/internal/output" - "github.com/curusarn/resh/internal/records" + "github.com/curusarn/resh/internal/recordint" "go.uber.org/zap" ) // SendRecord to daemon -func SendRecord(out *output.Output, r records.Record, port, path string) { +func SendRecord(out *output.Output, r recordint.Collect, port, path string) { out.Logger.Debug("Sending record ...", - zap.String("cmdLine", r.CmdLine), + zap.String("cmdLine", r.Rec.CmdLine), zap.String("sessionID", r.SessionID), ) recJSON, err := json.Marshal(r) @@ -42,6 +42,33 @@ func SendRecord(out *output.Output, r records.Record, port, path string) { } } +// SendSessionInit to daemon +func SendSessionInit(out *output.Output, r recordint.SessionInit, port string) { + out.Logger.Debug("Sending session init ...", + zap.String("sessionID", r.SessionID), + zap.Int("sessionPID", r.SessionPID), + ) + recJSON, err := json.Marshal(r) + if err != nil { + out.Fatal("Error while encoding record", err) + } + + req, err := http.NewRequest("POST", "http://localhost:"+port+"/session_init", + bytes.NewBuffer(recJSON)) + if err != nil { + out.Fatal("Error while sending record", err) + } + req.Header.Set("Content-Type", "application/json") + + client := http.Client{ + Timeout: 1 * time.Second, + } + _, err = client.Do(req) + if err != nil { + out.FatalDaemonNotRunning(err) + } +} + // ReadFileContent and return it as a string func ReadFileContent(logger *zap.Logger, path string) string { dat, err := ioutil.ReadFile(path) diff --git a/internal/histcli/histcli.go b/internal/histcli/histcli.go index 9bedf61..8069990 100644 --- a/internal/histcli/histcli.go +++ b/internal/histcli/histcli.go @@ -1,13 +1,13 @@ package histcli import ( - "github.com/curusarn/resh/internal/records" + "github.com/curusarn/resh/internal/recordint" ) // Histcli is a dump of history preprocessed for resh cli purposes type Histcli struct { // list of records - List []records.CliRecord + List []recordint.SearchApp } // New Histcli @@ -16,16 +16,15 @@ func New() Histcli { } // AddRecord to the histcli -func (h *Histcli) AddRecord(record records.Record) { - enriched := records.Enriched(record) - cli := records.NewCliRecord(enriched) +func (h *Histcli) AddRecord(rec *recordint.Indexed) { + cli := recordint.NewSearchApp(rec) h.List = append(h.List, cli) } // AddCmdLine to the histcli func (h *Histcli) AddCmdLine(cmdline string) { - cli := records.NewCliRecordFromCmdLine(cmdline) + cli := recordint.NewSearchAppFromCmdLine(cmdline) h.List = append(h.List, cli) } diff --git a/internal/histfile/histfile.go b/internal/histfile/histfile.go index 9d7cce0..9eea14d 100644 --- a/internal/histfile/histfile.go +++ b/internal/histfile/histfile.go @@ -1,7 +1,6 @@ package histfile import ( - "encoding/json" "math" "os" "strconv" @@ -9,42 +8,48 @@ import ( "github.com/curusarn/resh/internal/histcli" "github.com/curusarn/resh/internal/histlist" + "github.com/curusarn/resh/internal/recio" + "github.com/curusarn/resh/internal/record" + "github.com/curusarn/resh/internal/recordint" "github.com/curusarn/resh/internal/records" + "github.com/curusarn/resh/internal/recutil" "go.uber.org/zap" ) +// TODO: get rid of histfile - use histio instead // Histfile writes records to histfile type Histfile struct { sugar *zap.SugaredLogger sessionsMutex sync.Mutex - sessions map[string]records.Record + sessions map[string]recordint.Collect historyPath string - recentMutex sync.Mutex - recentRecords []records.Record - // NOTE: we have separate histories which only differ if there was not enough resh_history // resh_history itself is common for both bash and zsh bashCmdLines histlist.Histlist zshCmdLines histlist.Histlist cliRecords histcli.Histcli + + rio *recio.RecIO } // New creates new histfile and runs its gorutines -func New(sugar *zap.SugaredLogger, input chan records.Record, sessionsToDrop chan string, +func New(sugar *zap.SugaredLogger, input chan recordint.Collect, sessionsToDrop chan string, reshHistoryPath string, bashHistoryPath string, zshHistoryPath string, maxInitHistSize int, minInitHistSizeKB int, signals chan os.Signal, shutdownDone chan string) *Histfile { + rio := recio.New(sugar.With("module", "histfile")) hf := Histfile{ sugar: sugar.With("module", "histfile"), - sessions: map[string]records.Record{}, + sessions: map[string]recordint.Collect{}, historyPath: reshHistoryPath, bashCmdLines: histlist.New(sugar), zshCmdLines: histlist.New(sugar), cliRecords: histcli.New(), + rio: &rio, } go hf.loadHistory(bashHistoryPath, zshHistoryPath, maxInitHistSize, minInitHistSizeKB) go hf.writer(input, signals, shutdownDone) @@ -53,7 +58,7 @@ func New(sugar *zap.SugaredLogger, input chan records.Record, sessionsToDrop cha } // load records from resh history, reverse, enrich and save -func (h *Histfile) loadCliRecords(recs []records.Record) { +func (h *Histfile) loadCliRecords(recs []recordint.Indexed) { for _, cmdline := range h.bashCmdLines.List { h.cliRecords.AddCmdLine(cmdline) } @@ -62,7 +67,7 @@ func (h *Histfile) loadCliRecords(recs []records.Record) { } for i := len(recs) - 1; i >= 0; i-- { rec := recs[i] - h.cliRecords.AddRecord(rec) + h.cliRecords.AddRecord(&rec) } h.sugar.Infow("Resh history loaded", "historyRecordsCount", len(h.cliRecords.List), @@ -71,8 +76,6 @@ func (h *Histfile) loadCliRecords(recs []records.Record) { // loadsHistory from resh_history and if there is not enough of it also load native shell histories func (h *Histfile) loadHistory(bashHistoryPath, zshHistoryPath string, maxInitHistSize, minInitHistSizeKB int) { - h.recentMutex.Lock() - defer h.recentMutex.Unlock() h.sugar.Infow("Checking if resh_history is large enough ...") fi, err := os.Stat(h.historyPath) var size int @@ -95,14 +98,17 @@ func (h *Histfile) loadHistory(bashHistoryPath, zshHistoryPath string, maxInitHi h.sugar.Debugw("Loading resh history from file ...", "historyFile", h.historyPath, ) - history := records.LoadFromFile(h.sugar, h.historyPath) + history, err := h.rio.ReadAndFixFile(h.historyPath, 3) + if err != nil { + h.sugar.Panicf("Failed to read file: %w", err) + } h.sugar.Infow("Resh history loaded from file", "historyFile", h.historyPath, "recordCount", len(history), ) go h.loadCliRecords(history) // NOTE: keeping this weird interface for now because we might use it in the future - // when we only load bash or zsh history + // when we only load bash or zsh history reshCmdLines := loadCmdLines(h.sugar, history) h.sugar.Infow("Resh history loaded and processed", "recordCount", len(reshCmdLines.List), @@ -130,7 +136,7 @@ func (h *Histfile) sessionGC(sessionsToDrop chan string) { if part1, found := h.sessions[session]; found == true { sugar.Infow("Dropping session") delete(h.sessions, session) - go writeRecord(sugar, part1, h.historyPath) + go h.rio.AppendToFile(h.historyPath, []record.V1{part1.Rec}) } else { sugar.Infow("No hanging parts for session - nothing to drop") } @@ -139,43 +145,43 @@ func (h *Histfile) sessionGC(sessionsToDrop chan string) { } // writer reads records from channel, merges them and writes them to file -func (h *Histfile) writer(input chan records.Record, signals chan os.Signal, shutdownDone chan string) { +func (h *Histfile) writer(collect chan recordint.Collect, signals chan os.Signal, shutdownDone chan string) { for { func() { select { - case record := <-input: + case rec := <-collect: part := "2" - if record.PartOne { + if rec.Rec.PartOne { part = "1" } sugar := h.sugar.With( - "recordCmdLine", record.CmdLine, + "recordCmdLine", rec.Rec.CmdLine, "recordPart", part, - "recordShell", record.Shell, + "recordShell", rec.Shell, ) sugar.Debugw("Got record") h.sessionsMutex.Lock() defer h.sessionsMutex.Unlock() // allows nested sessions to merge records properly - mergeID := record.SessionID + "_" + strconv.Itoa(record.Shlvl) + mergeID := rec.SessionID + "_" + strconv.Itoa(rec.Shlvl) sugar = sugar.With("mergeID", mergeID) - if record.PartOne { + if rec.Rec.PartOne { if _, found := h.sessions[mergeID]; found { msg := "Got another first part of the records before merging the previous one - overwriting!" - if record.Shell == "zsh" { + if rec.Shell == "zsh" { sugar.Warnw(msg) } else { sugar.Infow(msg + " Unfortunately this is normal in bash, it can't be prevented.") } } - h.sessions[mergeID] = record + h.sessions[mergeID] = rec } else { if part1, found := h.sessions[mergeID]; found == false { sugar.Warnw("Got second part of record and nothing to merge it with - ignoring!") } else { delete(h.sessions, mergeID) - go h.mergeAndWriteRecord(sugar, part1, record) + go h.mergeAndWriteRecord(sugar, part1, rec) } } case sig := <-signals: @@ -187,11 +193,11 @@ func (h *Histfile) writer(input chan records.Record, signals chan os.Signal, shu defer h.sessionsMutex.Unlock() sugar.Debugw("Unlocked mutex") - for sessID, record := range h.sessions { + for sessID, rec := range h.sessions { sugar.Warnw("Writing incomplete record for session", "sessionID", sessID, ) - h.writeRecord(sugar, record) + h.writeRecord(sugar, rec.Rec) } sugar.Debugw("Shutdown successful") shutdownDone <- "histfile" @@ -201,52 +207,53 @@ func (h *Histfile) writer(input chan records.Record, signals chan os.Signal, shu } } -func (h *Histfile) writeRecord(sugar *zap.SugaredLogger, part1 records.Record) { - writeRecord(sugar, part1, h.historyPath) +func (h *Histfile) writeRecord(sugar *zap.SugaredLogger, rec record.V1) { + h.rio.AppendToFile(h.historyPath, []record.V1{rec}) } -func (h *Histfile) mergeAndWriteRecord(sugar *zap.SugaredLogger, part1, part2 records.Record) { - err := part1.Merge(part2) +func (h *Histfile) mergeAndWriteRecord(sugar *zap.SugaredLogger, part1 recordint.Collect, part2 recordint.Collect) { + rec, err := recutil.Merge(&part1, &part2) if err != nil { sugar.Errorw("Error while merging records", "error", err) return } func() { - h.recentMutex.Lock() - defer h.recentMutex.Unlock() - h.recentRecords = append(h.recentRecords, part1) - cmdLine := part1.CmdLine + cmdLine := rec.CmdLine h.bashCmdLines.AddCmdLine(cmdLine) h.zshCmdLines.AddCmdLine(cmdLine) - h.cliRecords.AddRecord(part1) + h.cliRecords.AddRecord(&recordint.Indexed{ + // TODO: is this what we want? + Rec: rec, + }) }() - writeRecord(sugar, part1, h.historyPath) + h.rio.AppendToFile(h.historyPath, []record.V1{rec}) } -func writeRecord(sugar *zap.SugaredLogger, rec records.Record, outputPath string) { - recJSON, err := json.Marshal(rec) - if err != nil { - sugar.Errorw("Marshalling error", "error", err) - return - } - f, err := os.OpenFile(outputPath, - os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - sugar.Errorw("Could not open file", "error", err) - return - } - defer f.Close() - _, err = f.Write(append(recJSON, []byte("\n")...)) - if err != nil { - sugar.Errorw("Error while writing record", - "recordRaw", rec, - "error", err, - ) - return - } -} +// TODO: use errors in RecIO +// func writeRecord(sugar *zap.SugaredLogger, rec record.V1, outputPath string) { +// recJSON, err := json.Marshal(rec) +// if err != nil { +// sugar.Errorw("Marshalling error", "error", err) +// return +// } +// f, err := os.OpenFile(outputPath, +// os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) +// if err != nil { +// sugar.Errorw("Could not open file", "error", err) +// return +// } +// defer f.Close() +// _, err = f.Write(append(recJSON, []byte("\n")...)) +// if err != nil { +// sugar.Errorw("Error while writing record", +// "recordRaw", rec, +// "error", err, +// ) +// return +// } +// } // DumpCliRecords returns enriched records func (h *Histfile) DumpCliRecords() histcli.Histcli { @@ -254,13 +261,13 @@ func (h *Histfile) DumpCliRecords() histcli.Histcli { return h.cliRecords } -func loadCmdLines(sugar *zap.SugaredLogger, recs []records.Record) histlist.Histlist { +func loadCmdLines(sugar *zap.SugaredLogger, recs []recordint.Indexed) histlist.Histlist { hl := histlist.New(sugar) // go from bottom and deduplicate var cmdLines []string cmdLinesSet := map[string]bool{} for i := len(recs) - 1; i >= 0; i-- { - cmdLine := recs[i].CmdLine + cmdLine := recs[i].Rec.CmdLine if cmdLinesSet[cmdLine] { continue } diff --git a/internal/msg/msg.go b/internal/msg/msg.go index 06d87cf..7d3b103 100644 --- a/internal/msg/msg.go +++ b/internal/msg/msg.go @@ -1,5 +1,7 @@ package msg +import "github.com/curusarn/resh/internal/recordint" + // CliMsg struct type CliMsg struct { SessionID string @@ -8,7 +10,7 @@ type CliMsg struct { // CliResponse struct type CliResponse struct { - Records []record.SearchApp + Records []recordint.SearchApp } // StatusResponse struct diff --git a/internal/output/output.go b/internal/output/output.go index 769f099..2799e57 100644 --- a/internal/output/output.go +++ b/internal/output/output.go @@ -39,7 +39,7 @@ func (f *Output) Fatal(msg string, err error) { var msgDeamonNotRunning = `Resh-daemon didn't respond - it's probably not running. -> Try restarting this terminal window to bring resh-daemon back up - -> If the problem persists you can check resh-daemon logs: ~/.resh/log.json + -> If the problem persists you can check resh-daemon logs: ~/.local/share/resh/log.json (or ~/$XDG_DATA_HOME/resh/log.json) -> You can create an issue at: https://github.com/curusarn/resh/issues ` var msgVersionMismatch = `This terminal session was started with different resh version than is installed now. @@ -58,12 +58,18 @@ func (f *Output) FatalDaemonNotRunning(err error) { f.Logger.Fatal("Daemon is not running", zap.Error(err)) } -func (f *Output) ErrorVersionMismatch(err error) { - fmt.Fprintf(os.Stderr, "%s: %s", f.ErrPrefix, msgVersionMismatch) - f.Logger.Fatal("Version mismatch", zap.Error(err)) +func (f *Output) ErrorVersionMismatch(installedVer, terminalVer string) { + fmt.Fprintf(os.Stderr, "%s: %s\n\n(installed version: %s, this terminal version: %s)", + f.ErrPrefix, msgVersionMismatch, installedVer, terminalVer) + f.Logger.Fatal("Version mismatch", + zap.String("installed", installedVer), + zap.String("terminal", terminalVer)) } -func (f *Output) FatalVersionMismatch(err error) { - fmt.Fprintf(os.Stderr, "%s: %s", f.ErrPrefix, msgVersionMismatch) - f.Logger.Fatal("Version mismatch", zap.Error(err)) +func (f *Output) FatalVersionMismatch(installedVer, terminalVer string) { + fmt.Fprintf(os.Stderr, "%s: %s\n\n(installed version: %s, this terminal version: %s)", + f.ErrPrefix, msgVersionMismatch, installedVer, terminalVer) + f.Logger.Fatal("Version mismatch", + zap.String("installed", installedVer), + zap.String("terminal", terminalVer)) } diff --git a/internal/recconv/recconv.go b/internal/recconv/recconv.go index d0156c5..36cf605 100644 --- a/internal/recconv/recconv.go +++ b/internal/recconv/recconv.go @@ -1,9 +1,35 @@ package recconv -import "github.com/curusarn/resh/internal/record" +import ( + "github.com/curusarn/resh/internal/record" +) func LegacyToV1(r *record.Legacy) *record.V1 { return &record.V1{ // FIXME: fill in all the fields + + // Flags: 0, + + DeviceID: r.MachineID, + SessionID: r.SessionID, + RecordID: r.RecordID, + + CmdLine: r.CmdLine, + ExitCode: r.ExitCode, + + Home: r.Home, + Pwd: r.Pwd, + RealPwd: r.RealPwd, + + Logname: r.Login, + Hostname: r.Host, + + GitOriginRemote: r.GitOriginRemote, + + Time: r.RealtimeBefore, + Duration: r.RealtimeDuration, + + PartOne: r.PartOne, + PartsNotMerged: !r.PartsMerged, } } diff --git a/internal/recio/read.go b/internal/recio/read.go index 7a7f183..304a4bd 100644 --- a/internal/recio/read.go +++ b/internal/recio/read.go @@ -48,7 +48,7 @@ func (r *RecIO) ReadAndFixFile(fpath string, maxErrors int) ([]recordint.Indexed for _, rec := range recs { recsV1 = append(recsV1, rec.Rec) } - err = r.WriteFile(fpath, recsV1) + err = r.OverwriteFile(fpath, recsV1) if err != nil { r.sugar.Errorw("Failed write fixed history file - aborting fixing history file", "filename", fpath, diff --git a/internal/recio/write.go b/internal/recio/write.go index 8bc5e06..831a146 100644 --- a/internal/recio/write.go +++ b/internal/recio/write.go @@ -10,13 +10,36 @@ import ( ) // TODO: better errors -func (r *RecIO) WriteFile(fpath string, data []record.V1) error { +func (r *RecIO) OverwriteFile(fpath string, recs []record.V1) error { file, err := os.Create(fpath) if err != nil { return err } defer file.Close() - for _, rec := range data { + return writeRecords(file, recs) +} + +// TODO: better errors +func (r *RecIO) AppendToFile(fpath string, recs []record.V1) error { + file, err := os.OpenFile(fpath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + return err + } + defer file.Close() + return writeRecords(file, recs) +} + +// TODO: better errors +func (r *RecIO) EditRecordFlagsInFile(fpath string, idx int, rec recordint.Flag) error { + // FIXME: implement + // open file "not as append" + // scan to the correct line + r.sugar.Error("not implemented yet (FIXME)") + return nil +} + +func writeRecords(file *os.File, recs []record.V1) error { + for _, rec := range recs { jsn, err := encodeV1Record(rec) if err != nil { return err @@ -29,18 +52,11 @@ func (r *RecIO) WriteFile(fpath string, data []record.V1) error { return nil } -func (r *RecIO) EditRecordFlagsInFile(fpath string, idx int, rec recordint.Flag) error { - // FIXME: implement - // open file "not as append" - // scan to the correct line - - return nil -} - func encodeV1Record(rec record.V1) ([]byte, error) { + version := []byte("v1") jsn, err := json.Marshal(rec) if err != nil { return nil, fmt.Errorf("failed to encode json: %w", err) } - return append(jsn, []byte("\n")...), nil + return append(append(version, jsn...), []byte("\n")...), nil } diff --git a/internal/record/v1.go b/internal/record/v1.go index 606988a..1620ccd 100644 --- a/internal/record/v1.go +++ b/internal/record/v1.go @@ -16,6 +16,7 @@ type V1 struct { ExitCode int `json:"exitCode"` // paths + // TODO: Do we need both pwd and real pwd? Home string `json:"home"` Pwd string `json:"pwd"` RealPwd string `json:"realPwd"` @@ -27,8 +28,9 @@ type V1 struct { // git info // origin is the most important GitOriginRemote string `json:"gitOriginRemote"` - // maybe branch could be useful - e.g. in monorepo ?? - GitBranch string `json:"gitBranch"` + // TODO: add GitBranch (v2 ?) + // maybe branch could be useful - e.g. in monorepo ?? + // GitBranch string `json:"gitBranch"` // what is this for ?? // session watching needs this @@ -36,11 +38,11 @@ type V1 struct { // records belong to sessions // PID int `json:"pid"` // needed for tracking of sessions but I think it shouldn't be part of V1 - SessionPID int `json:"sessionPID"` + // SessionPID int `json:"sessionPID"` // needed to because records are merged with parts with same "SessionID + Shlvl" // I don't think we need to save it - Shlvl int `json:"shlvl"` + // Shlvl int `json:"shlvl"` // time (before), duration of command Time float64 `json:"time"` diff --git a/internal/recordint/collect.go b/internal/recordint/collect.go index b1e62e7..645efe4 100644 --- a/internal/recordint/collect.go +++ b/internal/recordint/collect.go @@ -8,6 +8,7 @@ type Collect struct { Shlvl int // session watching SessionPID int + Shell string Rec record.V1 } @@ -18,4 +19,16 @@ type Postcollect struct { Shlvl int // session watching SessionPID int + + RecordID string + ExitCode int + Duration float64 +} + +type SessionInit struct { + // record merging + SessionID string + Shlvl int + // session watching + SessionPID int } diff --git a/internal/recordint/enriched.go b/internal/recordint/enriched.go deleted file mode 100644 index b2141a4..0000000 --- a/internal/recordint/enriched.go +++ /dev/null @@ -1,51 +0,0 @@ -package recordint - -import ( - "github.com/curusarn/resh/internal/record" - "github.com/curusarn/resh/internal/recutil" -) - -// TODO: This all seems excessive -// TODO: V1 should be converted directly to SearchApp record - -// EnrichedRecord - record enriched with additional data -type Enriched struct { - // TODO: think about if it really makes sense to have this based on V1 - record.V1 - - // TODO: drop some/all of this - // enriching fields - added "later" - Command string `json:"command"` - FirstWord string `json:"firstWord"` - Invalid bool `json:"invalid"` - SeqSessionID uint64 `json:"seqSessionId"` - LastRecordOfSession bool `json:"lastRecordOfSession"` - DebugThisRecord bool `json:"debugThisRecord"` - Errors []string `json:"errors"` - // SeqSessionID uint64 `json:"seqSessionId,omitempty"` -} - -// Enriched - returns enriched record -func NewEnrichedFromV1(r *record.V1) Enriched { - rec := Enriched{Record: r} - // normlize git remote - rec.GitOriginRemote = NormalizeGitRemote(rec.GitOriginRemote) - rec.GitOriginRemoteAfter = NormalizeGitRemote(rec.GitOriginRemoteAfter) - // Get command/first word from commandline - var err error - err = recutil.Validate(r) - if err != nil { - rec.Errors = append(rec.Errors, "Validate error:"+err.Error()) - // rec, _ := record.ToString() - // sugar.Println("Invalid command:", rec) - rec.Invalid = true - } - rec.Command, rec.FirstWord, err = GetCommandAndFirstWord(r.CmdLine) - if err != nil { - rec.Errors = append(rec.Errors, "GetCommandAndFirstWord error:"+err.Error()) - // rec, _ := record.ToString() - // sugar.Println("Invalid command:", rec) - rec.Invalid = true // should this be really invalid ? - } - return rec -} diff --git a/internal/recordint/searchapp.go b/internal/recordint/searchapp.go index 965ebce..a80b018 100644 --- a/internal/recordint/searchapp.go +++ b/internal/recordint/searchapp.go @@ -1,5 +1,12 @@ package recordint +import ( + "net/url" + "strings" + + giturls "github.com/whilp/git-urls" +) + // SearchApp record used for sending records to RESH-CLI type SearchApp struct { IsRaw bool @@ -14,6 +21,9 @@ type SearchApp struct { ExitCode int Time float64 + + // file index + Idx int } // NewCliRecordFromCmdLine @@ -25,16 +35,39 @@ func NewSearchAppFromCmdLine(cmdLine string) SearchApp { } // NewCliRecord from EnrichedRecord -func NewSearchApp(r *Enriched) SearchApp { +func NewSearchApp(r *Indexed) SearchApp { + // TODO: we used to validate records with recutil.Validate() return SearchApp{ - IsRaw: false, - SessionID: r.SessionID, - CmdLine: r.CmdLine, - Host: r.Hostname, - Pwd: r.Pwd, - Home: r.Home, - GitOriginRemote: r.GitOriginRemote, - ExitCode: r.ExitCode, - Time: r.Time, + IsRaw: false, + SessionID: r.Rec.SessionID, + CmdLine: r.Rec.CmdLine, + Host: r.Rec.Hostname, + Pwd: r.Rec.Pwd, + Home: r.Rec.Home, + // TODO: is this the right place to normalize the git remote + GitOriginRemote: normalizeGitRemote(r.Rec.GitOriginRemote), + ExitCode: r.Rec.ExitCode, + Time: r.Rec.Time, + + Idx: r.Idx, + } +} + +// TODO: maybe move this to a more appropriate place +// normalizeGitRemote helper +func normalizeGitRemote(gitRemote string) string { + if strings.HasSuffix(gitRemote, ".git") { + gitRemote = gitRemote[:len(gitRemote)-4] + } + parsedURL, err := giturls.Parse(gitRemote) + if err != nil { + // TODO: log this error + return gitRemote + } + if parsedURL.User == nil || parsedURL.User.Username() == "" { + parsedURL.User = url.User("git") } + // TODO: figure out what scheme we want + parsedURL.Scheme = "git+ssh" + return parsedURL.String() } diff --git a/internal/records/records.go b/internal/records/records.go index 1747547..a9972d2 100644 --- a/internal/records/records.go +++ b/internal/records/records.go @@ -2,269 +2,13 @@ package records import ( "bufio" - "encoding/json" - "fmt" - "io" "os" - "strconv" "strings" "github.com/curusarn/resh/internal/histlist" "go.uber.org/zap" ) -// BaseRecord - common base for Record and FallbackRecord -type BaseRecord struct { - // core - CmdLine string `json:"cmdLine"` - ExitCode int `json:"exitCode"` - Shell string `json:"shell"` - Uname string `json:"uname"` - SessionID string `json:"sessionId"` - RecordID string `json:"recordId"` - - // posix - Home string `json:"home"` - Lang string `json:"lang"` - LcAll string `json:"lcAll"` - Login string `json:"login"` - //Path string `json:"path"` - Pwd string `json:"pwd"` - PwdAfter string `json:"pwdAfter"` - ShellEnv string `json:"shellEnv"` - Term string `json:"term"` - - // non-posix"` - RealPwd string `json:"realPwd"` - RealPwdAfter string `json:"realPwdAfter"` - Pid int `json:"pid"` - SessionPID int `json:"sessionPid"` - Host string `json:"host"` - Hosttype string `json:"hosttype"` - Ostype string `json:"ostype"` - Machtype string `json:"machtype"` - Shlvl int `json:"shlvl"` - - // before after - TimezoneBefore string `json:"timezoneBefore"` - TimezoneAfter string `json:"timezoneAfter"` - - RealtimeBefore float64 `json:"realtimeBefore"` - RealtimeAfter float64 `json:"realtimeAfter"` - RealtimeBeforeLocal float64 `json:"realtimeBeforeLocal"` - RealtimeAfterLocal float64 `json:"realtimeAfterLocal"` - - RealtimeDuration float64 `json:"realtimeDuration"` - RealtimeSinceSessionStart float64 `json:"realtimeSinceSessionStart"` - RealtimeSinceBoot float64 `json:"realtimeSinceBoot"` - //Logs []string `json: "logs"` - - GitDir string `json:"gitDir"` - GitRealDir string `json:"gitRealDir"` - GitOriginRemote string `json:"gitOriginRemote"` - GitDirAfter string `json:"gitDirAfter"` - GitRealDirAfter string `json:"gitRealDirAfter"` - GitOriginRemoteAfter string `json:"gitOriginRemoteAfter"` - MachineID string `json:"machineId"` - - OsReleaseID string `json:"osReleaseId"` - OsReleaseVersionID string `json:"osReleaseVersionId"` - OsReleaseIDLike string `json:"osReleaseIdLike"` - OsReleaseName string `json:"osReleaseName"` - OsReleasePrettyName string `json:"osReleasePrettyName"` - - ReshUUID string `json:"reshUuid"` - ReshVersion string `json:"reshVersion"` - ReshRevision string `json:"reshRevision"` - - // records come in two parts (collect and postcollect) - PartOne bool `json:"partOne,omitempty"` // false => part two - PartsMerged bool `json:"partsMerged"` - // special flag -> not an actual record but an session end - SessionExit bool `json:"sessionExit,omitempty"` - - // recall metadata - Recalled bool `json:"recalled"` - RecallHistno int `json:"recallHistno,omitempty"` - RecallStrategy string `json:"recallStrategy,omitempty"` - RecallActionsRaw string `json:"recallActionsRaw,omitempty"` - RecallActions []string `json:"recallActions,omitempty"` - RecallLastCmdLine string `json:"recallLastCmdLine"` - - // recall command - RecallPrefix string `json:"recallPrefix,omitempty"` - - // added by sanitizatizer - Sanitized bool `json:"sanitized,omitempty"` - CmdLength int `json:"cmdLength,omitempty"` -} - -// Record representing single executed command with its metadata -type Record struct { - BaseRecord - - Cols string `json:"cols"` - Lines string `json:"lines"` -} - -// EnrichedRecord - record enriched with additional data -type EnrichedRecord struct { - Record - - // enriching fields - added "later" - Command string `json:"command"` - FirstWord string `json:"firstWord"` - Invalid bool `json:"invalid"` - SeqSessionID uint64 `json:"seqSessionId"` - LastRecordOfSession bool `json:"lastRecordOfSession"` - DebugThisRecord bool `json:"debugThisRecord"` - Errors []string `json:"errors"` - // SeqSessionID uint64 `json:"seqSessionId,omitempty"` -} - -// FallbackRecord when record is too old and can't be parsed into regular Record -type FallbackRecord struct { - BaseRecord - // older version of the record where cols and lines are int - - Cols int `json:"cols"` // notice the int type - Lines int `json:"lines"` // notice the int type -} - -// Convert from FallbackRecord to Record -func Convert(r *FallbackRecord) Record { - return Record{ - BaseRecord: r.BaseRecord, - // these two lines are the only reason we are doing this - Cols: strconv.Itoa(r.Cols), - Lines: strconv.Itoa(r.Lines), - } -} - -// ToString - returns record the json -func (r EnrichedRecord) ToString() (string, error) { - jsonRec, err := json.Marshal(r) - if err != nil { - return "marshalling error", err - } - return string(jsonRec), nil -} - -// LoadFromFile loads records from 'fname' file -func LoadFromFile(sugar *zap.SugaredLogger, fname string) []Record { - const allowedErrors = 3 - var encounteredErrors int - var recs []Record - file, err := os.Open(fname) - if err != nil { - sugar.Error("Failed to open resh history file - skipping reading resh history", zap.Error(err)) - return recs - } - defer file.Close() - - reader := bufio.NewReader(file) - var i int - for { - var line string - line, err = reader.ReadString('\n') - if err != nil { - break - } - i++ - record := Record{} - fallbackRecord := FallbackRecord{} - err = json.Unmarshal([]byte(line), &record) - if err != nil { - err = json.Unmarshal([]byte(line), &fallbackRecord) - if err != nil { - encounteredErrors++ - sugar.Error("Could not decode line in resh history file", - "lineContents", line, - "lineNumber", i, - zap.Error(err), - ) - if encounteredErrors > allowedErrors { - sugar.Fatal("Encountered too many errors during decoding - exiting", - "allowedErrors", allowedErrors, - ) - } - } - record = Convert(&fallbackRecord) - } - recs = append(recs, record) - } - if err != io.EOF { - sugar.Error("Error while loading file", zap.Error(err)) - } - sugar.Infow("Loaded resh history records", - "recordCount", len(recs), - ) - if encounteredErrors > 0 { - // fix errors in the history file - sugar.Warnw("Some history records could not be decoded - fixing resh history file by dropping them", - "corruptedRecords", encounteredErrors, - ) - fnameBak := fname + ".bak" - sugar.Infow("Backing up current corrupted history file", - "backupFilename", fnameBak, - ) - err := copyFile(fname, fnameBak) - if err != nil { - sugar.Errorw("Failed to create a backup history file - aborting fixing history file", - "backupFilename", fnameBak, - zap.Error(err), - ) - return recs - } - sugar.Info("Writing resh history file without errors ...") - err = writeHistory(fname, recs) - if err != nil { - sugar.Errorw("Failed write fixed history file - aborting fixing history file", - "filename", fname, - zap.Error(err), - ) - } - } - return recs -} - -func copyFile(source, dest string) error { - from, err := os.Open(source) - if err != nil { - return err - } - defer from.Close() - - // to, err := os.OpenFile(dest, os.O_RDWR|os.O_CREATE, 0666) - to, err := os.Create(dest) - if err != nil { - return err - } - defer to.Close() - - _, err = io.Copy(to, from) - if err != nil { - return err - } - return nil -} - -func writeHistory(fname string, history []Record) error { - file, err := os.Create(fname) - if err != nil { - return err - } - defer file.Close() - for _, rec := range history { - jsn, err := json.Marshal(rec) - if err != nil { - return fmt.Errorf("failed to encode record: %w", err) - } - file.Write(append(jsn, []byte("\n")...)) - } - return nil -} - // LoadCmdLinesFromZshFile loads cmdlines from zsh history file func LoadCmdLinesFromZshFile(sugar *zap.SugaredLogger, fname string) histlist.Histlist { hl := histlist.New(sugar) diff --git a/internal/records/records_test.go b/internal/records/records_test.go deleted file mode 100644 index 9bcb69f..0000000 --- a/internal/records/records_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package records - -import ( - "bufio" - "encoding/json" - "log" - "os" - "testing" -) - -func GetTestRecords() []Record { - file, err := os.Open("testdata/resh_history.json") - if err != nil { - log.Fatalf("Failed to open resh history file: %v", err) - } - defer file.Close() - - var recs []Record - scanner := bufio.NewScanner(file) - for scanner.Scan() { - record := Record{} - line := scanner.Text() - err = json.Unmarshal([]byte(line), &record) - if err != nil { - log.Fatalf("Error decoding record: '%s'; err: %v", line, err) - } - recs = append(recs, record) - } - return recs -} - -func GetTestEnrichedRecords() []EnrichedRecord { - var recs []EnrichedRecord - for _, rec := range GetTestRecords() { - recs = append(recs, Enriched(rec)) - } - return recs -} - -func TestToString(t *testing.T) { - for _, rec := range GetTestEnrichedRecords() { - _, err := rec.ToString() - if err != nil { - t.Error("ToString() failed") - } - } -} - -func TestEnriched(t *testing.T) { - record := Record{BaseRecord: BaseRecord{CmdLine: "cmd arg1 arg2"}} - enriched := Enriched(record) - if enriched.FirstWord != "cmd" || enriched.Command != "cmd" { - t.Error("Enriched() returned reocord w/ wrong Command OR FirstWord") - } -} - -func TestValidate(t *testing.T) { - record := EnrichedRecord{} - if record.Validate() == nil { - t.Error("Validate() didn't return an error for invalid record") - } - record.CmdLine = "cmd arg" - record.FirstWord = "cmd" - record.Command = "cmd" - time := 1234.5678 - record.RealtimeBefore = time - record.RealtimeAfter = time - record.RealtimeBeforeLocal = time - record.RealtimeAfterLocal = time - pwd := "/pwd" - record.Pwd = pwd - record.PwdAfter = pwd - record.RealPwd = pwd - record.RealPwdAfter = pwd - if record.Validate() != nil { - t.Error("Validate() returned an error for a valid record") - } -} - -func TestGetCommandAndFirstWord(t *testing.T) { - cmd, stWord, err := GetCommandAndFirstWord("cmd arg1 arg2") - if err != nil || cmd != "cmd" || stWord != "cmd" { - t.Error("GetCommandAndFirstWord() returned wrong Command OR FirstWord") - } -} diff --git a/internal/records/testdata/resh_history.json b/internal/records/testdata/resh_history.json deleted file mode 100644 index 40f43ab..0000000 --- a/internal/records/testdata/resh_history.json +++ /dev/null @@ -1,27 +0,0 @@ -{"cmdLine":"ls","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"d5c0fe70-c80b-4715-87cb-f8d8d5b4c673","cols":"80","lines":"24","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon","pwdAfter":"/home/simon","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon","realPwdAfter":"/home/simon","pid":14560,"sessionPid":14560,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1566762905.173595,"realtimeAfter":1566762905.1894295,"realtimeBeforeLocal":1566770105.173595,"realtimeAfterLocal":1566770105.1894295,"realtimeDuration":0.015834569931030273,"realtimeSinceSessionStart":1.7122540473937988,"realtimeSinceBoot":20766.542254047396,"gitDir":"","gitRealDir":"","gitOriginRemote":"","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"752acb916f2a"} -{"cmdLine":"find . -name applications","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"c5251955-3a64-4353-952e-08d62a898694","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon","pwdAfter":"/home/simon","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon","realPwdAfter":"/home/simon","pid":3109,"sessionPid":3109,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1567420001.2531302,"realtimeAfter":1567420002.4311218,"realtimeBeforeLocal":1567427201.2531302,"realtimeAfterLocal":1567427202.4311218,"realtimeDuration":1.1779916286468506,"realtimeSinceSessionStart":957.4848053455353,"realtimeSinceBoot":2336.594805345535,"gitDir":"","gitRealDir":"","gitOriginRemote":"","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"752acb916f2a"} -{"cmdLine":"desktop-file-validate curusarn.sync-clipboards.desktop ","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"c5251955-3a64-4353-952e-08d62a898694","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/.local/share/applications","pwdAfter":"/home/simon/.local/share/applications","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/.local/share/applications","realPwdAfter":"/home/simon/.local/share/applications","pid":3109,"sessionPid":3109,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1567421748.2965438,"realtimeAfter":1567421748.3068867,"realtimeBeforeLocal":1567428948.2965438,"realtimeAfterLocal":1567428948.3068867,"realtimeDuration":0.010342836380004883,"realtimeSinceSessionStart":2704.528218984604,"realtimeSinceBoot":4083.6382189846036,"gitDir":"","gitRealDir":"","gitOriginRemote":"","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"752acb916f2a"} -{"cmdLine":"cat /tmp/extensions | grep '.'","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"f044cdbf-fd51-4c37-8528-dcd98fc7b6d9","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon","pwdAfter":"/home/simon","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon","realPwdAfter":"/home/simon","pid":6887,"sessionPid":6887,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1567461416.6871984,"realtimeAfter":1567461416.7336714,"realtimeBeforeLocal":1567468616.6871984,"realtimeAfterLocal":1567468616.7336714,"realtimeDuration":0.046473026275634766,"realtimeSinceSessionStart":21.45597553253174,"realtimeSinceBoot":43752.03597553253,"gitDir":"","gitRealDir":"","gitOriginRemote":"","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"752acb916f2a"} -{"cmdLine":"cd git/resh/","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"f044cdbf-fd51-4c37-8528-dcd98fc7b6d9","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon","pwdAfter":"/home/simon/git/resh","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon","realPwdAfter":"/home/simon/git/resh","pid":6887,"sessionPid":6887,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1567461667.8806899,"realtimeAfter":1567461667.8949044,"realtimeBeforeLocal":1567468867.8806899,"realtimeAfterLocal":1567468867.8949044,"realtimeDuration":0.014214515686035156,"realtimeSinceSessionStart":272.64946699142456,"realtimeSinceBoot":44003.229466991426,"gitDir":"","gitRealDir":"","gitOriginRemote":"","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"752acb916f2a"} -{"cmdLine":"git s","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"f044cdbf-fd51-4c37-8528-dcd98fc7b6d9","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/resh","pwdAfter":"/home/simon/git/resh","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/resh","realPwdAfter":"/home/simon/git/resh","pid":6887,"sessionPid":6887,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1567461707.6467602,"realtimeAfter":1567461707.7177293,"realtimeBeforeLocal":1567468907.6467602,"realtimeAfterLocal":1567468907.7177293,"realtimeDuration":0.0709691047668457,"realtimeSinceSessionStart":312.4155373573303,"realtimeSinceBoot":44042.99553735733,"gitDir":"/home/simon/git/resh","gitRealDir":"/home/simon/git/resh","gitOriginRemote":"git@github.com:curusarn/resh.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"752acb916f2a"} -{"cmdLine":"cat /tmp/extensions | grep '^\\.' | cut -f1 |tr '[:upper:]' '[:lower:]' ","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"f044cdbf-fd51-4c37-8528-dcd98fc7b6d9","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/resh","pwdAfter":"/home/simon/git/resh","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/resh","realPwdAfter":"/home/simon/git/resh","pid":6887,"sessionPid":6887,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1567461722.813049,"realtimeAfter":1567461722.8280325,"realtimeBeforeLocal":1567468922.813049,"realtimeAfterLocal":1567468922.8280325,"realtimeDuration":0.014983415603637695,"realtimeSinceSessionStart":327.581826210022,"realtimeSinceBoot":44058.161826210024,"gitDir":"/home/simon/git/resh","gitRealDir":"/home/simon/git/resh","gitOriginRemote":"git@github.com:curusarn/resh.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"752acb916f2a"} -{"cmdLine":"tig","exitCode":127,"shell":"bash","uname":"Linux","sessionId":"f044cdbf-fd51-4c37-8528-dcd98fc7b6d9","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/resh","pwdAfter":"/home/simon/git/resh","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/resh","realPwdAfter":"/home/simon/git/resh","pid":6887,"sessionPid":6887,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1567461906.3896828,"realtimeAfter":1567461906.4084594,"realtimeBeforeLocal":1567469106.3896828,"realtimeAfterLocal":1567469106.4084594,"realtimeDuration":0.018776655197143555,"realtimeSinceSessionStart":511.1584599018097,"realtimeSinceBoot":44241.73845990181,"gitDir":"/home/simon/git/resh","gitRealDir":"/home/simon/git/resh","gitOriginRemote":"git@github.com:curusarn/resh.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"752acb916f2a"} -{"cmdLine":"resh-sanitize-history | jq","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"a3318c80-3521-4b22-aa64-ea0f6c641410","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon","pwdAfter":"/home/simon","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon","realPwdAfter":"/home/simon","pid":14601,"sessionPid":14601,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1567547116.2430356,"realtimeAfter":1567547116.7547352,"realtimeBeforeLocal":1567554316.2430356,"realtimeAfterLocal":1567554316.7547352,"realtimeDuration":0.5116996765136719,"realtimeSinceSessionStart":15.841878414154053,"realtimeSinceBoot":30527.201878414155,"gitDir":"","gitRealDir":"","gitOriginRemote":"","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"737bc0a4df38","cmdLength":0} -{"cmdLine":"sudo pacman -S ansible","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"64154f2d-a4bc-4463-a690-520080b61ead","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/kristin","pwdAfter":"/home/simon/git/kristin","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/kristin","realPwdAfter":"/home/simon/git/kristin","pid":5663,"sessionPid":5663,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1567609042.0166302,"realtimeAfter":1567609076.9726007,"realtimeBeforeLocal":1567616242.0166302,"realtimeAfterLocal":1567616276.9726007,"realtimeDuration":34.95597052574158,"realtimeSinceSessionStart":1617.0794131755829,"realtimeSinceBoot":6120.029413175583,"gitDir":"/home/simon/git/kristin","gitRealDir":"/home/simon/git/kristin","gitOriginRemote":"git@gitlab.com:sucvut/kristin.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"737bc0a4df38","cmdLength":0} -{"cmdLine":"vagrant up","exitCode":1,"shell":"bash","uname":"Linux","sessionId":"64154f2d-a4bc-4463-a690-520080b61ead","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/kristin","pwdAfter":"/home/simon/git/kristin","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/kristin","realPwdAfter":"/home/simon/git/kristin","pid":5663,"sessionPid":5663,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1567609090.7359188,"realtimeAfter":1567609098.3125577,"realtimeBeforeLocal":1567616290.7359188,"realtimeAfterLocal":1567616298.3125577,"realtimeDuration":7.57663893699646,"realtimeSinceSessionStart":1665.798701763153,"realtimeSinceBoot":6168.748701763153,"gitDir":"/home/simon/git/kristin","gitRealDir":"/home/simon/git/kristin","gitOriginRemote":"git@gitlab.com:sucvut/kristin.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"737bc0a4df38","cmdLength":0} -{"cmdLine":"sudo modprobe vboxnetflt","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"64154f2d-a4bc-4463-a690-520080b61ead","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/kristin","pwdAfter":"/home/simon/git/kristin","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/kristin","realPwdAfter":"/home/simon/git/kristin","pid":5663,"sessionPid":5663,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1567609143.2847652,"realtimeAfter":1567609143.3116078,"realtimeBeforeLocal":1567616343.2847652,"realtimeAfterLocal":1567616343.3116078,"realtimeDuration":0.026842594146728516,"realtimeSinceSessionStart":1718.3475482463837,"realtimeSinceBoot":6221.2975482463835,"gitDir":"/home/simon/git/kristin","gitRealDir":"/home/simon/git/kristin","gitOriginRemote":"git@gitlab.com:sucvut/kristin.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"737bc0a4df38","cmdLength":0} -{"cmdLine":"echo $RANDOM","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"8ddacadc-6e73-483c-b347-4e18df204466","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon","pwdAfter":"/home/simon","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon","realPwdAfter":"/home/simon","pid":31387,"sessionPid":31387,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1567727039.6540458,"realtimeAfter":1567727039.6629689,"realtimeBeforeLocal":1567734239.6540458,"realtimeAfterLocal":1567734239.6629689,"realtimeDuration":0.008923053741455078,"realtimeSinceSessionStart":1470.7667458057404,"realtimeSinceBoot":18495.01674580574,"gitDir":"","gitRealDir":"","gitOriginRemote":"","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"737bc0a4df38","cmdLength":0} -{"cmdLine":"make resh-evaluate ","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"93998b68-ec48-4e48-9e4a-b37b39f5439e","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/resh","pwdAfter":"/home/simon/git/resh","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/resh","realPwdAfter":"/home/simon/git/resh","pid":9463,"sessionPid":9463,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1567977478.9672194,"realtimeAfter":1567977479.5449634,"realtimeBeforeLocal":1567984678.9672194,"realtimeAfterLocal":1567984679.5449634,"realtimeDuration":0.5777440071105957,"realtimeSinceSessionStart":5738.577540636063,"realtimeSinceBoot":20980.42754063606,"gitDir":"/home/simon/git/resh","gitRealDir":"/home/simon/git/resh","gitOriginRemote":"git@github.com:curusarn/resh.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"737bc0a4df38","cmdLength":0} -{"cmdLine":"cat ~/.resh_history.json | grep \"./resh-eval\" | jq","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"93998b68-ec48-4e48-9e4a-b37b39f5439e","cols":"105","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/resh","pwdAfter":"/home/simon/git/resh","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/resh","realPwdAfter":"/home/simon/git/resh","pid":9463,"sessionPid":9463,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1567986105.3988302,"realtimeAfter":1567986105.4809113,"realtimeBeforeLocal":1567993305.3988302,"realtimeAfterLocal":1567993305.4809113,"realtimeDuration":0.08208107948303223,"realtimeSinceSessionStart":14365.00915145874,"realtimeSinceBoot":29606.85915145874,"gitDir":"/home/simon/git/resh","gitRealDir":"/home/simon/git/resh","gitOriginRemote":"git@github.com:curusarn/resh.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"737bc0a4df38","cmdLength":0} -{"cmdLine":"git c \"add sanitized flag to record, add Enrich() to record\"","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"93998b68-ec48-4e48-9e4a-b37b39f5439e","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/resh","pwdAfter":"/home/simon/git/resh","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/resh","realPwdAfter":"/home/simon/git/resh","pid":9463,"sessionPid":9463,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1568063976.9103937,"realtimeAfter":1568063976.9326868,"realtimeBeforeLocal":1568071176.9103937,"realtimeAfterLocal":1568071176.9326868,"realtimeDuration":0.0222930908203125,"realtimeSinceSessionStart":92236.52071499825,"realtimeSinceBoot":107478.37071499825,"gitDir":"/home/simon/git/resh","gitRealDir":"/home/simon/git/resh","gitOriginRemote":"git@github.com:curusarn/resh.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"737bc0a4df38","cmdLength":0} -{"cmdLine":"git s","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"93998b68-ec48-4e48-9e4a-b37b39f5439e","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/resh","pwdAfter":"/home/simon/git/resh","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/resh","realPwdAfter":"/home/simon/git/resh","pid":9463,"sessionPid":9463,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1568063978.2340608,"realtimeAfter":1568063978.252463,"realtimeBeforeLocal":1568071178.2340608,"realtimeAfterLocal":1568071178.252463,"realtimeDuration":0.0184023380279541,"realtimeSinceSessionStart":92237.84438204765,"realtimeSinceBoot":107479.69438204766,"gitDir":"/home/simon/git/resh","gitRealDir":"/home/simon/git/resh","gitOriginRemote":"git@github.com:curusarn/resh.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"737bc0a4df38","cmdLength":0} -{"cmdLine":"git a evaluate/results.go ","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"93998b68-ec48-4e48-9e4a-b37b39f5439e","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/resh","pwdAfter":"/home/simon/git/resh","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/resh","realPwdAfter":"/home/simon/git/resh","pid":9463,"sessionPid":9463,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1568063989.0446353,"realtimeAfter":1568063989.2452207,"realtimeBeforeLocal":1568071189.0446353,"realtimeAfterLocal":1568071189.2452207,"realtimeDuration":0.20058536529541016,"realtimeSinceSessionStart":92248.65495657921,"realtimeSinceBoot":107490.50495657921,"gitDir":"/home/simon/git/resh","gitRealDir":"/home/simon/git/resh","gitOriginRemote":"git@github.com:curusarn/resh.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"737bc0a4df38","cmdLength":0} -{"cmdLine":"sudo pacman -S python-pip","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"93998b68-ec48-4e48-9e4a-b37b39f5439e","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/resh","pwdAfter":"/home/simon/git/resh","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/resh","realPwdAfter":"/home/simon/git/resh","pid":9463,"sessionPid":9463,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1568072068.3557143,"realtimeAfter":1568072070.7509863,"realtimeBeforeLocal":1568079268.3557143,"realtimeAfterLocal":1568079270.7509863,"realtimeDuration":2.3952720165252686,"realtimeSinceSessionStart":100327.96603560448,"realtimeSinceBoot":115569.81603560448,"gitDir":"/home/simon/git/resh","gitRealDir":"/home/simon/git/resh","gitOriginRemote":"git@github.com:curusarn/resh.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"737bc0a4df38","cmdLength":0} -{"cmdLine":"pip3 install matplotlib","exitCode":1,"shell":"bash","uname":"Linux","sessionId":"93998b68-ec48-4e48-9e4a-b37b39f5439e","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/resh","pwdAfter":"/home/simon/git/resh","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/resh","realPwdAfter":"/home/simon/git/resh","pid":9463,"sessionPid":9463,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1568072088.5575967,"realtimeAfter":1568072094.372314,"realtimeBeforeLocal":1568079288.5575967,"realtimeAfterLocal":1568079294.372314,"realtimeDuration":5.8147172927856445,"realtimeSinceSessionStart":100348.16791796684,"realtimeSinceBoot":115590.01791796685,"gitDir":"/home/simon/git/resh","gitRealDir":"/home/simon/git/resh","gitOriginRemote":"git@github.com:curusarn/resh.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"737bc0a4df38","cmdLength":0} -{"cmdLine":"sudo pip3 install matplotlib","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"93998b68-ec48-4e48-9e4a-b37b39f5439e","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/resh","pwdAfter":"/home/simon/git/resh","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/resh","realPwdAfter":"/home/simon/git/resh","pid":9463,"sessionPid":9463,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1568072106.138616,"realtimeAfter":1568072115.1124601,"realtimeBeforeLocal":1568079306.138616,"realtimeAfterLocal":1568079315.1124601,"realtimeDuration":8.973844051361084,"realtimeSinceSessionStart":100365.7489373684,"realtimeSinceBoot":115607.5989373684,"gitDir":"/home/simon/git/resh","gitRealDir":"/home/simon/git/resh","gitOriginRemote":"git@github.com:curusarn/resh.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"737bc0a4df38","cmdLength":0} -{"cmdLine":"./resh-evaluate --plotting-script evaluate/resh-evaluate-plot.py --input ~/git/resh_private/history_data/simon/dell/resh_history.json ","exitCode":130,"shell":"bash","uname":"Linux","sessionId":"93998b68-ec48-4e48-9e4a-b37b39f5439e","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/resh","pwdAfter":"/home/simon/git/resh","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/resh","realPwdAfter":"/home/simon/git/resh","pid":9463,"sessionPid":9463,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1568076266.9364285,"realtimeAfter":1568076288.1131275,"realtimeBeforeLocal":1568083466.9364285,"realtimeAfterLocal":1568083488.1131275,"realtimeDuration":21.176698923110962,"realtimeSinceSessionStart":104526.54674983025,"realtimeSinceBoot":119768.39674983025,"gitDir":"/home/simon/git/resh","gitRealDir":"/home/simon/git/resh","gitOriginRemote":"git@github.com:curusarn/resh.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.1","reshRevision":"737bc0a4df38","cmdLength":0} -{"cmdLine":"git c \"Add a bunch of useless comments to make linter happy\"","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"04050353-a97d-4435-9248-f47dd08b2f2a","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/resh","pwdAfter":"/home/simon/git/resh","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/resh","realPwdAfter":"/home/simon/git/resh","pid":14702,"sessionPid":14702,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1569456045.8763022,"realtimeAfter":1569456045.9030173,"realtimeBeforeLocal":1569463245.8763022,"realtimeAfterLocal":1569463245.9030173,"realtimeDuration":0.02671504020690918,"realtimeSinceSessionStart":2289.789242744446,"realtimeSinceBoot":143217.91924274445,"gitDir":"/home/simon/git/resh","gitRealDir":"/home/simon/git/resh","gitOriginRemote":"git@github.com:curusarn/resh.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.3","reshRevision":"188d8b420493","sanitized":false} -{"cmdLine":"fuck","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"a4aadf03-610d-4731-ba94-5b7ce21e7bb9","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/resh","pwdAfter":"/home/simon/git/resh","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/resh","realPwdAfter":"/home/simon/git/resh","pid":3413,"sessionPid":3413,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1569687682.4250975,"realtimeAfter":1569687682.5877323,"realtimeBeforeLocal":1569694882.4250975,"realtimeAfterLocal":1569694882.5877323,"realtimeDuration":0.16263484954833984,"realtimeSinceSessionStart":264603.49496507645,"realtimeSinceBoot":374854.48496507644,"gitDir":"/home/simon/git/resh","gitRealDir":"/home/simon/git/resh","gitOriginRemote":"git@github.com:curusarn/resh.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.3","reshRevision":"188d8b420493","sanitized":false} -{"cmdLine":"code .","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"87c7ab14-ae51-408d-adbc-fc4f9d28de6e","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/resh","pwdAfter":"/home/simon/git/resh","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/resh","realPwdAfter":"/home/simon/git/resh","pid":31947,"sessionPid":31947,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1569709366.523767,"realtimeAfter":1569709367.516908,"realtimeBeforeLocal":1569716566.523767,"realtimeAfterLocal":1569716567.516908,"realtimeDuration":0.9931409358978271,"realtimeSinceSessionStart":23846.908839941025,"realtimeSinceBoot":396539.888839941,"gitDir":"/home/simon/git/resh","gitRealDir":"/home/simon/git/resh","gitOriginRemote":"git@github.com:curusarn/resh.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.3","reshRevision":"188d8b420493","sanitized":false} -{"cmdLine":"make test","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"87c7ab14-ae51-408d-adbc-fc4f9d28de6e","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon/git/resh","pwdAfter":"/home/simon/git/resh","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon/git/resh","realPwdAfter":"/home/simon/git/resh","pid":31947,"sessionPid":31947,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1569709371.89966,"realtimeAfter":1569709377.430194,"realtimeBeforeLocal":1569716571.89966,"realtimeAfterLocal":1569716577.430194,"realtimeDuration":5.530533790588379,"realtimeSinceSessionStart":23852.284733057022,"realtimeSinceBoot":396545.264733057,"gitDir":"/home/simon/git/resh","gitRealDir":"/home/simon/git/resh","gitOriginRemote":"git@github.com:curusarn/resh.git","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.3","reshRevision":"188d8b420493","sanitized":false} -{"cmdLine":"mkdir ~/git/resh/testdata","exitCode":0,"shell":"bash","uname":"Linux","sessionId":"71529b60-2e7b-4d5b-8dc1-6d0740b58e9e","cols":"211","lines":"56","home":"/home/simon","lang":"en_US.UTF-8","lcAll":"","login":"simon","pwd":"/home/simon","pwdAfter":"/home/simon","shellEnv":"/bin/bash","term":"xterm-256color","realPwd":"/home/simon","realPwdAfter":"/home/simon","pid":21224,"sessionPid":21224,"host":"simon-pc","hosttype":"x86_64","ostype":"linux-gnu","machtype":"x86_64-pc-linux-gnu","shlvl":1,"timezoneBefore":"+0200","timezoneAfter":"+0200","realtimeBefore":1569709838.4642656,"realtimeAfter":1569709838.4718792,"realtimeBeforeLocal":1569717038.4642656,"realtimeAfterLocal":1569717038.4718792,"realtimeDuration":0.007613658905029297,"realtimeSinceSessionStart":9.437154054641724,"realtimeSinceBoot":397011.02715405467,"gitDir":"","gitRealDir":"","gitOriginRemote":"","machineId":"c70365240bc647f09e2490722cc8186b","osReleaseId":"manjaro","osReleaseVersionId":"","osReleaseIdLike":"arch","osReleaseName":"Manjaro Linux","osReleasePrettyName":"Manjaro Linux","reshUuid":"","reshVersion":"1.1.3","reshRevision":"188d8b420493","sanitized":false} diff --git a/internal/recutil/recutil.go b/internal/recutil/recutil.go index 96d8baa..e2b3c85 100644 --- a/internal/recutil/recutil.go +++ b/internal/recutil/recutil.go @@ -2,93 +2,50 @@ package recutil import ( "errors" - "net/url" - "strings" "github.com/curusarn/resh/internal/record" - "github.com/mattn/go-shellwords" - giturls "github.com/whilp/git-urls" + "github.com/curusarn/resh/internal/recordint" ) -// NormalizeGitRemote helper -func NormalizeGitRemote(gitRemote string) string { - if strings.HasSuffix(gitRemote, ".git") { - gitRemote = gitRemote[:len(gitRemote)-4] - } - parsedURL, err := giturls.Parse(gitRemote) - if err != nil { - // TODO: log this error - return gitRemote - } - if parsedURL.User == nil || parsedURL.User.Username() == "" { - parsedURL.User = url.User("git") - } - // TODO: figure out what scheme we want - parsedURL.Scheme = "git+ssh" - return parsedURL.String() -} - +// TODO: reintroduce validation // Validate returns error if the record is invalid -func Validate(r *record.V1) error { - if r.CmdLine == "" { - return errors.New("There is no CmdLine") - } - if r.RealtimeBefore == 0 || r.RealtimeAfter == 0 { - return errors.New("There is no Time") - } - if r.RealtimeBeforeLocal == 0 || r.RealtimeAfterLocal == 0 { - return errors.New("There is no Local Time") - } - if r.RealPwd == "" || r.RealPwdAfter == "" { - return errors.New("There is no Real Pwd") - } - if r.Pwd == "" || r.PwdAfter == "" { - return errors.New("There is no Pwd") - } - return nil -} +// func Validate(r *record.V1) error { +// if r.CmdLine == "" { +// return errors.New("There is no CmdLine") +// } +// if r.Time == 0 { +// return errors.New("There is no Time") +// } +// if r.RealPwd == "" { +// return errors.New("There is no Real Pwd") +// } +// if r.Pwd == "" { +// return errors.New("There is no Pwd") +// } +// return nil +// } +// TODO: maybe more to a more appropriate place +// TODO: cleanup the interface - stop modifying the part1 and returning a ew record at the same time // Merge two records (part1 - collect + part2 - postcollect) -func Merge(r1 *record.V1, r2 *record.V1) error { - if r1.PartOne == false || r2.PartOne { - return errors.New("Expected part1 and part2 of the same record - usage: Merge(part1, part2)") - } +func Merge(r1 *recordint.Collect, r2 *recordint.Collect) (record.V1, error) { if r1.SessionID != r2.SessionID { - return errors.New("Records to merge are not from the same sesion - r1:" + r1.SessionID + " r2:" + r2.SessionID) + return record.V1{}, errors.New("Records to merge are not from the same sesion - r1:" + r1.SessionID + " r2:" + r2.SessionID) } - if r1.CmdLine != r2.CmdLine { - return errors.New("Records to merge are not parts of the same records - r1:" + r1.CmdLine + " r2:" + r2.CmdLine) + if r1.Rec.RecordID != r2.Rec.RecordID { + return record.V1{}, errors.New("Records to merge do not have the same ID - r1:" + r1.Rec.RecordID + " r2:" + r2.Rec.RecordID) } - if r1.RecordID != r2.RecordID { - return errors.New("Records to merge do not have the same ID - r1:" + r1.RecordID + " r2:" + r2.RecordID) - } - r1.ExitCode = r2.ExitCode - r1.Duration = r2.Duration - r1.PartsMerged = true - r1.PartOne = false - return nil -} + r := recordint.Collect{ + SessionID: r1.SessionID, + Shlvl: r1.Shlvl, + SessionPID: r1.SessionPID, -// GetCommandAndFirstWord func -func GetCommandAndFirstWord(cmdLine string) (string, string, error) { - args, err := shellwords.Parse(cmdLine) - if err != nil { - // Println("shellwords Error:", err, " (cmdLine: <", cmdLine, "> )") - return "", "", err - } - if len(args) == 0 { - return "", "", nil - } - i := 0 - for true { - // commands in shell sometimes look like this `variable=something command argument otherArgument --option` - // to get the command we skip over tokens that contain '=' - if strings.ContainsRune(args[i], '=') && len(args) > i+1 { - i++ - continue - } - return args[i], args[0], nil + Rec: r1.Rec, } - return "ERROR", "ERROR", errors.New("failed to retrieve first word of command") + r.Rec.ExitCode = r2.Rec.ExitCode + r.Rec.Duration = r2.Rec.Duration + r.Rec.PartOne = false + r.Rec.PartsNotMerged = false + return r.Rec, nil } diff --git a/internal/searchapp/item.go b/internal/searchapp/item.go index c015428..33fc827 100644 --- a/internal/searchapp/item.go +++ b/internal/searchapp/item.go @@ -7,7 +7,7 @@ import ( "strings" "time" - "github.com/curusarn/resh/internal/records" + "github.com/curusarn/resh/internal/recordint" "golang.org/x/exp/utf8string" ) @@ -18,7 +18,7 @@ const dots = "…" type Item struct { isRaw bool - realtimeBefore float64 + time float64 // [host:]pwd differentHost bool @@ -105,8 +105,8 @@ func (i Item) DrawStatusLine(compactRendering bool, printedLineLength, realLineL if i.isRaw { return splitStatusLineToLines(i.CmdLine, printedLineLength, realLineLength) } - secs := int64(i.realtimeBefore) - nsecs := int64((i.realtimeBefore - float64(secs)) * 1e9) + secs := int64(i.time) + nsecs := int64((i.time - float64(secs)) * 1e9) tm := time.Unix(secs, nsecs) const timeFormat = "2006-01-02 15:04:05" timeString := tm.Format(timeFormat) @@ -142,8 +142,8 @@ func (i Item) DrawItemColumns(compactRendering bool, debug bool) ItemColumns { // DISPLAY // DISPLAY > date - secs := int64(i.realtimeBefore) - nsecs := int64((i.realtimeBefore - float64(secs)) * 1e9) + secs := int64(i.time) + nsecs := int64((i.time - float64(secs)) * 1e9) tm := time.Unix(secs, nsecs) var date string @@ -314,7 +314,7 @@ func properMatch(str, term, padChar string) bool { // NewItemFromRecordForQuery creates new item from record based on given query // returns error if the query doesn't match the record -func NewItemFromRecordForQuery(record records.CliRecord, query Query, debug bool) (Item, error) { +func NewItemFromRecordForQuery(record recordint.SearchApp, query Query, debug bool) (Item, error) { // Use numbers that won't add up to same score for any number of query words // query score weigth 1.51 const hitScore = 1.517 // 1 * 1.51 @@ -411,10 +411,10 @@ func NewItemFromRecordForQuery(record records.CliRecord, query Query, debug bool // if score <= 0 && !anyHit { // return Item{}, errors.New("no match for given record and query") // } - score += record.RealtimeBefore * timeScoreCoef + score += record.Time * timeScoreCoef it := Item{ - realtimeBefore: record.RealtimeBefore, + time: record.Time, differentHost: differentHost, host: record.Host, @@ -470,7 +470,7 @@ type RawItem struct { // NewRawItemFromRecordForQuery creates new item from record based on given query // returns error if the query doesn't match the record -func NewRawItemFromRecordForQuery(record records.CliRecord, terms []string, debug bool) (RawItem, error) { +func NewRawItemFromRecordForQuery(record recordint.SearchApp, terms []string, debug bool) (RawItem, error) { const hitScore = 1.0 const hitScoreConsecutive = 0.01 const properMatchScore = 0.3 @@ -489,7 +489,7 @@ func NewRawItemFromRecordForQuery(record records.CliRecord, terms []string, debu cmd = strings.ReplaceAll(cmd, term, highlightMatch(term)) } } - score += record.RealtimeBefore * timeScoreCoef + score += record.Time * timeScoreCoef // KEY for deduplication key := record.CmdLine diff --git a/internal/searchapp/test.go b/internal/searchapp/test.go index 36d55e4..9a2d284 100644 --- a/internal/searchapp/test.go +++ b/internal/searchapp/test.go @@ -3,20 +3,24 @@ package searchapp import ( "github.com/curusarn/resh/internal/histcli" "github.com/curusarn/resh/internal/msg" - "github.com/curusarn/resh/internal/records" + "github.com/curusarn/resh/internal/recio" "go.uber.org/zap" ) // LoadHistoryFromFile ... func LoadHistoryFromFile(sugar *zap.SugaredLogger, historyPath string, numLines int) msg.CliResponse { - recs := records.LoadFromFile(sugar, historyPath) + rio := recio.New(sugar) + recs, _, err := rio.ReadFile(historyPath) + if err != nil { + sugar.Panicf("failed to read hisotry file: %w", err) + } if numLines != 0 && numLines < len(recs) { recs = recs[:numLines] } cliRecords := histcli.New() for i := len(recs) - 1; i >= 0; i-- { rec := recs[i] - cliRecords.AddRecord(rec) + cliRecords.AddRecord(&rec) } - return msg.CliResponse{CliRecords: cliRecords.List} + return msg.CliResponse{Records: cliRecords.List} } diff --git a/internal/sesswatch/sesswatch.go b/internal/sesswatch/sesswatch.go index e5a55ec..b20bb61 100644 --- a/internal/sesswatch/sesswatch.go +++ b/internal/sesswatch/sesswatch.go @@ -4,7 +4,7 @@ import ( "sync" "time" - "github.com/curusarn/resh/internal/records" + "github.com/curusarn/resh/internal/recordint" "github.com/mitchellh/go-ps" "go.uber.org/zap" ) @@ -21,7 +21,7 @@ type sesswatch struct { // Go runs the session watcher - watches sessions and sends func Go(sugar *zap.SugaredLogger, - sessionsToWatch chan records.Record, sessionsToWatchRecords chan records.Record, + sessionsToWatch chan recordint.SessionInit, sessionsToWatchRecords chan recordint.Collect, sessionsToDrop []chan string, sleepSeconds uint) { sw := sesswatch{ @@ -33,17 +33,17 @@ func Go(sugar *zap.SugaredLogger, go sw.waiter(sessionsToWatch, sessionsToWatchRecords) } -func (s *sesswatch) waiter(sessionsToWatch chan records.Record, sessionsToWatchRecords chan records.Record) { +func (s *sesswatch) waiter(sessionsToWatch chan recordint.SessionInit, sessionsToWatchRecords chan recordint.Collect) { for { func() { select { - case record := <-sessionsToWatch: + case rec := <-sessionsToWatch: // normal way to start watching a session - id := record.SessionID - pid := record.SessionPID + id := rec.SessionID + pid := rec.SessionPID sugar := s.sugar.With( - "sessionID", record.SessionID, - "sessionPID", record.SessionPID, + "sessionID", rec.SessionID, + "sessionPID", rec.SessionPID, ) s.mutex.Lock() defer s.mutex.Unlock() @@ -52,13 +52,13 @@ func (s *sesswatch) waiter(sessionsToWatch chan records.Record, sessionsToWatchR s.watchedSessions[id] = true go s.watcher(sugar, id, pid) } - case record := <-sessionsToWatchRecords: + case rec := <-sessionsToWatchRecords: // additional safety - watch sessions that were never properly initialized - id := record.SessionID - pid := record.SessionPID + id := rec.SessionID + pid := rec.SessionPID sugar := s.sugar.With( - "sessionID", record.SessionID, - "sessionPID", record.SessionPID, + "sessionID", rec.SessionID, + "sessionPID", rec.SessionPID, ) s.mutex.Lock() defer s.mutex.Unlock() diff --git a/scripts/hooks.sh b/scripts/hooks.sh index a734b7b..20d8c9e 100644 --- a/scripts/hooks.sh +++ b/scripts/hooks.sh @@ -8,30 +8,21 @@ __resh_preexec() { # core __RESH_COLLECT=1 __RESH_CMDLINE="$1" # not local to preserve it for postcollect (useful as sanity check) - local fpath_last_run="$__RESH_XDG_CACHE_HOME/collect_last_run_out.txt" - __resh_collect --cmdLine "$__RESH_CMDLINE" \ - >| "$fpath_last_run" 2>&1 || echo "resh-collect ERROR: $(head -n 1 $fpath_last_run)" + __resh_collect --cmdLine "$__RESH_CMDLINE" } # used for collect and collect --recall __resh_collect() { # posix - local __RESH_COLS="$COLUMNS" - local __RESH_LANG="$LANG" - local __RESH_LC_ALL="$LC_ALL" - local __RESH_LINES="$LINES" local __RESH_PWD="$PWD" # non-posix local __RESH_SHLVL="$SHLVL" - local __RESH_GIT_CDUP; __RESH_GIT_CDUP="$(git rev-parse --show-cdup 2>/dev/null)" - local __RESH_GIT_CDUP_EXIT_CODE=$? local __RESH_GIT_REMOTE; __RESH_GIT_REMOTE="$(git remote get-url origin 2>/dev/null)" local __RESH_GIT_REMOTE_EXIT_CODE=$? local __RESH_PID="$$" # current pid # time - local __RESH_TZ_BEFORE; __RESH_TZ_BEFORE=$(date +%z) # __RESH_RT_BEFORE="$EPOCHREALTIME" __RESH_RT_BEFORE=$(__resh_get_epochrealtime) @@ -54,38 +45,16 @@ __resh_collect() { resh-collect -requireVersion "$__RESH_VERSION" \ -requireRevision "$__RESH_REVISION" \ -shell "$__RESH_SHELL" \ - -uname "$__RESH_UNAME" \ - -sessionId "$__RESH_SESSION_ID" \ - -recordId "$__RESH_RECORD_ID" \ - -cols "$__RESH_COLS" \ + -sessionID "$__RESH_SESSION_ID" \ + -recordID "$__RESH_RECORD_ID" \ -home "$__RESH_HOME" \ - -lang "$__RESH_LANG" \ - -lcAll "$__RESH_LC_ALL" \ - -lines "$__RESH_LINES" \ - -login "$__RESH_LOGIN" \ + -logname "$__RESH_LOGIN" \ -pwd "$__RESH_PWD" \ - -shellEnv "$__RESH_SHELL_ENV" \ - -term "$__RESH_TERM" \ - -pid "$__RESH_PID" \ - -sessionPid "$__RESH_SESSION_PID" \ - -host "$__RESH_HOST" \ - -hosttype "$__RESH_HOSTTYPE" \ - -ostype "$__RESH_OSTYPE" \ - -machtype "$__RESH_MACHTYPE" \ + -sessionPID "$__RESH_SESSION_PID" \ + -hostname "$__RESH_HOST" \ -shlvl "$__RESH_SHLVL" \ - -gitCdup "$__RESH_GIT_CDUP" \ - -gitCdupExitCode "$__RESH_GIT_CDUP_EXIT_CODE" \ -gitRemote "$__RESH_GIT_REMOTE" \ - -gitRemoteExitCode "$__RESH_GIT_REMOTE_EXIT_CODE" \ - -realtimeBefore "$__RESH_RT_BEFORE" \ - -realtimeSession "$__RESH_RT_SESSION" \ - -realtimeSessSinceBoot "$__RESH_RT_SESS_SINCE_BOOT" \ - -timezoneBefore "$__RESH_TZ_BEFORE" \ - -osReleaseId "$__RESH_OS_RELEASE_ID" \ - -osReleaseVersionId "$__RESH_OS_RELEASE_VERSION_ID" \ - -osReleaseIdLike "$__RESH_OS_RELEASE_ID_LIKE" \ - -osReleaseName "$__RESH_OS_RELEASE_NAME" \ - -osReleasePrettyName "$__RESH_OS_RELEASE_PRETTY_NAME" \ + -time "$__RESH_RT_BEFORE" \ "$@" return $? fi @@ -95,20 +64,8 @@ __resh_collect() { __resh_precmd() { local __RESH_EXIT_CODE=$? local __RESH_RT_AFTER - local __RESH_TZ_AFTER - local __RESH_PWD_AFTER - local __RESH_GIT_CDUP_AFTER - local __RESH_GIT_CDUP_EXIT_CODE_AFTER - local __RESH_GIT_REMOTE_AFTER - local __RESH_GIT_REMOTE_EXIT_CODE_AFTER local __RESH_SHLVL="$SHLVL" __RESH_RT_AFTER=$(__resh_get_epochrealtime) - __RESH_TZ_AFTER=$(date +%z) - __RESH_PWD_AFTER="$PWD" - __RESH_GIT_CDUP_AFTER="$(git rev-parse --show-cdup 2>/dev/null)" - __RESH_GIT_CDUP_EXIT_CODE_AFTER=$? - __RESH_GIT_REMOTE_AFTER="$(git remote get-url origin 2>/dev/null)" - __RESH_GIT_REMOTE_EXIT_CODE_AFTER=$? if [ -n "${__RESH_COLLECT}" ]; then if [ "$__RESH_VERSION" != "$(resh-postcollect -version)" ]; then # shellcheck source=shellrc.sh @@ -126,24 +83,14 @@ __resh_precmd() { fi fi if [ "$__RESH_VERSION" = "$(resh-postcollect -version)" ] && [ "$__RESH_REVISION" = "$(resh-postcollect -revision)" ]; then - local fpath_last_run="$__RESH_XDG_CACHE_HOME/postcollect_last_run_out.txt" resh-postcollect -requireVersion "$__RESH_VERSION" \ -requireRevision "$__RESH_REVISION" \ - -cmdLine "$__RESH_CMDLINE" \ - -realtimeBefore "$__RESH_RT_BEFORE" \ + -timeBefore "$__RESH_RT_BEFORE" \ -exitCode "$__RESH_EXIT_CODE" \ - -sessionId "$__RESH_SESSION_ID" \ - -recordId "$__RESH_RECORD_ID" \ - -shell "$__RESH_SHELL" \ + -sessionID "$__RESH_SESSION_ID" \ + -recordID "$__RESH_RECORD_ID" \ -shlvl "$__RESH_SHLVL" \ - -pwdAfter "$__RESH_PWD_AFTER" \ - -gitCdupAfter "$__RESH_GIT_CDUP_AFTER" \ - -gitCdupExitCodeAfter "$__RESH_GIT_CDUP_EXIT_CODE_AFTER" \ - -gitRemoteAfter "$__RESH_GIT_REMOTE_AFTER" \ - -gitRemoteExitCodeAfter "$__RESH_GIT_REMOTE_EXIT_CODE_AFTER" \ - -realtimeAfter "$__RESH_RT_AFTER" \ - -timezoneAfter "$__RESH_TZ_AFTER" \ - >| "$fpath_last_run" 2>&1 || echo "resh-postcollect ERROR: $(head -n 1 $fpath_last_run)" + -timeAfter "$__RESH_RT_AFTER" fi __resh_reset_variables fi diff --git a/scripts/install.sh b/scripts/install.sh index 8d5aba9..336c4cf 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -135,7 +135,7 @@ bin/resh-control completion zsh > ~/.resh/zsh_completion.d/_reshctl echo "Copying more files ..." cp -f scripts/uuid.sh ~/.resh/bin/resh-uuid -cp -f bin/resh-{daemon,control,collect,postcollect,session-init,config} ~/.resh/bin/ +cp -f bin/resh-{daemon,cli,control,collect,postcollect,session-init,config} ~/.resh/bin/ echo "Creating/updating config file ..." ./bin/resh-config-setup @@ -179,7 +179,8 @@ else pkill -SIGTERM "resh-daemon" || true fi # daemon uses xdg path variables -__resh_set_xdg_home_paths +# FIXME: this does not exist anymore +#__resh_set_xdg_home_paths __resh_run_daemon diff --git a/scripts/reshctl.sh b/scripts/reshctl.sh index d043366..69ab09d 100644 --- a/scripts/reshctl.sh +++ b/scripts/reshctl.sh @@ -74,8 +74,6 @@ resh() { elif [ $status_code = 130 ]; then true else - local fpath_last_run="$__RESH_XDG_CACHE_HOME/cli_last_run_out.txt" - echo "$buffer" >| "$fpath_last_run" - echo "resh-cli failed - check '$fpath_last_run' and '~/.resh/cli.log'" + printf "%s" "$buffer" >&2 fi } \ No newline at end of file diff --git a/scripts/shellrc.sh b/scripts/shellrc.sh index 2bc84ee..9092ff6 100644 --- a/scripts/shellrc.sh +++ b/scripts/shellrc.sh @@ -55,7 +55,8 @@ export __RESH_VERSION=$(resh-collect -version) # shellcheck disable=2155 export __RESH_REVISION=$(resh-collect -revision) -__resh_set_xdg_home_paths +# FIXME: this does not exist anymore +# __resh_set_xdg_home_paths __resh_run_daemon diff --git a/scripts/util.sh b/scripts/util.sh index 7383e57..8d616a5 100644 --- a/scripts/util.sh +++ b/scripts/util.sh @@ -47,19 +47,21 @@ __resh_get_epochrealtime() { fi } +# FIXME: figure out if stdout/stderr should be discarded __resh_run_daemon() { if [ -n "${ZSH_VERSION-}" ]; then setopt LOCAL_OPTIONS NO_NOTIFY NO_MONITOR fi - local fpath_last_run="$__RESH_XDG_CACHE_HOME/daemon_last_run_out.txt" if [ "$(uname)" = Darwin ]; then # hotfix - gnohup resh-daemon >| "$fpath_last_run" 2>&1 & disown + # gnohup resh-daemon 2>&1 & disown + gnohup resh-daemon & disown else # TODO: switch to nohup for consistency once you confirm that daemon is # not getting killed anymore on macOS - # nohup resh-daemon >| "$fpath_last_run" 2>&1 & disown - setsid resh-daemon >| "$fpath_last_run" 2>&1 & disown + nohup resh-daemon & disown + #nohup resh-daemon 2>&1 & disown + #setsid resh-daemon 2>&1 & disown fi } @@ -71,7 +73,7 @@ __resh_bash_completion_init() { . ~/.resh/bash_completion.d/_reshctl } -// TODO: redo this +# TODO: redo this __resh_zsh_completion_init() { # NOTE: this is hacky - each completion needs to be added individually # TODO: fix later @@ -131,32 +133,8 @@ __resh_session_init() { if [ "$__RESH_VERSION" = "$(resh-session-init -version)" ] && [ "$__RESH_REVISION" = "$(resh-session-init -revision)" ]; then resh-session-init -requireVersion "$__RESH_VERSION" \ -requireRevision "$__RESH_REVISION" \ - -shell "$__RESH_SHELL" \ - -uname "$__RESH_UNAME" \ -sessionId "$__RESH_SESSION_ID" \ - -cols "$__RESH_COLS" \ - -home "$__RESH_HOME" \ - -lang "$__RESH_LANG" \ - -lcAll "$__RESH_LC_ALL" \ - -lines "$__RESH_LINES" \ - -login "$__RESH_LOGIN" \ - -shellEnv "$__RESH_SHELL_ENV" \ - -term "$__RESH_TERM" \ - -pid "$__RESH_PID" \ - -sessionPid "$__RESH_SESSION_PID" \ - -host "$__RESH_HOST" \ - -hosttype "$__RESH_HOSTTYPE" \ - -ostype "$__RESH_OSTYPE" \ - -machtype "$__RESH_MACHTYPE" \ - -shlvl "$__RESH_SHLVL" \ - -realtimeBefore "$__RESH_RT_BEFORE" \ - -realtimeSession "$__RESH_RT_SESSION" \ - -realtimeSessSinceBoot "$__RESH_RT_SESS_SINCE_BOOT" \ - -timezoneBefore "$__RESH_TZ_BEFORE" \ - -osReleaseId "$__RESH_OS_RELEASE_ID" \ - -osReleaseVersionId "$__RESH_OS_RELEASE_VERSION_ID" \ - -osReleaseIdLike "$__RESH_OS_RELEASE_ID_LIKE" \ - -osReleaseName "$__RESH_OS_RELEASE_NAME" \ - -osReleasePrettyName "$__RESH_OS_RELEASE_PRETTY_NAME" - fi + -sessionPid "$__RESH_SESSION_PID" + fi + } diff --git a/scripts/widgets.sh b/scripts/widgets.sh index fd0a0b9..e8acd55 100644 --- a/scripts/widgets.sh +++ b/scripts/widgets.sh @@ -16,8 +16,6 @@ __resh_widget_control_R() { local git_remote; git_remote="$(git remote get-url origin 2>/dev/null)" BUFFER=$(resh-cli --sessionID "$__RESH_SESSION_ID" --host "$__RESH_HOST" --pwd "$PWD" --gitOriginRemote "$git_remote" --query "$BUFFER") status_code=$? - local fpath_last_run="$__RESH_XDG_CACHE_HOME/cli_last_run_out.txt" - touch "$fpath_last_run" if [ $status_code = 111 ]; then # execute if [ -n "${ZSH_VERSION-}" ]; then @@ -35,8 +33,8 @@ __resh_widget_control_R() { bind -x '"\u[32~": __resh_nop' fi else - echo "$BUFFER" >| "$fpath_last_run" - echo "# RESH SEARCH APP failed - sorry for the inconvinience - check '$fpath_last_run' and '~/.resh/cli.log'" + echo "RESH SEARCH APP failed" + printf "%s" "$buffer" >&2 BUFFER="$PREVBUFFER" fi CURSOR=${#BUFFER}