Archived
X restores the selection to the committed pins without the staged or committed question, and resets every restored repository's index to HEAD, so staged pins below are dropped too. Dropped staged pins alone don't make it ask; they are listed if something else is lost. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
126 lines
5.1 KiB
Go
126 lines
5.1 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, and whether staged
|
|
// pins below it are kept. The superproject's target is always HEAD; only
|
|
// RestoreHard matters for it.
|
|
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
|
|
RestoreHard // the pin in the parent's HEAD, and staged pins below are dropped too
|
|
)
|
|
|
|
// Committed reports whether a submodule goes to the pin in its parent's HEAD.
|
|
func (t RestoreTarget) Committed() bool { return t != RestoreStaged }
|
|
|
|
// KeepsStaged reports whether staged pins below the restored repository are
|
|
// kept.
|
|
func (t RestoreTarget) KeepsStaged() bool { return t != RestoreHard }
|
|
|
|
// 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
|
|
}
|