init: pristine aerc 0.20.0 source

This commit is contained in:
Mortdecai
2026-04-07 19:54:54 -04:00
commit 083402a548
502 changed files with 68722 additions and 0 deletions
+93
View File
@@ -0,0 +1,93 @@
package models
import (
"fmt"
"strings"
)
const (
Untracked = "untracked"
)
func NewCommit(r RevisionController, id, tag string) Commit {
return Commit{
ID: id,
Subject: r.Subject(id),
Author: r.Author(id),
Date: r.Date(id),
MessageId: "",
Tag: tag,
}
}
func (c Commit) Untracked() bool {
return c.Tag == Untracked
}
func (c Commit) Info() string {
s := []string{}
if c.Subject == "" {
s = append(s, "(no subject)")
} else {
s = append(s, c.Subject)
}
if c.Author != "" {
s = append(s, c.Author)
}
if c.Date != "" {
s = append(s, c.Date)
}
if c.MessageId != "" {
s = append(s, "<"+c.MessageId+">")
}
return strings.Join(s, ", ")
}
func (c Commit) String() string {
return fmt.Sprintf("%-6.6s %s", c.ID, c.Info())
}
type Commits []Commit
func (h Commits) Tags() []string {
var tags []string
dedup := make(map[string]struct{})
for _, c := range h {
_, ok := dedup[c.Tag]
if ok {
continue
}
tags = append(tags, c.Tag)
dedup[c.Tag] = struct{}{}
}
return tags
}
func (h Commits) HasTag(t string) bool {
for _, c := range h {
if c.Tag == t {
return true
}
}
return false
}
func (h Commits) Lookup(id string) (Commit, bool) {
for _, c := range h {
if c.ID == id {
return c, true
}
}
return Commit{}, false
}
type CommitIDs []string
func (c CommitIDs) Has(id string) bool {
for _, cid := range c {
if cid == id {
return true
}
}
return false
}
+106
View File
@@ -0,0 +1,106 @@
package models
// Commit represents a commit object in a revision control system.
type Commit struct {
// ID is the commit hash.
ID string
// Subject is the subject line of the commit.
Subject string
// Author is the author's name.
Author string
// Date associated with the given commit.
Date string
// MessageId is the message id for the message that contains the commit
// diff. This field is only set when commits were applied via patch
// apply system.
MessageId string
// Tag is a user label that is assigned to one or multiple commits. It
// creates a logical connection between a group of commits to represent
// a patch set.
Tag string
}
// WorktreeParent stores the name and repo location for the base project in the
// linked worktree project.
type WorktreeParent struct {
// Name is the project name from the base repo.
Name string
// Root is the root directory of the base repo.
Root string
}
// Project contains the data to access a revision control system and to store
// the internal patch tracking data.
type Project struct {
// Name is the project name and works as the project ID. Do not change
// it.
Name string
// Root represents the root directory of the revision control system.
Root string
// RevctrlID stores the ID for the revision control system.
RevctrlID string
// Worktree keeps the base repo information. If Worktree.Name and
// Worktree.Root are not zero, this project contains a linked worktree.
Worktree WorktreeParent
// Base represents the reference (base) commit.
Base Commit
// Commits contains the commits that are being tracked. The slice can
// contain any commit between the Base commit and HEAD. These commits
// will be updated by an applying, removing or rebase operation.
Commits []Commit
}
// RevisionController is an interface to a revision control system.
type RevisionController interface {
// Returns the commit hash of the HEAD commit.
Head() (string, error)
// History accepts a commit hash and returns a list of commit hashes
// between the provided hash and HEAD. The order of the returned slice
// is important. The commit hashes should be ordered from "earlier" to
// "later" where the last element must be HEAD.
History(string) ([]string, error)
// Clean returns true if there are no unstaged changes. If there are
// unstaged changes, applying and removing patches will not work.
Clean() bool
// Exists returns true if the commit hash exists in the commit history.
Exists(string) bool
// Subject returns the subject line for the provided commit hash.
Subject(string) string
// Author returns the author for the provided commit hash.
Author(string) string
// Date returns the date for the provided commit hash.
Date(string) string
// Drop removes the commit with the provided commit hash from the
// repository.
Drop(string) error
// ApplyCmd returns a string with an executable command that is used to
// apply patches with the :pipe command.
ApplyCmd() string
// CreateWorktree creates a worktree in path at commit.
CreateWorktree(path string, commit string) error
// DeleteWorktree removes the linked worktree stored in the path
// location. Note that this function should be called from the base
// repo.
DeleteWorktree(path string) error
}
// PersistentStorer is an interface to a persistent storage for Project structs.
type PersistentStorer interface {
// StoreProject saves the project data persistently. If overwrite is
// true, it will write over existing data.
StoreProject(Project, bool) error
// DeleteProject removes the project data from the store.
DeleteProject(string) error
// CurrentName returns the Project.Name for the active project.
CurrentName() (string, error)
// SetCurrent stores a Project.Name and make that project active.
SetCurrent(string) error
// Current returns the project data for the active project.
Current() (Project, error)
// Names returns a slice of Project.Name for all stored projects.
Names() ([]string, error)
// Project returns the stored project for the provided name.
Project(string) (Project, error)
// Projects returns all stored projects.
Projects() ([]Project, error)
}
+85
View File
@@ -0,0 +1,85 @@
package models
import (
"bytes"
"io"
"strings"
"text/template"
"git.sr.ht/~rjarry/aerc/lib/log"
)
var templateText = `
Project {{.Name}} {{if .IsActive}}[active]{{end}} {{if .IsWorktree}}[Linked worktree to {{.WorktreeParent}}]{{end}}
Directory {{.Root}}
Base {{with .Base.ID}}{{if ge (len .) 40}}{{printf "%-6.6s" .}}{{else}}{{.}}{{end}}{{end}}
{{$notes := .Notes}}{{$commits := .Commits}}
{{- range $index, $patch := .Patches}}
{{$patch}}:
{{- range (index $commits $patch)}}
{{with (index $notes .ID)}}[{{.}}] {{end}}{{. -}}
{{end}}
{{end -}}
`
var viewRenderer = template.Must(template.New("ProjectToText").Parse(templateText))
type view struct {
Name string
Root string
Base Commit
// Patches are the unique tag names.
Patches []string
// Commits is a map where the tag names are keys and the associated
// commits the values.
Commits map[string][]Commit
// Notes contain annotations of the commits where the commit hash is
// the key and the annotation is the value.
Notes map[string]string
// IsActive is true if the current project is selected.
IsActive bool
IsWorktree bool
WorktreeParent string
}
func newView(p Project, active bool, notes map[string]string) view {
v := view{
Name: p.Name,
Root: p.Root,
Base: p.Base,
Commits: make(map[string][]Commit),
Notes: notes,
IsActive: active,
IsWorktree: p.Worktree.Root != "" && p.Worktree.Name != "",
WorktreeParent: p.Worktree.Name,
}
for _, commit := range p.Commits {
patch := commit.Tag
commits, ok := v.Commits[patch]
if !ok {
v.Patches = append(v.Patches, patch)
}
commits = append(commits, commit)
v.Commits[patch] = commits
}
return v
}
func (v view) String() string {
var buf bytes.Buffer
err := viewRenderer.Execute(&buf, v)
if err != nil {
log.Errorf("failed to run template: %v", err)
}
return buf.String()
}
func (p Project) String() string {
return newView(p, false, nil).String()
}
func (p Project) NewReader(isActive bool, notes map[string]string) io.Reader {
return strings.NewReader(newView(p, isActive, notes).String())
}