1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2025-04-29 13:53:10 +00:00

Make commits using git executable

This commit is contained in:
Timur Ismagilov 2020-08-27 21:27:57 +05:00
parent 813bbcf954
commit e004f653bd
5 changed files with 86 additions and 84 deletions

1
data

@ -1 +0,0 @@
Subproject commit b2e78031973e4a6844d943333e823c0714e7a673

58
history/common.go Normal file
View File

@ -0,0 +1,58 @@
package history
import (
"bytes"
"fmt"
"log"
"os/exec"
"strconv"
"time"
"github.com/bouncepaw/mycorrhiza/util"
)
// Revision represents a revision, duh. Hash is usually short. Username is extracted from email.
type Revision struct {
Hash string
Username string
Time time.Time
Message string
}
// Path to git executable. Set at init()
var gitpath string
func init() {
path, err := exec.LookPath("git")
if err != nil {
log.Fatal("Cound not find the git executable. Check your $PATH.")
} else {
log.Println("Git path is", path)
}
gitpath = path
}
// I pronounce it as [gɪt͡ʃ].
func gitsh(args ...string) (out bytes.Buffer, err error) {
fmt.Printf("$ %v\n", args)
cmd := exec.Command(gitpath, args...)
cmd.Dir = util.WikiDir
b, err := cmd.CombinedOutput()
if err != nil {
log.Println("gitsh:", err)
}
return *bytes.NewBuffer(b), err
}
// Convert a UNIX timestamp as string into a time. If nil is returned, it means that the timestamp could not be converted.
func unixTimestampAsTime(ts string) *time.Time {
i, err := strconv.ParseInt(ts, 10, 64)
if err != nil {
return nil
}
tm := time.Unix(i, 0)
return &tm
}

View File

@ -3,12 +3,9 @@ package history
import ( import (
"fmt" "fmt"
"log" "log"
"os"
"time"
"github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/util"
"github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5"
// "github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object" "github.com/go-git/go-git/v5/plumbing/object"
) )
@ -33,6 +30,8 @@ func Start(wikiDir string) {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
gitsh("config", "user.name", "wikimind")
gitsh("config", "user.email", "wikimind@mycorrhiza")
log.Println("Wiki repository found") log.Println("Wiki repository found")
} }
@ -41,7 +40,8 @@ type HistoryOp struct {
opType OpType opType OpType
userMsg string userMsg string
signature *object.Signature signature *object.Signature
isDone bool name string
email string
} }
func Operation(opType OpType) *HistoryOp { func Operation(opType OpType) *HistoryOp {
@ -52,66 +52,55 @@ func Operation(opType OpType) *HistoryOp {
return hop return hop
} }
// WithFiles stages all passed `paths`. Paths can be rooted or not. func (hop *HistoryOp) gitop(args ...string) *HistoryOp {
func (hop *HistoryOp) WithFiles(paths ...string) *HistoryOp { out, err := gitsh(args...)
for _, path := range paths { fmt.Println("out:", out.String())
if _, err := Worktree.Add(util.ShorterPath(path)); err != nil { if err != nil {
log.Println(err)
hop.Errs = append(hop.Errs, err) hop.Errs = append(hop.Errs, err)
} }
}
return hop return hop
} }
// WithFiles stages all passed `paths`. Paths can be rooted or not.
func (hop *HistoryOp) WithFiles(paths ...string) *HistoryOp {
for i, path := range paths {
paths[i] = util.ShorterPath(path)
}
return hop.gitop(append([]string{"add"}, paths...)...)
}
// WithMsg sets what message will be used for the future commit. If user message exceeds one line, it is stripped down. // WithMsg sets what message will be used for the future commit. If user message exceeds one line, it is stripped down.
func (hop *HistoryOp) WithMsg(userMsg string) *HistoryOp { func (hop *HistoryOp) WithMsg(userMsg string) *HistoryOp {
// Isn't it too imperative?
var firstLine string
for _, ch := range userMsg { for _, ch := range userMsg {
if ch == '\r' || ch == '\n' { if ch == '\r' || ch == '\n' {
break break
} }
firstLine += string(ch) hop.userMsg += string(ch)
} }
hop.userMsg = firstLine
return hop return hop
} }
// WithSignature sets a signature for the future commit. You need to pass a username only, the rest is upon us (including email and time). // WithSignature sets a signature for the future commit. You need to pass a username only, the rest is upon us (including email and time).
func (hop *HistoryOp) WithSignature(username string) *HistoryOp { func (hop *HistoryOp) WithSignature(username string) *HistoryOp {
hop.signature = &object.Signature{ hop.name = username
Name: username, hop.email = username + "@mycorrhiza" // A fake email, why not
// A fake email, why not
Email: username + "@mycorrhiza",
When: time.Now(),
}
return hop return hop
} }
// Apply applies history operation by doing the commit. You can't apply the same operation more than once. // Apply applies history operation by doing the commit.
func (hop *HistoryOp) Apply() *HistoryOp { func (hop *HistoryOp) Apply() *HistoryOp {
if !hop.isDone { hop.gitop(
opts := &git.CommitOptions{ "commit",
All: false, "--author='"+hop.name+" <"+hop.email+">'",
Author: hop.signature, "--message="+hop.userMsg,
} )
err := opts.Validate(WikiRepo)
if err != nil {
hop.Errs = append(hop.Errs, err)
}
// TODO: work on this section:
_, err = Worktree.Commit(hop.userMsg, opts)
if err != nil {
hop.Errs = append(hop.Errs, err)
}
}
return hop return hop
} }
// Rename renames from `from` to `to`. NB. It uses os.Rename internally rather than git.Move because git.Move works wrong for some reason. // Rename renames from `from` to `to`. NB. It uses os.Rename internally rather than git.Move because git.Move works wrong for some reason.
func Rename(from, to string) error { func Rename(from, to string) error {
log.Println(util.ShorterPath(from), util.ShorterPath(to)) log.Println(util.ShorterPath(from), util.ShorterPath(to))
err := os.Rename(from, to) _, err := gitsh("mv", from, to)
return err return err
} }

