diff options
author | Koni Marti <koni.marti@gmail.com> | 2023-11-24 16:03:06 +0100 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2023-12-30 15:42:09 +0100 |
commit | 6592d6e711a2d909465a758259adc76edc5ae3e6 (patch) | |
tree | 2316f4e69cf1b005af010ea177e86f5c90a09198 /lib | |
parent | c711fe1cab738fdc1e9c12c601d80d6bf5892c9e (diff) | |
download | aerc-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.go | 81 |
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) +} |