réplica de
https://github.com/quitesimpleorg/hs9001.git
sincronizado 2025-07-01 23:23:49 +02:00
Comparar comentimentos
14 Cometimentos
Autor(a) | SHA1 | Data | |
---|---|---|---|
baa0d58a47 | |||
163429138c | |||
2af0c1d551 | |||
595595c4cb | |||
250af52750 | |||
88362e99a9 | |||
776dcebb04 | |||
1809905992 | |||
305e4300cc | |||
b02911c9b4 | |||
8477ba5bfe | |||
54697be895 | |||
da945dce2d | |||
ee7a0868a8 |
6
LICENSE
Ficheiro normal
6
LICENSE
Ficheiro normal
@ -0,0 +1,6 @@
|
||||
Copyright 2021 lawl (github.com/lawl)
|
||||
Copyright 2021 Albert S. <hs9001 at quitesimple org>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
36
README.md
36
README.md
@ -1,24 +1,44 @@
|
||||
# hs9001
|
||||
hs90001 (history search 9001) is an easy, quite simple bash history enhancement. It simply writes all
|
||||
hs9001 (history search 9001) is an easy, quite simple bash history enhancement. It simply writes all
|
||||
your bash commands into an sqlite database. You can then search this database.
|
||||
|
||||
|
||||
## Setup
|
||||
## Install
|
||||
|
||||
### From source
|
||||
```
|
||||
go build
|
||||
#move hs9001 to a PATH location
|
||||
# Initialize database
|
||||
hs9001 init
|
||||
````
|
||||
```
|
||||
|
||||
### Debian / Ubuntu
|
||||
Latest release can be installed using apt
|
||||
```
|
||||
curl -s https://repo.quitesimple.org/repo.quitesimple.org.asc | sudo apt-key add -
|
||||
echo "deb https://repo.quitesimple.org/debian/ default main" | sudo tee /etc/apt/sources.list.d/quitesimple.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install hs9001
|
||||
```
|
||||
|
||||
### Alpine
|
||||
```
|
||||
wget https://repo.quitesimple.org/repo%40quitesimple.org-5f3d101.rsa.pub -O /etc/apk/repo@quitesimple.org-5f3d101.rsa.pub
|
||||
echo "https://repo.quitesimple.org/alpine/quitesimple/" >> /etc/apk/repositories
|
||||
apk update
|
||||
apk add hs9001
|
||||
```
|
||||
|
||||
|
||||
### Setup / Config
|
||||
|
||||
Add this to .bashrc
|
||||
|
||||
```
|
||||
if [ -n "$PS1" ] ; then
|
||||
PROMPT_COMMAND='hs9001 -ret $? add "$(history 1)"'
|
||||
PROMPT_COMMAND='hs9001 add -ret $? "$(history 1)"'
|
||||
fi
|
||||
```
|
||||
By default, every system user gets his own database. You can override this by overriding the environment variable
|
||||
By default, every system user gets his own database. You can override this by setting the environment variable
|
||||
for all users that should write to your unified database.
|
||||
|
||||
```
|
||||
@ -29,7 +49,7 @@ export HS9001_DB_PATH="/home/db/history.sqlite"
|
||||
### Search
|
||||
|
||||
```
|
||||
hs9001 search "term"
|
||||
hs9001 search [search terms]
|
||||
```
|
||||
|
||||
It is recommended to create an alias for search to make life easier, e. g.:
|
||||
|
5
go.mod
5
go.mod
@ -2,4 +2,7 @@ module hs9001
|
||||
|
||||
go 1.16
|
||||
|
||||
require modernc.org/sqlite v1.10.0 // indirect
|
||||
require (
|
||||
github.com/tj/go-naturaldate v1.3.0
|
||||
modernc.org/sqlite v1.10.0
|
||||
)
|
||||
|
21
go.sum
21
go.sum
@ -1,12 +1,26 @@
|
||||
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=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
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=
|
||||
@ -36,10 +50,15 @@ 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=
|
||||
modernc.org/ccgo/v3 v3.9.0/go.mod h1:nQbgkn8mwzPdp4mm6BT6+p85ugQ7FrGgIcYaE7nSrpY=
|
||||
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
|
||||
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
|
||||
modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
|
||||
modernc.org/libc v1.8.0 h1:Pp4uv9g0csgBMpGPABKtkieF6O5MGhfGo6ZiOdlYfR8=
|
||||
@ -55,8 +74,10 @@ modernc.org/sqlite v1.10.0 h1:0QNqx4EzfZzNEG13sFbS/L+egh0X5WXSckHrxHkySX8=
|
||||
modernc.org/sqlite v1.10.0/go.mod h1:PGzq6qlhyYjL6uVbSgS6WoF7ZopTW/sI7+7p+mb4ZVU=
|
||||
modernc.org/strutil v1.1.0 h1:+1/yCzZxY2pZwwrsbH+4T7BQMoLQ9QiBshRC9eicYsc=
|
||||
modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
|
||||
modernc.org/tcl v1.5.0 h1:euZSUNfE0Fd4W8VqXI1Ly1v7fqDJoBuAV88Ea+SnaSs=
|
||||
modernc.org/tcl v1.5.0/go.mod h1:gb57hj4pO8fRrK54zveIfFXBaMHK3SKJNWcmRw1cRzc=
|
||||
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
|
||||
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
|
||||
modernc.org/z v1.0.1 h1:WyIDpEpAIx4Hel6q/Pcgj/VhaQV5XPJ2I6ryIYbjnpc=
|
||||
modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
|
||||
|
259
main.go
259
main.go
@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"container/list"
|
||||
"database/sql"
|
||||
"flag"
|
||||
"fmt"
|
||||
@ -10,10 +11,21 @@ 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
|
||||
timestamp time.Time
|
||||
}
|
||||
|
||||
func databaseLocation() string {
|
||||
envOverride := os.Getenv("HS9001_DB_PATH")
|
||||
if envOverride != "" {
|
||||
@ -28,6 +40,7 @@ func createConnection() *sql.DB {
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
@ -41,6 +54,73 @@ func initDatabase(conn *sql.DB) {
|
||||
}
|
||||
}
|
||||
|
||||
func migrateDatabase(conn *sql.DB, currentVersion int) {
|
||||
|
||||
migrations := []string{
|
||||
"ALTER TABLE history add column workdir varchar(4096) DEFAULT ''",
|
||||
}
|
||||
|
||||
if !(len(migrations) > currentVersion) {
|
||||
return
|
||||
}
|
||||
|
||||
_, err := conn.Exec("BEGIN;")
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
for _, m := range migrations[currentVersion:] {
|
||||
_, err := conn.Exec(m)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
setDBVersion(conn, len(migrations))
|
||||
|
||||
_, err = conn.Exec("END;")
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func fetchDBVersion(conn *sql.DB) int {
|
||||
rows, err := conn.Query("PRAGMA user_version;")
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
rows.Next()
|
||||
var res int
|
||||
rows.Scan(&res)
|
||||
return res
|
||||
}
|
||||
|
||||
func setDBVersion(conn *sql.DB, ver int) {
|
||||
_, err := conn.Exec(fmt.Sprintf("PRAGMA user_version=%d", ver))
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func NewHistoryEntry(cmd string) HistoryEntry {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
return HistoryEntry{
|
||||
user: os.Getenv("USER"),
|
||||
hostname: hostname,
|
||||
cmd: cmd,
|
||||
cwd: wd,
|
||||
timestamp: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
func importFromStdin(conn *sql.DB) {
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
|
||||
@ -50,7 +130,10 @@ func importFromStdin(conn *sql.DB) {
|
||||
}
|
||||
|
||||
for scanner.Scan() {
|
||||
add(conn, scanner.Text())
|
||||
entry := NewHistoryEntry(scanner.Text())
|
||||
entry.cwd = ""
|
||||
entry.timestamp = time.Unix(0, 0)
|
||||
add(conn, entry)
|
||||
}
|
||||
|
||||
_, err = conn.Exec("END;")
|
||||
@ -59,37 +142,43 @@ func importFromStdin(conn *sql.DB) {
|
||||
}
|
||||
}
|
||||
|
||||
func search(conn *sql.DB, q string) {
|
||||
queryStmt := "SELECT command 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)
|
||||
}
|
||||
|
||||
var result list.List
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var command string
|
||||
err = rows.Scan(&command)
|
||||
var entry HistoryEntry
|
||||
err = rows.Scan(&entry.id, &entry.cmd, &entry.cwd, &entry.user, &entry.hostname)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
fmt.Printf("%s\n", command)
|
||||
result.PushBack(&entry)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func delete(conn *sql.DB, entryId uint32) {
|
||||
queryStmt := "DELETE FROM history WHERE id = ?"
|
||||
|
||||
_, err := conn.Exec(queryStmt, entryId)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func add(conn *sql.DB, cmd string) {
|
||||
user := os.Getenv("USER")
|
||||
hostname, err := os.Hostname()
|
||||
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)
|
||||
}
|
||||
|
||||
stmt, err := conn.Prepare("INSERT INTO history (user, command, hostname) VALUES (?, ?, ?)")
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
_, err = stmt.Exec(user, cmd, hostname)
|
||||
_, err = stmt.Exec(entry.user, entry.cmd, entry.hostname, entry.cwd, entry.timestamp.Unix())
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
@ -120,57 +209,127 @@ func exists(path string) (bool, error) {
|
||||
}
|
||||
|
||||
func printUsage() {
|
||||
fmt.Fprintf(os.Stderr, "Usage: ./hs9001 <add/search/init/import>\n")
|
||||
fmt.Fprintf(os.Stderr, "Usage: ./hs9001 <add/search/import>\n")
|
||||
}
|
||||
|
||||
func main() {
|
||||
var ret int
|
||||
flag.IntVar(&ret, "ret", 0, "Return value of the command to add")
|
||||
flag.Parse()
|
||||
args := flag.Args()
|
||||
argslen := len(args)
|
||||
addCmd := flag.NewFlagSet("add", flag.ExitOnError)
|
||||
searchCmd := flag.NewFlagSet("search", flag.ExitOnError)
|
||||
|
||||
if argslen < 1 {
|
||||
if len(os.Args) < 2 {
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
|
||||
cmd := args[0]
|
||||
cmd := os.Args[1]
|
||||
globalargs := os.Args[2:]
|
||||
|
||||
conn := createConnection()
|
||||
var conn *sql.DB
|
||||
ok, _ := exists(databaseLocation())
|
||||
|
||||
if cmd == "add" {
|
||||
if ret == 23 { // 23 is our secret do not log status code
|
||||
return
|
||||
}
|
||||
if argslen < 2 {
|
||||
fmt.Fprint(os.Stderr, "Error: You need to provide the command to be added")
|
||||
|
||||
}
|
||||
historycmd := args[1]
|
||||
var rgx = regexp.MustCompile("\\s+\\d+\\s+(.*)")
|
||||
rs := rgx.FindStringSubmatch(historycmd)
|
||||
if len(rs) == 2 {
|
||||
add(conn, rs[1])
|
||||
}
|
||||
} else if cmd == "search" {
|
||||
if argslen < 2 {
|
||||
fmt.Fprint(os.Stderr, "Please provide the search query\n")
|
||||
}
|
||||
q := strings.Join(args[1:], " ")
|
||||
search(conn, q)
|
||||
os.Exit(23)
|
||||
} else if cmd == "init" {
|
||||
if !ok {
|
||||
err := os.MkdirAll(filepath.Dir(databaseLocation()), 0755)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
conn = createConnection()
|
||||
initDatabase(conn)
|
||||
} else if cmd == "import" {
|
||||
importFromStdin(conn)
|
||||
} else {
|
||||
fmt.Fprint(os.Stderr, "Error: Unknown command supplied\n\n")
|
||||
conn = createConnection()
|
||||
}
|
||||
|
||||
migrateDatabase(conn, fetchDBVersion(conn))
|
||||
|
||||
switch cmd {
|
||||
case "add":
|
||||
var ret int
|
||||
addCmd.IntVar(&ret, "ret", 0, "Return value of the command to add")
|
||||
addCmd.Parse(globalargs)
|
||||
args := addCmd.Args()
|
||||
|
||||
if ret == 23 { // 23 is our secret do not log status code
|
||||
return
|
||||
}
|
||||
if len(args) < 1 {
|
||||
fmt.Fprint(os.Stderr, "Error: You need to provide the command to be added")
|
||||
|
||||
}
|
||||
historycmd := args[0]
|
||||
var rgx = regexp.MustCompile("\\s+\\d+\\s+(.*)")
|
||||
rs := rgx.FindStringSubmatch(historycmd)
|
||||
if len(rs) == 2 {
|
||||
add(conn, NewHistoryEntry(rs[1]))
|
||||
}
|
||||
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()
|
||||
|
||||
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+"%", workDir, beginTimestamp, endTimeStamp)
|
||||
|
||||
for e := results.Front(); e != nil; e = e.Next() {
|
||||
entry, ok := e.Value.(*HistoryEntry)
|
||||
if !ok {
|
||||
log.Panic("Failed to retrieve entries")
|
||||
}
|
||||
|
||||
fmt.Printf("%s\n", entry.cmd)
|
||||
}
|
||||
|
||||
if cmd == "delete" {
|
||||
|
||||
_, err := conn.Exec("BEGIN;")
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
for e := results.Front(); e != nil; e = e.Next() {
|
||||
entry, ok := e.Value.(*HistoryEntry)
|
||||
if !ok {
|
||||
log.Panic("Failed to retrieve entries")
|
||||
}
|
||||
delete(conn, entry.id)
|
||||
}
|
||||
|
||||
_, err = conn.Exec("END;")
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
_, err = conn.Exec("VACUUM")
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
}
|
||||
os.Exit(23)
|
||||
case "import":
|
||||
importFromStdin(conn)
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "Error: Unknown subcommand '%s' supplied\n\n", cmd)
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
Criar uma nova questão referindo esta
Bloquear um utilizador