Compare commits

...

4 Commits

Author SHA1 Message Date
lawl baa0d58a47 Fix a bug in DB migration 2021-04-05 14:37:37 +02:00
Albert S. 163429138c search(): Allow searching by timestamps 2021-04-05 14:22:05 +02:00
Albert S. 2af0c1d551 add(): Log current timestamp too 2021-04-05 14:21:54 +02:00
Albert S. 595595c4cb search: Allow searching for cwd 2021-04-05 13:15:20 +02:00
3 changed files with 60 additions and 22 deletions

5
go.mod
View File

@ -2,4 +2,7 @@ module hs9001
go 1.16
require modernc.org/sqlite v1.10.0
require (
github.com/tj/go-naturaldate v1.3.0
modernc.org/sqlite v1.10.0
)

15
go.sum
View File

@ -1,3 +1,5 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo=
@ -8,8 +10,17 @@ github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHX
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/tj/assert v0.0.0-20190920132354-ee03d75cd160 h1:NSWpaDaurcAJY7PkL8Xt0PhZE7qpvbZl5ljd8r6U0bI=
github.com/tj/assert v0.0.0-20190920132354-ee03d75cd160/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0=
github.com/tj/go-naturaldate v1.3.0 h1:OgJIPkR/Jk4bFMBLbxZ8w+QUxwjqSvzd9x+yXocY4RI=
github.com/tj/go-naturaldate v1.3.0/go.mod h1:rpUbjivDKiS1BlfMGc2qUKNZ/yxgthOfmytQs8d8hKk=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@ -39,6 +50,10 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
modernc.org/cc/v3 v3.31.5-0.20210308123301-7a3e9dab9009 h1:u0oCo5b9wyLr++HF3AN9JicGhkUxJhMz51+8TIZH9N0=
modernc.org/cc/v3 v3.31.5-0.20210308123301-7a3e9dab9009/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878=
modernc.org/ccgo/v3 v3.9.0 h1:JbcEIqjw4Agf+0g3Tc85YvfYqkkFOv6xBwS4zkfqSoA=

62
main.go
View File

@ -11,16 +11,19 @@ import (
"path/filepath"
"regexp"
"strings"
"time"
"github.com/tj/go-naturaldate"
_ "modernc.org/sqlite"
)
type HistoryEntry struct {
id uint32
cmd string
cwd string
hostname string
user string
id uint32
cmd string
cwd string
hostname string
user string
timestamp time.Time
}
func databaseLocation() string {
@ -54,7 +57,7 @@ func initDatabase(conn *sql.DB) {
func migrateDatabase(conn *sql.DB, currentVersion int) {
migrations := []string{
"ALTER TABLE history add column workdir varchar(4096)",
"ALTER TABLE history add column workdir varchar(4096) DEFAULT ''",
}
if !(len(migrations) > currentVersion) {
@ -110,10 +113,11 @@ func NewHistoryEntry(cmd string) HistoryEntry {
log.Panic(err)
}
return HistoryEntry{
user : os.Getenv("USER"),
hostname : hostname,
cmd : cmd,
cwd : wd,
user: os.Getenv("USER"),
hostname: hostname,
cmd: cmd,
cwd: wd,
timestamp: time.Now(),
}
}
@ -128,6 +132,7 @@ func importFromStdin(conn *sql.DB) {
for scanner.Scan() {
entry := NewHistoryEntry(scanner.Text())
entry.cwd = ""
entry.timestamp = time.Unix(0, 0)
add(conn, entry)
}
@ -137,10 +142,10 @@ func importFromStdin(conn *sql.DB) {
}
}
func search(conn *sql.DB, q string) list.List {
queryStmt := "SELECT id, command, workdir, user, hostname FROM history WHERE command LIKE ? ORDER BY timestamp ASC"
func search(conn *sql.DB, q string, workdir string, beginTime time.Time, endTime time.Time) list.List {
queryStmt := "SELECT id, command, workdir, user, hostname FROM history WHERE timestamp BETWEEN datetime(?, 'unixepoch') AND datetime(?, 'unixepoch') AND command LIKE ? AND workdir LIKE ? ORDER BY timestamp ASC"
rows, err := conn.Query(queryStmt, "%"+q+"%")
rows, err := conn.Query(queryStmt, beginTime.Unix(), endTime.Unix(), q, workdir)
if err != nil {
log.Panic(err)
}
@ -167,13 +172,13 @@ func delete(conn *sql.DB, entryId uint32) {
}
}
func add(conn *sql.DB, entry HistoryEntry ) {
stmt, err := conn.Prepare("INSERT INTO history (user, command, hostname, workdir) VALUES (?, ?, ?, ?)")
func add(conn *sql.DB, entry HistoryEntry) {
stmt, err := conn.Prepare("INSERT INTO history (user, command, hostname, workdir, timestamp) VALUES (?, ?, ?, ?, datetime(?, 'unixepoch'))")
if err != nil {
log.Panic(err)
}
_, err = stmt.Exec(entry.user, entry.cmd, entry.hostname, entry.cwd)
_, err = stmt.Exec(entry.user, entry.cmd, entry.hostname, entry.cwd, entry.timestamp.Unix())
if err != nil {
log.Panic(err)
}
@ -255,18 +260,33 @@ func main() {
if len(rs) == 2 {
add(conn, NewHistoryEntry(rs[1]))
}
case "search": fallthrough;
case "search":
fallthrough
case "delete":
var workDir string
var beginTime string
var endTime string
searchCmd.StringVar(&workDir, "workdir", "%", "Search only within this workdir")
searchCmd.StringVar(&beginTime, "begin", "50 years ago", "Start searching from this timeframe")
searchCmd.StringVar(&endTime, "end", "now", "End searching from this timeframe")
searchCmd.Parse(globalargs)
args := searchCmd.Args()
if len(args) < 1 {
fmt.Fprint(os.Stderr, "Please provide the query\n")
os.Exit(1)
beginTimestamp, err := naturaldate.Parse(beginTime, time.Now())
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to convert time string: %s\n", err.Error())
}
endTimeStamp, err := naturaldate.Parse(endTime, time.Now())
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to convert time string: %s\n", err.Error())
}
q := strings.Join(args, " ")
results := search(conn, q)
results := search(conn, "%"+q+"%", workDir, beginTimestamp, endTimeStamp)
for e := results.Front(); e != nil; e = e.Next() {
entry, ok := e.Value.(*HistoryEntry)