aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKoni Marti <koni.marti@gmail.com>2023-11-24 16:03:06 +0100
committerRobin Jarry <robin@jarry.cc>2023-12-30 15:42:09 +0100
commit6592d6e711a2d909465a758259adc76edc5ae3e6 (patch)
tree2316f4e69cf1b005af010ea177e86f5c90a09198 /lib
parentc711fe1cab738fdc1e9c12c601d80d6bf5892c9e (diff)
downloadaerc-6592d6e711a2d909465a758259adc76edc5ae3e6.tar.gz
patch/rebase: add rebase sub-cmd
Implement the :patch rebase command. Rebase the internal patch data in case the repository was rebased too. The :patch rebase command accepts a optional argument which is used as the reference commit from which the rebasing will occur. Open an editor with the commits that are found on top of the rebase reference. Any untracked commit will have the tag 'untracked'. If a line is removed or the 'untracked' tag remains, it will be dropped from the internal data. To group commits into a patch set, assign the same tag names. Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
Diffstat (limited to 'lib')
-rw-r--r--lib/pama/rebase.go81
1 files changed, 81 insertions, 0 deletions
diff --git a/lib/pama/rebase.go b/lib/pama/rebase.go
new file mode 100644
index 00000000..8f316b7e
--- /dev/null
+++ b/lib/pama/rebase.go
@@ -0,0 +1,81 @@
+package pama
+
+import (
+ "fmt"
+
+ "git.sr.ht/~rjarry/aerc/lib/pama/models"
+)
+
+// RebaseCommits fetches the commits between baseID and HEAD. The tags from the
+// current project will be mapped onto the fetched commits based on either the
+// commit hash or the commit subject.
+func (m PatchManager) RebaseCommits(p models.Project, baseID string) ([]models.Commit, error) {
+ rc, err := m.rc(p.RevctrlID, p.Root)
+ if err != nil {
+ return nil, revErr(err)
+ }
+
+ if !rc.Exists(baseID) {
+ return nil, fmt.Errorf("cannot rebase on %s. "+
+ "commit does not exist", baseID)
+ }
+
+ commitIDs, err := rc.History(baseID)
+ if err != nil {
+ return nil, err
+ }
+
+ commits := make([]models.Commit, len(commitIDs))
+ for i := 0; i < len(commitIDs); i++ {
+ commits[i] = models.NewCommit(
+ rc,
+ commitIDs[i],
+ models.Untracked,
+ )
+ }
+
+ // map tags from the commits from the project p
+ for i, r := range commits {
+ for _, c := range p.Commits {
+ if c.ID == r.ID || c.Subject == r.Subject {
+ commits[i].MessageId = c.MessageId
+ commits[i].Tag = c.Tag
+ break
+ }
+ }
+ }
+
+ return commits, nil
+}
+
+// SaveRebased checks if the commits actually exist in the repo, repopulate the
+// info fields and saves the baseID for project p.
+func (m PatchManager) SaveRebased(p models.Project, baseID string, commits []models.Commit) error {
+ rc, err := m.rc(p.RevctrlID, p.Root)
+ if err != nil {
+ return revErr(err)
+ }
+
+ exist := make([]models.Commit, 0, len(commits))
+ for _, c := range commits {
+ if !rc.Exists(c.ID) {
+ continue
+ }
+ exist = append(exist, c)
+ }
+
+ for i, c := range exist {
+ exist[i].Subject = rc.Subject(c.ID)
+ exist[i].Author = rc.Author(c.ID)
+ exist[i].Date = rc.Date(c.ID)
+ }
+
+ p.Commits = exist
+
+ if rc.Exists(baseID) {
+ p.Base = models.NewCommit(rc, baseID, "")
+ }
+
+ err = m.store().StoreProject(p, true)
+ return storeErr(err)
+}