Add local publication attempt discovery
This commit is contained in:
91
internal/publish/attempts.go
Normal file
91
internal/publish/attempts.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package publish
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Attempt struct {
|
||||
RecordPath string
|
||||
Evidence Evidence
|
||||
}
|
||||
type AttemptsResult struct {
|
||||
RecordDir string
|
||||
Attempts []Attempt
|
||||
Diagnostics []*RecoveryError
|
||||
}
|
||||
|
||||
func ListAttempts(ctx context.Context, repositoryDir, override string) (AttemptsResult, error) {
|
||||
if repositoryDir == "" {
|
||||
repositoryDir = "."
|
||||
}
|
||||
result := AttemptsResult{Attempts: []Attempt{}, Diagnostics: []*RecoveryError{}}
|
||||
var directory string
|
||||
{
|
||||
resolved, err := recordDirectoryFor(ctx, repositoryDir, override)
|
||||
if err != nil {
|
||||
return result, &RecoveryError{Kind: "storage_enumeration", cause: err}
|
||||
}
|
||||
directory = resolved
|
||||
}
|
||||
result.RecordDir = directory
|
||||
if err := ctx.Err(); err != nil {
|
||||
return result, &RecoveryError{Kind: "canceled", cause: err}
|
||||
}
|
||||
entries, err := os.ReadDir(directory)
|
||||
if err != nil {
|
||||
return result, &RecoveryError{Kind: "storage_enumeration", cause: fmt.Errorf("enumerate records in %q: %w", directory, err)}
|
||||
}
|
||||
paths := make([]string, 0, len(entries))
|
||||
for _, entry := range entries {
|
||||
if !entry.IsDir() && strings.HasSuffix(entry.Name(), ".json") {
|
||||
paths = append(paths, filepath.Join(directory, entry.Name()))
|
||||
}
|
||||
}
|
||||
sort.Strings(paths)
|
||||
for _, path := range paths {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return result, &RecoveryError{Kind: "canceled", cause: err}
|
||||
}
|
||||
absolute, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
result.Diagnostics = append(result.Diagnostics, &RecoveryError{Kind: "record_read", RecordPath: path, cause: err})
|
||||
continue
|
||||
}
|
||||
evidence, err := LoadEvidence(absolute)
|
||||
if err != nil {
|
||||
var recordError *RecoveryError
|
||||
if errors.As(err, &recordError) {
|
||||
result.Diagnostics = append(result.Diagnostics, recordError)
|
||||
}
|
||||
continue
|
||||
}
|
||||
result.Attempts = append(result.Attempts, Attempt{RecordPath: absolute, Evidence: evidence})
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func recordDirectoryFor(ctx context.Context, repositoryDir, override string) (string, error) {
|
||||
if filepath.IsAbs(override) {
|
||||
return filepath.Clean(override), nil
|
||||
}
|
||||
root, err := exec.CommandContext(ctx, "git", "-C", repositoryDir, "rev-parse", "--show-toplevel").Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
rootPath := strings.TrimSpace(string(root))
|
||||
if override != "" {
|
||||
return filepath.Join(rootPath, override), nil
|
||||
}
|
||||
common, err := exec.CommandContext(ctx, "git", "-C", repositoryDir, "rev-parse", "--path-format=absolute", "--git-common-dir").Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(strings.TrimSpace(string(common)), "releasekit", "publication-attempts"), nil
|
||||
}
|
||||
Reference in New Issue
Block a user