mirror of https://github.com/curusarn/resh
Realpaths for before fields are actually evaluated before. Hard prerequisite for any recall functionalitypull/18/head
parent
7b437b6870
commit
b8c00b6c73
@ -0,0 +1,57 @@ |
|||||||
|
package main |
||||||
|
|
||||||
|
import ( |
||||||
|
"encoding/json" |
||||||
|
"log" |
||||||
|
"os" |
||||||
|
|
||||||
|
"github.com/curusarn/resh/pkg/records" |
||||||
|
) |
||||||
|
|
||||||
|
// HistfileWriter - reads records from channel, merges them and wrotes them to file
|
||||||
|
func HistfileWriter(input chan records.Record, outputPath string) { |
||||||
|
sessions := map[string]records.Record{} |
||||||
|
|
||||||
|
for { |
||||||
|
record := <-input |
||||||
|
if record.PartOne { |
||||||
|
if _, found := sessions[record.SessionID]; found { |
||||||
|
log.Println("ERROR: Got another first part of the records before merging the previous one - overwriting!") |
||||||
|
} |
||||||
|
sessions[record.SessionID] = record |
||||||
|
} else { |
||||||
|
part1, found := sessions[record.SessionID] |
||||||
|
if found == false { |
||||||
|
log.Println("ERROR: Got second part of records and nothing to merge it with - ignoring!") |
||||||
|
continue |
||||||
|
} |
||||||
|
delete(sessions, record.SessionID) |
||||||
|
go mergeAndWriteRecord(part1, record, outputPath) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func mergeAndWriteRecord(part1, part2 records.Record, outputPath string) { |
||||||
|
err := part1.Merge(part2) |
||||||
|
if err != nil { |
||||||
|
log.Println("Error while merging", err) |
||||||
|
return |
||||||
|
} |
||||||
|
recJSON, err := json.Marshal(part1) |
||||||
|
if err != nil { |
||||||
|
log.Println("Marshalling error", err) |
||||||
|
return |
||||||
|
} |
||||||
|
f, err := os.OpenFile(outputPath, |
||||||
|
os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) |
||||||
|
if err != nil { |
||||||
|
log.Println("Could not open file", err) |
||||||
|
return |
||||||
|
} |
||||||
|
defer f.Close() |
||||||
|
_, err = f.Write(append(recJSON, []byte("\n")...)) |
||||||
|
if err != nil { |
||||||
|
log.Printf("Error while writing: %v, %s\n", part1, err) |
||||||
|
return |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
package main |
||||||
|
|
||||||
|
import "fmt" |
||||||
|
|
||||||
|
func main() { |
||||||
|
fmt.Println("Hell world") |
||||||
|
} |
||||||
@ -0,0 +1,147 @@ |
|||||||
|
package main |
||||||
|
|
||||||
|
import ( |
||||||
|
"flag" |
||||||
|
"fmt" |
||||||
|
"log" |
||||||
|
"os" |
||||||
|
|
||||||
|
"github.com/BurntSushi/toml" |
||||||
|
"github.com/curusarn/resh/pkg/cfg" |
||||||
|
"github.com/curusarn/resh/pkg/collect" |
||||||
|
"github.com/curusarn/resh/pkg/records" |
||||||
|
|
||||||
|
// "os/exec"
|
||||||
|
"os/user" |
||||||
|
"path/filepath" |
||||||
|
"strconv" |
||||||
|
) |
||||||
|
|
||||||
|
// Version from git set during build
|
||||||
|
var Version string |
||||||
|
|
||||||
|
// Revision from git set during build
|
||||||
|
var Revision string |
||||||
|
|
||||||
|
func main() { |
||||||
|
usr, _ := user.Current() |
||||||
|
dir := usr.HomeDir |
||||||
|
configPath := filepath.Join(dir, "/.config/resh.toml") |
||||||
|
reshUUIDPath := filepath.Join(dir, "/.resh/resh-uuid") |
||||||
|
|
||||||
|
machineIDPath := "/etc/machine-id" |
||||||
|
|
||||||
|
var config cfg.Config |
||||||
|
if _, err := toml.DecodeFile(configPath, &config); err != nil { |
||||||
|
log.Fatal("Error reading config:", err) |
||||||
|
} |
||||||
|
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") |
||||||
|
|
||||||
|
// 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") |
||||||
|
flag.Parse() |
||||||
|
|
||||||
|
if *showVersion == true { |
||||||
|
fmt.Println(Version) |
||||||
|
os.Exit(0) |
||||||
|
} |
||||||
|
if *showRevision == true { |
||||||
|
fmt.Println(Revision) |
||||||
|
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) |
||||||
|
} |
||||||
|
if *requireRevision != "" && *requireRevision != Revision { |
||||||
|
fmt.Println("Please restart/reload this terminal session " + |
||||||
|
"(resh revision: " + Revision + |
||||||
|
"; resh revision of this terminal session: " + *requireRevision + |
||||||
|
")") |
||||||
|
os.Exit(3) |
||||||
|
} |
||||||
|
realtimeAfter, err := strconv.ParseFloat(*rta, 64) |
||||||
|
if err != nil { |
||||||
|
log.Fatal("Flag Parsing error (rta):", err) |
||||||
|
} |
||||||
|
realtimeBefore, err := strconv.ParseFloat(*rtb, 64) |
||||||
|
if err != nil { |
||||||
|
log.Fatal("Flag Parsing error (rtb):", err) |
||||||
|
} |
||||||
|
realtimeDuration := realtimeAfter - realtimeBefore |
||||||
|
|
||||||
|
timezoneAfterOffset := collect.GetTimezoneOffsetInSeconds(*timezoneAfter) |
||||||
|
realtimeAfterLocal := realtimeAfter + timezoneAfterOffset |
||||||
|
|
||||||
|
realPwdAfter, err := filepath.EvalSymlinks(*pwdAfter) |
||||||
|
if err != nil { |
||||||
|
log.Println("err while handling pwdAfter realpath:", err) |
||||||
|
realPwdAfter = "" |
||||||
|
} |
||||||
|
|
||||||
|
gitDirAfter, gitRealDirAfter := collect.GetGitDirs(*gitCdupAfter, *gitCdupExitCodeAfter, *pwdAfter) |
||||||
|
if *gitRemoteExitCodeAfter != 0 { |
||||||
|
*gitRemoteAfter = "" |
||||||
|
} |
||||||
|
|
||||||
|
rec := records.Record{ |
||||||
|
// core
|
||||||
|
BaseRecord: records.BaseRecord{ |
||||||
|
CmdLine: *cmdLine, |
||||||
|
ExitCode: *exitCode, |
||||||
|
SessionID: *sessionID, |
||||||
|
|
||||||
|
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(machineIDPath), |
||||||
|
|
||||||
|
PartOne: false, |
||||||
|
|
||||||
|
ReshUUID: collect.ReadFileContent(reshUUIDPath), |
||||||
|
ReshVersion: Version, |
||||||
|
ReshRevision: Revision, |
||||||
|
}, |
||||||
|
} |
||||||
|
collect.SendRecord(rec, strconv.Itoa(config.Port)) |
||||||
|
} |
||||||
@ -0,0 +1,78 @@ |
|||||||
|
package collect |
||||||
|
|
||||||
|
import ( |
||||||
|
"bytes" |
||||||
|
"encoding/json" |
||||||
|
"io/ioutil" |
||||||
|
"log" |
||||||
|
"net/http" |
||||||
|
"path/filepath" |
||||||
|
"strconv" |
||||||
|
"strings" |
||||||
|
|
||||||
|
"github.com/curusarn/resh/pkg/records" |
||||||
|
) |
||||||
|
|
||||||
|
// SendRecord to daemon
|
||||||
|
func SendRecord(r records.Record, port string) { |
||||||
|
recJSON, err := json.Marshal(r) |
||||||
|
if err != nil { |
||||||
|
log.Fatal("send err 1", err) |
||||||
|
} |
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", "http://localhost:"+port+"/record", |
||||||
|
bytes.NewBuffer(recJSON)) |
||||||
|
if err != nil { |
||||||
|
log.Fatal("send err 2", err) |
||||||
|
} |
||||||
|
req.Header.Set("Content-Type", "application/json") |
||||||
|
|
||||||
|
client := &http.Client{} |
||||||
|
_, err = client.Do(req) |
||||||
|
if err != nil { |
||||||
|
log.Fatal("resh-daemon is not running :(") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ReadFileContent and return it as a string
|
||||||
|
func ReadFileContent(path string) string { |
||||||
|
dat, err := ioutil.ReadFile(path) |
||||||
|
if err != nil { |
||||||
|
return "" |
||||||
|
//log.Fatal("failed to open " + path)
|
||||||
|
} |
||||||
|
return strings.TrimSuffix(string(dat), "\n") |
||||||
|
} |
||||||
|
|
||||||
|
// GetGitDirs based on result of git "cdup" command
|
||||||
|
func GetGitDirs(cdup string, exitCode int, pwd string) (string, string) { |
||||||
|
if exitCode != 0 { |
||||||
|
return "", "" |
||||||
|
} |
||||||
|
abspath := filepath.Clean(filepath.Join(pwd, cdup)) |
||||||
|
realpath, err := filepath.EvalSymlinks(abspath) |
||||||
|
if err != nil { |
||||||
|
log.Println("err while handling git dir paths:", err) |
||||||
|
return "", "" |
||||||
|
} |
||||||
|
return abspath, realpath |
||||||
|
} |
||||||
|
|
||||||
|
// GetTimezoneOffsetInSeconds based on zone returned by date command
|
||||||
|
func GetTimezoneOffsetInSeconds(zone string) float64 { |
||||||
|
// date +%z -> "+0200"
|
||||||
|
hoursStr := zone[:3] |
||||||
|
minsStr := zone[3:] |
||||||
|
hours, err := strconv.Atoi(hoursStr) |
||||||
|
if err != nil { |
||||||
|
log.Println("err while parsing hours in timezone offset:", err) |
||||||
|
return -1 |
||||||
|
} |
||||||
|
mins, err := strconv.Atoi(minsStr) |
||||||
|
if err != nil { |
||||||
|
log.Println("err while parsing mins in timezone offset:", err) |
||||||
|
return -1 |
||||||
|
} |
||||||
|
secs := ((hours * 60) + mins) * 60 |
||||||
|
return float64(secs) |
||||||
|
} |
||||||
Loading…
Reference in new issue