View File

@ -1,46 +1,11 @@
package history package history
import ( import (
"bytes"
"fmt" "fmt"
"log"
"os/exec"
"regexp" "regexp"
"strconv"
"strings" "strings"
"time"
) )
type Revision struct {
Hash string
Username string
Time time.Time
Message string
}
var gitpath string
func init() {
path, err := exec.LookPath("git")
if err != nil {
log.Fatal("Cound not find the git executable. Check your $PATH.")
} else {
log.Println("Git path is", path)
}
gitpath = path
}
// I pronounce it as [gɪt͡ʃ].
func gitsh(args ...string) (out bytes.Buffer, err error) {
cmd := exec.Command(gitpath, args...)
cmd.Stdout = &out
cmd.Run()
if err != nil {
log.Println("gitsh:", err)
}
return out, err
}
func Revisions(filepath string) ([]Revision, error) { func Revisions(filepath string) ([]Revision, error) {
if filepath == "" { if filepath == "" {
return []Revision{}, nil return []Revision{}, nil
@ -64,15 +29,6 @@ func Revisions(filepath string) ([]Revision, error) {
return revs, err return revs, err
} }
func unixTimestampAsTime(ts string) *time.Time {
i, err := strconv.ParseInt(ts, 10, 64)
if err != nil {
return nil
}
tm := time.Unix(i, 0)
return &tm
}
// This regex is wrapped in "". For some reason, these quotes appear at some time and we have to get rid of them. // This regex is wrapped in "". For some reason, these quotes appear at some time and we have to get rid of them.
var revisionLinePattern = regexp.MustCompile("\"(.*)\t(.*)@.*\t(.*)\t(.*)\"") var revisionLinePattern = regexp.MustCompile("\"(.*)\t(.*)@.*\t(.*)\t(.*)\"")

@ -1 +1 @@
Subproject commit 2f58d4e9663806496d7edfdeb24098abe986f454 Subproject commit e0e48d39b81968be9c5b00cac6b66cd68c1db3ce