Rich Enhanced Shell History - Contextual shell history for zsh and bash
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
resh/internal/recutil/recutil.go

94 lines
2.6 KiB

package recutil
import (
"errors"
"net/url"
"strings"
"github.com/curusarn/resh/internal/record"
"github.com/mattn/go-shellwords"
giturls "github.com/whilp/git-urls"
)
// 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()
}
// 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
}
// 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)")
}
if r1.SessionID != r2.SessionID {
return 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.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
}
// 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
}
return "ERROR", "ERROR", errors.New("failed to retrieve first word of command")
}