init: pristine aerc 0.20.0 source
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
package revctrl
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"git.sr.ht/~rjarry/aerc/lib/log"
|
||||
"git.sr.ht/~rjarry/aerc/lib/pama/models"
|
||||
)
|
||||
|
||||
func init() {
|
||||
register("git", newGit)
|
||||
}
|
||||
|
||||
func newGit(s string) models.RevisionController {
|
||||
return &git{path: strings.TrimSpace(s)}
|
||||
}
|
||||
|
||||
type git struct {
|
||||
path string
|
||||
}
|
||||
|
||||
func (g git) Support() bool {
|
||||
_, exitcode, err := g.do("rev-parse")
|
||||
return exitcode == 0 && err == nil
|
||||
}
|
||||
|
||||
func (g git) Root() (string, error) {
|
||||
s, _, err := g.do("rev-parse", "--show-toplevel")
|
||||
return s, err
|
||||
}
|
||||
|
||||
func (g git) Head() (string, error) {
|
||||
s, _, err := g.do("rev-list", "-n 1", "HEAD")
|
||||
return s, err
|
||||
}
|
||||
|
||||
func (g git) History(commit string) ([]string, error) {
|
||||
s, _, err := g.do("rev-list", "--reverse", fmt.Sprintf("%s..HEAD", commit))
|
||||
return strings.Fields(s), err
|
||||
}
|
||||
|
||||
func (g git) Subject(commit string) string {
|
||||
s, exitcode, err := g.do("log", "-1", "--pretty=%s", commit)
|
||||
if exitcode > 0 || err != nil {
|
||||
return ""
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (g git) Author(commit string) string {
|
||||
s, exitcode, err := g.do("log", "-1", "--pretty=%an", commit)
|
||||
if exitcode > 0 || err != nil {
|
||||
return ""
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (g git) Date(commit string) string {
|
||||
s, exitcode, err := g.do("log", "-1", "--pretty=%as", commit)
|
||||
if exitcode > 0 || err != nil {
|
||||
return ""
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (g git) Drop(commit string) error {
|
||||
_, exitcode, err := g.do("rebase", "--onto", commit+"^", commit)
|
||||
if exitcode > 0 {
|
||||
return fmt.Errorf("failed to drop commit %s", commit)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (g git) Exists(commit string) bool {
|
||||
_, exitcode, err := g.do("merge-base", "--is-ancestor", commit, "HEAD")
|
||||
return exitcode == 0 && err == nil
|
||||
}
|
||||
|
||||
func (g git) Clean() bool {
|
||||
// is a rebase in progress?
|
||||
dirs := []string{"rebase-merge", "rebase-apply"}
|
||||
for _, dir := range dirs {
|
||||
relPath, _, err := g.do("rev-parse", "--git-path", dir)
|
||||
if err == nil {
|
||||
if _, err := os.Stat(filepath.Join(g.path, relPath)); !os.IsNotExist(err) {
|
||||
log.Errorf("%s exists: another rebase in progress..", dir)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
// are there unstaged changes?
|
||||
s, exitcode, err := g.do("diff-index", "HEAD")
|
||||
return len(s) == 0 && exitcode == 0 && err == nil
|
||||
}
|
||||
|
||||
func (g git) CreateWorktree(target, commit string) error {
|
||||
_, exitcode, err := g.do("worktree", "add", target, commit)
|
||||
if exitcode > 0 {
|
||||
return fmt.Errorf("failed to create worktree in %s: %w", target, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (g git) DeleteWorktree(target string) error {
|
||||
_, exitcode, err := g.do("worktree", "remove", target)
|
||||
if exitcode > 0 {
|
||||
return fmt.Errorf("failed to delete worktree in %s: %w", target, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (g git) ApplyCmd() string {
|
||||
// TODO: should we return a *exec.Cmd instead of a string?
|
||||
return fmt.Sprintf("git -C %s am -3 --empty drop", g.path)
|
||||
}
|
||||
|
||||
func (g git) do(args ...string) (string, int, error) {
|
||||
proc := exec.Command("git", "-C", g.path)
|
||||
proc.Args = append(proc.Args, args...)
|
||||
proc.Env = os.Environ()
|
||||
result, err := proc.Output()
|
||||
return string(bytes.TrimSpace(result)), proc.ProcessState.ExitCode(), err
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package revctrl
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.sr.ht/~rjarry/aerc/lib/log"
|
||||
"git.sr.ht/~rjarry/aerc/lib/pama/models"
|
||||
)
|
||||
|
||||
var ErrUnsupported = errors.New("unsupported")
|
||||
|
||||
type factoryFunc func(string) models.RevisionController
|
||||
|
||||
var controllers = map[string]factoryFunc{}
|
||||
|
||||
func register(controllerID string, fn factoryFunc) {
|
||||
controllers[controllerID] = fn
|
||||
}
|
||||
|
||||
func New(controllerID string, path string) (models.RevisionController, error) {
|
||||
factoryFunc, ok := controllers[controllerID]
|
||||
if !ok {
|
||||
return nil, errors.New("cannot create revision control instance")
|
||||
}
|
||||
return factoryFunc(path), nil
|
||||
}
|
||||
|
||||
type detector interface {
|
||||
Support() bool
|
||||
Root() (string, error)
|
||||
}
|
||||
|
||||
func Detect(path string) (string, string, error) {
|
||||
for controllerID, factoryFunc := range controllers {
|
||||
rc, ok := factoryFunc(path).(detector)
|
||||
if ok && rc.Support() {
|
||||
log.Tracef("support found for %v", controllerID)
|
||||
root, err := rc.Root()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
log.Tracef("root found in %s", root)
|
||||
return controllerID, root, nil
|
||||
}
|
||||
}
|
||||
return "", "", fmt.Errorf("no supported repository found in %s", path)
|
||||
}
|
||||
Reference in New Issue
Block a user