Archived
b opens a centered popup with a search line and the local and remote branches of the selection. Enter stages the branch tip as the pin of a submodule, restores it (and everything below) to it, and puts HEAD on the branch; a remote branch gets a local tracking branch unless one exists elsewhere. Works on the superproject too. Losses are asked like restore. The backdrop behind the popup is dimmed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
117 lines
4.6 KiB
Go
117 lines
4.6 KiB
Go
package submodule
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
)
|
|
|
|
// Provider supplies repository data. Tree is expected to be fast (structure
|
|
// only); Status may be slow and is called once per submodule, concurrently.
|
|
type Provider interface {
|
|
Tree(ctx context.Context) (*Repo, error)
|
|
Status(ctx context.Context, path string) (*Status, error)
|
|
}
|
|
|
|
// Fetcher is implemented by providers that can download remote refs. Path
|
|
// "" is the superproject. Fetch must be safe to call concurrently and must
|
|
// never prompt the user.
|
|
type Fetcher interface {
|
|
// Fetchable reports whether path is a repository that can be fetched
|
|
// (e.g. not an uninitialized submodule).
|
|
Fetchable(path string) bool
|
|
Fetch(ctx context.Context, path string) error
|
|
}
|
|
|
|
// Watcher is implemented by providers that notice changes made outside the
|
|
// application, e.g. a fetch or commit in another shell. The channel is
|
|
// closed when ctx is done.
|
|
type Watcher interface {
|
|
Watch(ctx context.Context) <-chan Change
|
|
}
|
|
|
|
// Locator is implemented by providers whose submodules live on the local
|
|
// disk. Dir returns the absolute directory of path ("" is the superproject),
|
|
// or "" if it is unknown.
|
|
type Locator interface {
|
|
Dir(path string) string
|
|
}
|
|
|
|
// Restorer is implemented by providers that can make a repository (and all
|
|
// submodules below it) exactly what git records. Path "" is the
|
|
// superproject. Restore may clone or fetch objects that are missing, but must
|
|
// never prompt the user.
|
|
type Restorer interface {
|
|
// RestoreLoss reports what Restore would discard, read from the disk at
|
|
// this moment.
|
|
RestoreLoss(ctx context.Context, path string, to RestoreTarget) (Loss, error)
|
|
Restore(ctx context.Context, path string, to RestoreTarget) error
|
|
}
|
|
|
|
// Branch is a local or remote-tracking branch of a repository.
|
|
type Branch struct {
|
|
Ref string // full ref, e.g. "refs/remotes/origin/feat"
|
|
Name string // short name, e.g. "origin/feat"
|
|
Local string // name of the local branch it stands for, e.g. "feat"
|
|
Remote bool // a remote-tracking branch
|
|
Current bool // HEAD is on this branch
|
|
SHA string // the tip when the list was read
|
|
When time.Time // committer date of the tip
|
|
}
|
|
|
|
// Switcher is implemented by providers that can switch a repository to a
|
|
// branch: the tip becomes the staged pin of a submodule, and the repository
|
|
// (with everything below it) is restored to it. Path "" is the superproject.
|
|
// Like Restore, Switch may clone or fetch what is missing below, but must
|
|
// never prompt the user. Branches uses no network.
|
|
type Switcher interface {
|
|
Branches(ctx context.Context, path string) ([]Branch, error)
|
|
// SwitchLoss reports what Switch would discard, read from the disk now.
|
|
SwitchLoss(ctx context.Context, path string, b Branch) (Loss, error)
|
|
// Switch returns the branch HEAD ends up on, "" if it is detached. It
|
|
// fails if b.Ref no longer points at b.SHA.
|
|
Switch(ctx context.Context, path string, b Branch) (string, error)
|
|
}
|
|
|
|
// RestoreTarget is the pin a submodule is restored to. It doesn't matter for
|
|
// the superproject, whose target is always HEAD.
|
|
type RestoreTarget int
|
|
|
|
const (
|
|
RestoreStaged RestoreTarget = iota // the pin in the parent's index: a staged pin is kept and used
|
|
RestoreCommitted // the pin in the parent's HEAD: a staged pin is unstaged
|
|
)
|
|
|
|
// Loss is what a restore discards. The zero Loss means nothing is lost.
|
|
type Loss struct {
|
|
Files int // changed, conflicted and untracked files and directories
|
|
Modules int // repositories with a loss, the repository itself included
|
|
Operations int // merges, rebases, cherry-picks, reverts in progress
|
|
Commits int // commits that no branch, tag or remote ref reaches
|
|
Repositories int // untracked repositories with their own .git directory
|
|
StagedPins int // staged pins of repositories that move to another commit
|
|
Unknown int // repositories whose state could not be read
|
|
}
|
|
|
|
// Empty reports whether nothing would be lost.
|
|
func (l Loss) Empty() bool { return l == Loss{} }
|
|
|
|
// Add sums two losses.
|
|
func (l Loss) Add(o Loss) Loss {
|
|
return Loss{
|
|
Files: l.Files + o.Files,
|
|
Modules: l.Modules + o.Modules,
|
|
Operations: l.Operations + o.Operations,
|
|
Commits: l.Commits + o.Commits,
|
|
Repositories: l.Repositories + o.Repositories,
|
|
StagedPins: l.StagedPins + o.StagedPins,
|
|
Unknown: l.Unknown + o.Unknown,
|
|
}
|
|
}
|
|
|
|
// Change reports that the git metadata of a repository changed.
|
|
type Change struct {
|
|
Path string // "" is the superproject
|
|
Local bool // HEAD, index or local branches changed, not only remote refs
|
|
Structure bool // .gitmodules changed: submodules may have been added or removed
|
|
}
|