Derive module release identity and accept full Git tags
This commit is contained in:
@@ -18,7 +18,7 @@ var (
|
||||
ErrEndpointChanged = errors.New("Git publication endpoint changed")
|
||||
ErrRemoteMainMissing = errors.New("authoritative remote has no main branch")
|
||||
ErrRemoteMainConflict = errors.New("authoritative main does not identify the candidate commit")
|
||||
ErrRemoteTagConflict = errors.New("version tag already exists on the authoritative remote")
|
||||
ErrRemoteTagConflict = errors.New("tag already exists on the authoritative remote")
|
||||
ErrRemoteStateUnreadable = errors.New("authoritative remote state is unreadable")
|
||||
)
|
||||
|
||||
@@ -50,7 +50,7 @@ type RemoteRef struct {
|
||||
Peeled string
|
||||
}
|
||||
|
||||
// Snapshot is the result of querying refs/heads/main and one exact version tag.
|
||||
// Snapshot is the result of querying refs/heads/main and one exact tag.
|
||||
type Snapshot struct {
|
||||
Main RemoteRef
|
||||
Tag RemoteRef
|
||||
@@ -97,14 +97,14 @@ func (endpoint Endpoint) Recheck(ctx context.Context, repositoryDir string) erro
|
||||
return endpoint.verifyScopedURLs(ctx, repositoryDir)
|
||||
}
|
||||
|
||||
// Query reads exact main and version-tag refs. A command failure is unreadable,
|
||||
// Query reads exact main and tag refs. A command failure is unreadable,
|
||||
// never evidence that a ref is absent.
|
||||
func (endpoint Endpoint) Query(ctx context.Context, repositoryDir, version string) (Snapshot, error) {
|
||||
if !validVersionRef(version) {
|
||||
return Snapshot{}, fmt.Errorf("invalid version tag name %q", version)
|
||||
func (endpoint Endpoint) Query(ctx context.Context, repositoryDir, tag string) (Snapshot, error) {
|
||||
if err := checkTagRef(ctx, repositoryDir, tag); err != nil {
|
||||
return Snapshot{}, err
|
||||
}
|
||||
mainRef := "refs/heads/main"
|
||||
tagRef := "refs/tags/" + version
|
||||
tagRef := "refs/tags/" + tag
|
||||
peeledRef := tagRef + "^{}"
|
||||
output, err := run(ctx, repositoryDir, endpoint.scopedConfig(), "ls-remote", endpoint.ScopedName, mainRef, tagRef, peeledRef)
|
||||
if err != nil {
|
||||
@@ -112,7 +112,7 @@ func (endpoint Endpoint) Query(ctx context.Context, repositoryDir, version strin
|
||||
return snapshot, fmt.Errorf("%w: query authoritative refs at %s: %w", ErrRemoteStateUnreadable, endpoint.PushURL, err)
|
||||
}
|
||||
main := RemoteRef{State: RefAbsent}
|
||||
tag := RemoteRef{State: RefAbsent}
|
||||
remoteTag := RemoteRef{State: RefAbsent}
|
||||
for _, line := range strings.Split(strings.TrimSuffix(output, "\n"), "\n") {
|
||||
if line == "" {
|
||||
continue
|
||||
@@ -125,19 +125,19 @@ func (endpoint Endpoint) Query(ctx context.Context, repositoryDir, version strin
|
||||
case mainRef:
|
||||
main = mergeRef(main, object, false)
|
||||
case tagRef:
|
||||
tag = mergeRef(tag, object, false)
|
||||
remoteTag = mergeRef(remoteTag, object, false)
|
||||
case peeledRef:
|
||||
tag = mergeRef(tag, object, true)
|
||||
remoteTag = mergeRef(remoteTag, object, true)
|
||||
}
|
||||
}
|
||||
return Snapshot{Main: main, Tag: tag}, nil
|
||||
return Snapshot{Main: main, Tag: remoteTag}, nil
|
||||
}
|
||||
|
||||
// RequireCandidate requires exact main equality and an absent remote version
|
||||
// RequireCandidate requires exact main equality and an absent remote
|
||||
// tag. It deliberately does not accept a main branch that merely contains the
|
||||
// candidate as an ancestor.
|
||||
func (endpoint Endpoint) RequireCandidate(ctx context.Context, repositoryDir, version, commit string) (Snapshot, error) {
|
||||
snapshot, err := endpoint.Query(ctx, repositoryDir, version)
|
||||
func (endpoint Endpoint) RequireCandidate(ctx context.Context, repositoryDir, tag, commit string) (Snapshot, error) {
|
||||
snapshot, err := endpoint.Query(ctx, repositoryDir, tag)
|
||||
if err != nil {
|
||||
return snapshot, err
|
||||
}
|
||||
@@ -294,25 +294,14 @@ func mergeRef(ref RemoteRef, object string, peeled bool) RemoteRef {
|
||||
return ref
|
||||
}
|
||||
|
||||
func validVersionRef(version string) bool {
|
||||
if len(version) < 6 || !strings.HasPrefix(version, "v") {
|
||||
return false
|
||||
func checkTagRef(ctx context.Context, repositoryDir, tag string) error {
|
||||
if tag == "" {
|
||||
return fmt.Errorf("invalid Git tag name %q", tag)
|
||||
}
|
||||
parts := strings.Split(version[1:], ".")
|
||||
if len(parts) != 3 {
|
||||
return false
|
||||
if _, err := run(ctx, repositoryDir, nil, "check-ref-format", "refs/tags/"+tag); err != nil {
|
||||
return fmt.Errorf("invalid Git tag name %q: %w", tag, err)
|
||||
}
|
||||
for _, part := range parts {
|
||||
if part == "" || (len(part) > 1 && part[0] == '0') {
|
||||
return false
|
||||
}
|
||||
for _, char := range part {
|
||||
if char < '0' || char > '9' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
func validObjectID(object string) bool {
|
||||
|
||||
Reference in New Issue
Block a user