Documentation
¶
Overview ¶
Package service provides high-level business logic for UniRTM operations.
Package service provides high-level business logic for UniRTM operations.
Package service provides business logic for UniRTM operations.
Package service provides business logic for UniRTM operations.
Package service provides business logic for UniRTM operations.
Package service provides business logic for UniRTM operations.
Package service provides business logic for UniRTM operations.
Package service provides the plugin loading and management capabilities. It relies on HashiCorp go-plugin to dynamically load standalone binaries that implement the Backend or Provider interfaces via RPC.
Package service provides business logic for UniRTM operations.
Package service provides business logic for UniRTM operations.
Package service provides business logic for UniRTM operations.
Shim scripts are thin wrapper scripts placed in the shims directory that intercept calls to tools and delegate to the correct version based on the active environment settings.
Validates Requirements: 14.1, 14.2, 14.3, 14.4, 14.5, 14.6, 14.7
Package service provides business logic for UniRTM operations.
Example (VersionManager_basicUsage) ¶
Example_versionManager_basicUsage demonstrates basic Version Manager usage
package main
import (
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/backend"
"github.com/snowdreamtech/unirtm/internal/service"
)
// mockBackendForExample is a simple mock backend for examples
type mockBackendForExample struct {
name string
}
func (m *mockBackendForExample) Name() string {
return m.name
}
func (m *mockBackendForExample) AttestationType() string {
return ""
}
func (m *mockBackendForExample) Dependencies() []string {
return nil
}
func (m *mockBackendForExample) GetReach() string {
return ""
}
func (m *mockBackendForExample) IsRecommended() bool {
return false
}
func (m *mockBackendForExample) IsScriptless() bool {
return false
}
func (m *mockBackendForExample) IsStable() bool {
return true
}
func (m *mockBackendForExample) SupportsOffline() bool {
return false
}
func (m *mockBackendForExample) ListVersions(ctx context.Context, tool string, platform backend.Platform) ([]backend.VersionInfo, error) {
return []backend.VersionInfo{
{Version: "20.11.0", DownloadURL: "https://example.com/node-20.11.0.tar.gz"},
{Version: "20.10.0", DownloadURL: "https://example.com/node-20.10.0.tar.gz"},
{Version: "18.19.0", DownloadURL: "https://example.com/node-18.19.0.tar.gz"},
}, nil
}
func (m *mockBackendForExample) ResolveVersion(ctx context.Context, tool string, versionRequest string, platform backend.Platform) (*backend.VersionInfo, error) {
if versionRequest == "latest" {
return &backend.VersionInfo{
Version: "20.11.0",
DownloadURL: "https://example.com/node-20.11.0.tar.gz",
Checksum: "abc123def456",
Platform: platform,
}, nil
}
if versionRequest == "^20.0.0" {
return &backend.VersionInfo{
Version: "20.11.0",
DownloadURL: "https://example.com/node-20.11.0.tar.gz",
Checksum: "abc123def456",
Platform: platform,
}, nil
}
return nil, fmt.Errorf("unsupported version request: %s", versionRequest)
}
func (m *mockBackendForExample) GetDownloadInfo(ctx context.Context, tool string, version string, platform backend.Platform) (*backend.VersionInfo, error) {
return &backend.VersionInfo{
Version: version,
DownloadURL: fmt.Sprintf("https://example.com/%s-%s.tar.gz", tool, version),
Checksum: "abc123def456",
Platform: platform,
}, nil
}
func (m *mockBackendForExample) SupportsChecksum() bool {
return true
}
func (m *mockBackendForExample) SupportsGPG() bool {
return false
}
func main() {
// Create backends
backends := map[string]backend.Backend{
"github": &mockBackendForExample{name: "github"},
}
// Create Version Manager
vm := service.NewVersionManager(backends)
// Resolve exact version
ctx := context.Background()
platform := backend.Platform{OS: "linux", Arch: "amd64"}
versionInfo, err := vm.ResolveVersion(ctx, "github", "node", "20.0.0", platform)
if err != nil {
fmt.Println(err)
}
fmt.Printf("Version: %s\n", versionInfo.Version)
fmt.Printf("Download URL: %s\n", versionInfo.DownloadURL)
}
Output: Version: 20.0.0 Download URL: https://example.com/node-20.0.0.tar.gz
Example (VersionManager_explicitRequirement) ¶
Example_versionManager_explicitRequirement demonstrates explicit version requirement enforcement
package main
import (
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/backend"
"github.com/snowdreamtech/unirtm/internal/service"
)
// mockBackendForExample is a simple mock backend for examples
type mockBackendForExample struct {
name string
}
func (m *mockBackendForExample) Name() string {
return m.name
}
func (m *mockBackendForExample) AttestationType() string {
return ""
}
func (m *mockBackendForExample) Dependencies() []string {
return nil
}
func (m *mockBackendForExample) GetReach() string {
return ""
}
func (m *mockBackendForExample) IsRecommended() bool {
return false
}
func (m *mockBackendForExample) IsScriptless() bool {
return false
}
func (m *mockBackendForExample) IsStable() bool {
return true
}
func (m *mockBackendForExample) SupportsOffline() bool {
return false
}
func (m *mockBackendForExample) ListVersions(ctx context.Context, tool string, platform backend.Platform) ([]backend.VersionInfo, error) {
return []backend.VersionInfo{
{Version: "20.11.0", DownloadURL: "https://example.com/node-20.11.0.tar.gz"},
{Version: "20.10.0", DownloadURL: "https://example.com/node-20.10.0.tar.gz"},
{Version: "18.19.0", DownloadURL: "https://example.com/node-18.19.0.tar.gz"},
}, nil
}
func (m *mockBackendForExample) ResolveVersion(ctx context.Context, tool string, versionRequest string, platform backend.Platform) (*backend.VersionInfo, error) {
if versionRequest == "latest" {
return &backend.VersionInfo{
Version: "20.11.0",
DownloadURL: "https://example.com/node-20.11.0.tar.gz",
Checksum: "abc123def456",
Platform: platform,
}, nil
}
if versionRequest == "^20.0.0" {
return &backend.VersionInfo{
Version: "20.11.0",
DownloadURL: "https://example.com/node-20.11.0.tar.gz",
Checksum: "abc123def456",
Platform: platform,
}, nil
}
return nil, fmt.Errorf("unsupported version request: %s", versionRequest)
}
func (m *mockBackendForExample) GetDownloadInfo(ctx context.Context, tool string, version string, platform backend.Platform) (*backend.VersionInfo, error) {
return &backend.VersionInfo{
Version: version,
DownloadURL: fmt.Sprintf("https://example.com/%s-%s.tar.gz", tool, version),
Checksum: "abc123def456",
Platform: platform,
}, nil
}
func (m *mockBackendForExample) SupportsChecksum() bool {
return true
}
func (m *mockBackendForExample) SupportsGPG() bool {
return false
}
func main() {
backends := map[string]backend.Backend{
"github": &mockBackendForExample{name: "github"},
}
vm := service.NewVersionManager(backends)
ctx := context.Background()
platform := backend.Platform{OS: "linux", Arch: "amd64"}
// Try to resolve without specifying a version
_, err := vm.ResolveVersion(ctx, "github", "node", "", platform)
if err != nil {
fmt.Println("Error:", err)
}
}
Output: Error: explicit version specification required for tool 'node': must specify an exact version (e.g., 1.20.0), range (e.g., >=1.20.0, ^3.11, ~2.7.0), or alias (latest, lts, stable)
Example (VersionManager_listVersions) ¶
Example_versionManager_listVersions demonstrates listing available versions
package main
import (
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/backend"
"github.com/snowdreamtech/unirtm/internal/service"
)
// mockBackendForExample is a simple mock backend for examples
type mockBackendForExample struct {
name string
}
func (m *mockBackendForExample) Name() string {
return m.name
}
func (m *mockBackendForExample) AttestationType() string {
return ""
}
func (m *mockBackendForExample) Dependencies() []string {
return nil
}
func (m *mockBackendForExample) GetReach() string {
return ""
}
func (m *mockBackendForExample) IsRecommended() bool {
return false
}
func (m *mockBackendForExample) IsScriptless() bool {
return false
}
func (m *mockBackendForExample) IsStable() bool {
return true
}
func (m *mockBackendForExample) SupportsOffline() bool {
return false
}
func (m *mockBackendForExample) ListVersions(ctx context.Context, tool string, platform backend.Platform) ([]backend.VersionInfo, error) {
return []backend.VersionInfo{
{Version: "20.11.0", DownloadURL: "https://example.com/node-20.11.0.tar.gz"},
{Version: "20.10.0", DownloadURL: "https://example.com/node-20.10.0.tar.gz"},
{Version: "18.19.0", DownloadURL: "https://example.com/node-18.19.0.tar.gz"},
}, nil
}
func (m *mockBackendForExample) ResolveVersion(ctx context.Context, tool string, versionRequest string, platform backend.Platform) (*backend.VersionInfo, error) {
if versionRequest == "latest" {
return &backend.VersionInfo{
Version: "20.11.0",
DownloadURL: "https://example.com/node-20.11.0.tar.gz",
Checksum: "abc123def456",
Platform: platform,
}, nil
}
if versionRequest == "^20.0.0" {
return &backend.VersionInfo{
Version: "20.11.0",
DownloadURL: "https://example.com/node-20.11.0.tar.gz",
Checksum: "abc123def456",
Platform: platform,
}, nil
}
return nil, fmt.Errorf("unsupported version request: %s", versionRequest)
}
func (m *mockBackendForExample) GetDownloadInfo(ctx context.Context, tool string, version string, platform backend.Platform) (*backend.VersionInfo, error) {
return &backend.VersionInfo{
Version: version,
DownloadURL: fmt.Sprintf("https://example.com/%s-%s.tar.gz", tool, version),
Checksum: "abc123def456",
Platform: platform,
}, nil
}
func (m *mockBackendForExample) SupportsChecksum() bool {
return true
}
func (m *mockBackendForExample) SupportsGPG() bool {
return false
}
func main() {
backends := map[string]backend.Backend{
"github": &mockBackendForExample{name: "github"},
}
vm := service.NewVersionManager(backends)
ctx := context.Background()
platform := backend.Platform{OS: "linux", Arch: "amd64"}
// List available versions
versions, err := vm.ListAvailableVersions(ctx, "github", "node", platform)
if err != nil {
fmt.Println(err)
}
fmt.Println("Available versions:")
for _, v := range versions {
fmt.Printf(" - %s\n", v.Version)
}
}
Output: Available versions: - 20.11.0 - 20.10.0 - 18.19.0
Example (VersionManager_resolveAlias) ¶
Example_versionManager_resolveAlias demonstrates resolving version aliases
package main
import (
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/backend"
"github.com/snowdreamtech/unirtm/internal/service"
)
// mockBackendForExample is a simple mock backend for examples
type mockBackendForExample struct {
name string
}
func (m *mockBackendForExample) Name() string {
return m.name
}
func (m *mockBackendForExample) AttestationType() string {
return ""
}
func (m *mockBackendForExample) Dependencies() []string {
return nil
}
func (m *mockBackendForExample) GetReach() string {
return ""
}
func (m *mockBackendForExample) IsRecommended() bool {
return false
}
func (m *mockBackendForExample) IsScriptless() bool {
return false
}
func (m *mockBackendForExample) IsStable() bool {
return true
}
func (m *mockBackendForExample) SupportsOffline() bool {
return false
}
func (m *mockBackendForExample) ListVersions(ctx context.Context, tool string, platform backend.Platform) ([]backend.VersionInfo, error) {
return []backend.VersionInfo{
{Version: "20.11.0", DownloadURL: "https://example.com/node-20.11.0.tar.gz"},
{Version: "20.10.0", DownloadURL: "https://example.com/node-20.10.0.tar.gz"},
{Version: "18.19.0", DownloadURL: "https://example.com/node-18.19.0.tar.gz"},
}, nil
}
func (m *mockBackendForExample) ResolveVersion(ctx context.Context, tool string, versionRequest string, platform backend.Platform) (*backend.VersionInfo, error) {
if versionRequest == "latest" {
return &backend.VersionInfo{
Version: "20.11.0",
DownloadURL: "https://example.com/node-20.11.0.tar.gz",
Checksum: "abc123def456",
Platform: platform,
}, nil
}
if versionRequest == "^20.0.0" {
return &backend.VersionInfo{
Version: "20.11.0",
DownloadURL: "https://example.com/node-20.11.0.tar.gz",
Checksum: "abc123def456",
Platform: platform,
}, nil
}
return nil, fmt.Errorf("unsupported version request: %s", versionRequest)
}
func (m *mockBackendForExample) GetDownloadInfo(ctx context.Context, tool string, version string, platform backend.Platform) (*backend.VersionInfo, error) {
return &backend.VersionInfo{
Version: version,
DownloadURL: fmt.Sprintf("https://example.com/%s-%s.tar.gz", tool, version),
Checksum: "abc123def456",
Platform: platform,
}, nil
}
func (m *mockBackendForExample) SupportsChecksum() bool {
return true
}
func (m *mockBackendForExample) SupportsGPG() bool {
return false
}
func main() {
backends := map[string]backend.Backend{
"github": &mockBackendForExample{name: "github"},
}
vm := service.NewVersionManager(backends)
ctx := context.Background()
platform := backend.Platform{OS: "linux", Arch: "amd64"}
// Resolve "latest" alias
versionInfo, err := vm.ResolveVersion(ctx, "github", "node", "latest", platform)
if err != nil {
fmt.Println(err)
}
fmt.Printf("Latest version: %s\n", versionInfo.Version)
}
Output: Latest version: 20.11.0
Example (VersionManager_resolveRange) ¶
Example_versionManager_resolveRange demonstrates resolving version ranges
package main
import (
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/backend"
"github.com/snowdreamtech/unirtm/internal/service"
)
// mockBackendForExample is a simple mock backend for examples
type mockBackendForExample struct {
name string
}
func (m *mockBackendForExample) Name() string {
return m.name
}
func (m *mockBackendForExample) AttestationType() string {
return ""
}
func (m *mockBackendForExample) Dependencies() []string {
return nil
}
func (m *mockBackendForExample) GetReach() string {
return ""
}
func (m *mockBackendForExample) IsRecommended() bool {
return false
}
func (m *mockBackendForExample) IsScriptless() bool {
return false
}
func (m *mockBackendForExample) IsStable() bool {
return true
}
func (m *mockBackendForExample) SupportsOffline() bool {
return false
}
func (m *mockBackendForExample) ListVersions(ctx context.Context, tool string, platform backend.Platform) ([]backend.VersionInfo, error) {
return []backend.VersionInfo{
{Version: "20.11.0", DownloadURL: "https://example.com/node-20.11.0.tar.gz"},
{Version: "20.10.0", DownloadURL: "https://example.com/node-20.10.0.tar.gz"},
{Version: "18.19.0", DownloadURL: "https://example.com/node-18.19.0.tar.gz"},
}, nil
}
func (m *mockBackendForExample) ResolveVersion(ctx context.Context, tool string, versionRequest string, platform backend.Platform) (*backend.VersionInfo, error) {
if versionRequest == "latest" {
return &backend.VersionInfo{
Version: "20.11.0",
DownloadURL: "https://example.com/node-20.11.0.tar.gz",
Checksum: "abc123def456",
Platform: platform,
}, nil
}
if versionRequest == "^20.0.0" {
return &backend.VersionInfo{
Version: "20.11.0",
DownloadURL: "https://example.com/node-20.11.0.tar.gz",
Checksum: "abc123def456",
Platform: platform,
}, nil
}
return nil, fmt.Errorf("unsupported version request: %s", versionRequest)
}
func (m *mockBackendForExample) GetDownloadInfo(ctx context.Context, tool string, version string, platform backend.Platform) (*backend.VersionInfo, error) {
return &backend.VersionInfo{
Version: version,
DownloadURL: fmt.Sprintf("https://example.com/%s-%s.tar.gz", tool, version),
Checksum: "abc123def456",
Platform: platform,
}, nil
}
func (m *mockBackendForExample) SupportsChecksum() bool {
return true
}
func (m *mockBackendForExample) SupportsGPG() bool {
return false
}
func main() {
backends := map[string]backend.Backend{
"github": &mockBackendForExample{name: "github"},
}
vm := service.NewVersionManager(backends)
ctx := context.Background()
platform := backend.Platform{OS: "linux", Arch: "amd64"}
// Resolve caret range
versionInfo, err := vm.ResolveVersion(ctx, "github", "node", "^20.0.0", platform)
if err != nil {
fmt.Println(err)
}
fmt.Printf("Resolved ^20.0.0 to: %s\n", versionInfo.Version)
}
Output: Resolved ^20.0.0 to: 20.11.0
Example (VersionManager_validateConstraint) ¶
Example_versionManager_validateConstraint demonstrates version constraint validation
package main
import (
"fmt"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
vm := service.NewVersionManager(nil)
// Validate various version constraints
constraints := []string{
"20.0.0",
"^20.0.0",
">=18.0.0",
"latest",
}
for _, constraint := range constraints {
if err := vm.ValidateVersionConstraint(constraint); err != nil {
fmt.Printf("Invalid: %s - %v\n", constraint, err)
} else {
fmt.Printf("Valid: %s\n", constraint)
}
}
}
Output: Valid: 20.0.0 Valid: ^20.0.0 Valid: >=18.0.0 Valid: latest
Index ¶
- Constants
- Variables
- func ExecuteBinary(binPath string, args []string) error
- type ActivationAction
- type ActivationChange
- type ActivationConfig
- type ActivationManager
- func (m *ActivationManager) GenerateActivationScript(ctx context.Context, config ActivationConfig) (*ActivationScript, error)
- func (m *ActivationManager) GenerateGlobalActivation(ctx context.Context, shell ShellType, toolVersions map[string]string) (*ActivationScript, error)
- func (m *ActivationManager) GenerateProjectActivation(ctx context.Context, shell ShellType, projectDir string, ...) (*ActivationScript, error)
- type ActivationScope
- type ActivationScript
- type AuditLogEntry
- type AuditService
- func (s *AuditService) GetLogsByOperation(ctx context.Context, operation OperationType, limit int) ([]*repository.AuditEntry, error)
- func (s *AuditService) GetLogsByStatus(ctx context.Context, status OperationStatus, limit int) ([]*repository.AuditEntry, error)
- func (s *AuditService) GetLogsByTimeRange(ctx context.Context, startTime, endTime time.Time, limit int) ([]*repository.AuditEntry, error)
- func (s *AuditService) GetLogsByTool(ctx context.Context, tool string, limit int) ([]*repository.AuditEntry, error)
- func (s *AuditService) GetRecentLogs(ctx context.Context, limit int) ([]*repository.AuditEntry, error)
- func (s *AuditService) LogActivate(ctx context.Context, tool, version string, duration time.Duration, err error) error
- func (s *AuditService) LogCachePurge(ctx context.Context, duration time.Duration, purgedCount int, err error) error
- func (s *AuditService) LogConfigLoad(ctx context.Context, configPath string, duration time.Duration, err error) error
- func (s *AuditService) LogConfigUpdate(ctx context.Context, configPath string, duration time.Duration, err error) error
- func (s *AuditService) LogDeactivate(ctx context.Context, tool, version string, duration time.Duration, err error) error
- func (s *AuditService) LogIndexUpdate(ctx context.Context, backend string, duration time.Duration, toolCount int, ...) error
- func (s *AuditService) LogInstall(ctx context.Context, tool, version string, duration time.Duration, err error) error
- func (s *AuditService) LogOperation(ctx context.Context, entry *AuditLogEntry) error
- func (s *AuditService) LogUninstall(ctx context.Context, tool, version string, duration time.Duration, err error) error
- func (s *AuditService) LogUpdate(ctx context.Context, tool, oldVersion, newVersion string, ...) error
- func (s *AuditService) LogVersionResolve(ctx context.Context, tool, versionSpec, resolvedVersion string, ...) error
- func (s *AuditService) QueryAuditLogs(ctx context.Context, filter repository.AuditFilter) ([]*repository.AuditEntry, error)
- type AutoActivationManager
- func (m *AutoActivationManager) GenerateHookEnvScript(shell ShellType, exePath string) (string, error)
- func (m *AutoActivationManager) HandleDirectoryChange(ctx context.Context, event DirectoryChangeEvent, ...) (*ActivationChange, error)
- func (m *AutoActivationManager) LoadConfigByDir(projectDir string) (map[string]string, map[string]string, []string, error)
- type BackendRegistry
- type CacheManager
- func (cm *CacheManager) AutoCleanup(ctx context.Context) error
- func (cm *CacheManager) Delete(ctx context.Context, key string) error
- func (cm *CacheManager) Get(ctx context.Context, key string) ([]byte, error)
- func (cm *CacheManager) GetCacheSize() (int64, error)
- func (cm *CacheManager) GetStats() CacheStats
- func (cm *CacheManager) GetWithChecksum(ctx context.Context, key string, expectedChecksum string) ([]byte, error)
- func (cm *CacheManager) PurgeAll(ctx context.Context) error
- func (cm *CacheManager) PurgeByPrefix(ctx context.Context, prefix string) error
- func (cm *CacheManager) PurgeExpired(ctx context.Context) error
- func (cm *CacheManager) ResetStats()
- func (cm *CacheManager) Set(ctx context.Context, key string, value []byte, ttl time.Duration) error
- type CacheManagerConfig
- type CacheStats
- type ChecksumAlgorithm
- type CleanupManager
- type ConcurrentInstallResult
- type ConcurrentManager
- type ConcurrentManagerConfig
- type ConfigValidationResult
- type ConfigValidator
- type ConflictingRequester
- type Dependency
- type DependencyConflict
- type DependencyGraph
- type DependencyResolver
- func (r *DependencyResolver) DetectCircularDependencies(graph *DependencyGraph) error
- func (r *DependencyResolver) ParseDependencies(ctx context.Context, tools []string) (*DependencyGraph, error)
- func (r *DependencyResolver) ResolveDependencies(ctx context.Context, tools []string, requestedVersions map[string]string) (*InstallationOrder, error)
- func (r *DependencyResolver) ResolveVersionConstraints(ctx context.Context, graph *DependencyGraph, ...) error
- func (r *DependencyResolver) TopologicalSort(graph *DependencyGraph) (*InstallationOrder, error)
- type DirectoryChangeEvent
- type EnvironmentState
- type GenerateOptions
- type Generator
- type IncompleteOperation
- type IndexManager
- func (im *IndexManager) DeleteTool(ctx context.Context, tool string) error
- func (im *IndexManager) FilterByBackend(ctx context.Context, backendName string) ([]*repository.IndexEntry, error)
- func (im *IndexManager) GetStaleAge(ctx context.Context) (time.Duration, error)
- func (im *IndexManager) GetTool(ctx context.Context, tool string) (*repository.IndexEntry, error)
- func (im *IndexManager) GetToolMetadata(ctx context.Context, tool string) (*ToolMetadata, error)
- func (im *IndexManager) IsOfflineCapable(ctx context.Context) (bool, error)
- func (im *IndexManager) IsStale(ctx context.Context) (bool, error)
- func (im *IndexManager) ListBackends() []string
- func (im *IndexManager) ListTools(ctx context.Context) ([]*repository.IndexEntry, error)
- func (im *IndexManager) PromptForUpdate(ctx context.Context) (bool, string, error)
- func (im *IndexManager) RegisterBackend(backendName string, b backend.Backend)
- func (im *IndexManager) SearchTools(ctx context.Context, options SearchOptions) ([]*repository.IndexEntry, error)
- func (im *IndexManager) SupportsOffline() bool
- func (im *IndexManager) UnregisterBackend(backendName string)
- func (im *IndexManager) UpdateFromAllBackends(ctx context.Context) error
- func (im *IndexManager) UpdateFromBackend(ctx context.Context, backendName string) error
- func (im *IndexManager) UpsertTool(ctx context.Context, tool string, description string, homepage string, ...) error
- type IndexManagerConfig
- type InstallationManager
- func (im *InstallationManager) AutoDetectBackend(toolName string) string
- func (im *InstallationManager) Close() error
- func (im *InstallationManager) EnsureInstalled(ctx context.Context, tools map[string]config.ToolConfig) error
- func (im *InstallationManager) EnsureInstalledFromSpecs(ctx context.Context, tools map[string]ToolSpec) error
- func (im *InstallationManager) Install(ctx context.Context, toolKey, tool, version, backendName string) error
- func (im *InstallationManager) IsInstalled(ctx context.Context, tool, versionSpec, backendName string) (bool, *repository.Installation)
- func (im *InstallationManager) ParseToolSpec(spec string) (backend, tool, version string, explicit bool)
- func (im *InstallationManager) ResolveExecutable(ctx context.Context, exeName string, platform backend.Platform) (string, map[string]string, error)
- func (im *InstallationManager) ResolveToolEnvBySpec(toolName, version, backendName string) map[string]string
- func (im *InstallationManager) SelectVersionInteractive(ctx context.Context, tool, backendName string) (string, error)
- func (im *InstallationManager) SetAliases(aliases map[string]map[string]string)
- func (im *InstallationManager) SetDB(db *database.DB)
- func (im *InstallationManager) SetToolConfigs(toolConfigs map[string]config.ToolConfig)
- func (im *InstallationManager) SortTools(tools map[string]config.ToolConfig) []ToolToInstall
- func (im *InstallationManager) SortToolsFromSpecs(tools map[string]ToolSpec) []ToolToInstall
- func (im *InstallationManager) Uninstall(ctx context.Context, tool, version string) error
- type InstallationOrder
- type Installer
- type LockService
- func (ls *LockService) CheckStrict(lockKey, version string, platform backend.Platform) error
- func (ls *LockService) Generate(ctx context.Context, tools map[string]ToolSpec, opts GenerateOptions) error
- func (ls *LockService) IsEmpty() bool
- func (ls *LockService) IsStrictMode() bool
- func (ls *LockService) Path() string
- func (ls *LockService) RecordInstall(lockKey, backendName string, info *backend.VersionInfo) error
- func (ls *LockService) RemoveTool(lockKey string) error
- func (ls *LockService) Resolve(lockKey, version string, platform backend.Platform) (*backend.VersionInfo, bool)
- func (ls *LockService) SetBackendRegistry(r *backend.Registry)
- func (ls *LockService) Validate() error
- type LockServiceOptions
- type MigrationManager
- func (mm *MigrationManager) FormatReport(report *MigrationReport) string
- func (mm *MigrationManager) MigrateDirectory(ctx context.Context, dir string, dryRun bool) ([]*MigrationReport, error)
- func (mm *MigrationManager) MigrateFile(ctx context.Context, sourcePath string, outputPath string, dryRun bool) (*MigrationReport, error)
- type MigrationReport
- type MigrationSource
- type MigrationTool
- type OfflineManager
- func (om *OfflineManager) CanOperateOffline(operation string) bool
- func (om *OfflineManager) IsOnline(ctx context.Context) bool
- func (om *OfflineManager) RequireOnline(ctx context.Context, operation string) error
- func (om *OfflineManager) SkipIfOffline(ctx context.Context, operationName string) bool
- type OperationMetric
- type OperationPhase
- type OperationStatus
- type OperationType
- type PerformanceMonitor
- func (pm *PerformanceMonitor) AllReports() []*PerformanceReport
- func (pm *PerformanceMonitor) CacheHitRate() float64
- func (pm *PerformanceMonitor) DetectRegressions(threshold float64) map[OperationPhase]float64
- func (pm *PerformanceMonitor) FormatReport(r *PerformanceReport) string
- func (pm *PerformanceMonitor) Record(ctx context.Context, metric OperationMetric)
- func (pm *PerformanceMonitor) Report(phase OperationPhase) *PerformanceReport
- func (pm *PerformanceMonitor) SetBaseline(phase OperationPhase, d time.Duration)
- func (pm *PerformanceMonitor) Track(ctx context.Context, tool, version string, phase OperationPhase) func(success bool)
- type PerformanceReport
- type PluginManager
- type PluginMetadata
- type ProgressReporter
- type ProviderMetadata
- type ProviderRegistry
- type RecoveryAction
- type RecoveryManager
- type RecoveryReport
- type SearchOptions
- type SecurityManager
- func (sm *SecurityManager) VerifyChecksum(ctx context.Context, tool, version, filePath, expected string) (*SecurityVerificationResult, error)
- func (sm *SecurityManager) VerifyInstallation(ctx context.Context, installation *repository.Installation, binaryPath string) (*SecurityVerificationResult, error)
- type SecurityVerificationResult
- type ShellConfigManager
- type ShellType
- type ToolInstallRequest
- type ToolMetadata
- type ToolSpec
- type ToolToInstall
- type UpdateInfo
- type UpdateManager
- func (um *UpdateManager) CheckForUpdates(ctx context.Context) ([]UpdateInfo, error)
- func (um *UpdateManager) DisableAutomaticUpdates(ctx context.Context) error
- func (um *UpdateManager) EnableAutomaticUpdates(ctx context.Context, schedule string) error
- func (um *UpdateManager) PreviewUpdates(ctx context.Context) (*UpdatePreview, error)
- func (um *UpdateManager) UpdateAll(ctx context.Context) ([]UpdateResult, error)
- func (um *UpdateManager) UpdateTool(ctx context.Context, tool, targetVersion string) (*UpdateResult, error)
- type UpdatePreview
- type UpdateResult
- type ValidationIssue
- type ValidationSeverity
- type VersionManager
- func (vm *VersionManager) ListAvailableVersions(ctx context.Context, backendName, tool string, platform backend.Platform) ([]backend.VersionInfo, error)
- func (vm *VersionManager) ParseVersionConstraint(versionStr string) (*version.Version, error)
- func (vm *VersionManager) ResolveVersion(ctx context.Context, backendName, tool, versionSpec string, ...) (*backend.VersionInfo, error)
- func (vm *VersionManager) SupportsChecksum(backendName string) (bool, error)
- func (vm *VersionManager) SupportsGPG(backendName string) (bool, error)
- func (vm *VersionManager) ValidateVersionConstraint(versionStr string) error
Examples ¶
- Package (VersionManager_basicUsage)
- Package (VersionManager_explicitRequirement)
- Package (VersionManager_listVersions)
- Package (VersionManager_resolveAlias)
- Package (VersionManager_resolveRange)
- Package (VersionManager_validateConstraint)
- ActivationManager.GenerateActivationScript (Fish)
- ActivationManager.GenerateActivationScript (MultipleTools)
- ActivationManager.GenerateActivationScript (Powershell)
- ActivationManager.GenerateGlobalActivation
- ActivationManager.GenerateProjectActivation
- AuditService.GetLogsByStatus
- AuditService.GetLogsByTool
- AuditService.LogInstall
- AuditService.LogOperation
- AuditService.QueryAuditLogs
- AutoActivationManager (Deactivation)
- AutoActivationManager (ProjectSwitch)
- AutoActivationManager.GenerateHookEnvScript
- AutoActivationManager.HandleDirectoryChange
- DetectShell
- IndexManager (BackendManagement)
- IndexManager (Basic)
- IndexManager (FilterByBackend)
- IndexManager (Metadata)
- IndexManager (Offline)
- IndexManager (Pagination)
- IndexManager (Search)
- IndexManager (StaleDetection)
Constants ¶
const ( ContextKeyQuietProgress = "quietProgress" ContextKeyProgressReporter = "concurrentProgressReporter" )
const PluginAPIVersion = "v1"
PluginAPIVersion defines the current plugin API version for compatibility checking.
Validates Requirement: 22.3 (API stability and versioning)
Variables ¶
var ErrAlreadyInstalled = fmt.Errorf("already installed")
ErrAlreadyInstalled is returned when a tool version is already installed.
Functions ¶
func ExecuteBinary ¶
ExecuteBinary executes a binary with arguments, replacing the current process on Unix.
Types ¶
type ActivationAction ¶
type ActivationAction string
ActivationAction represents the type of activation change.
const ( // ActionActivate indicates activating a new project environment ActionActivate ActivationAction = "activate" // ActionDeactivate indicates deactivating the current project environment ActionDeactivate ActivationAction = "deactivate" // ActionSwitch indicates switching from one project to another ActionSwitch ActivationAction = "switch" // ActionNone indicates no change is needed ActionNone ActivationAction = "none" )
type ActivationChange ¶
type ActivationChange struct {
// Action is the type of change (activate, deactivate, switch)
Action ActivationAction
// Script is the shell script to execute the change
Script string
// NewState is the new environment state after the change
NewState *EnvironmentState
}
ActivationChange represents the changes needed to update the environment.
type ActivationConfig ¶
type ActivationConfig struct {
// Shell is the target shell type
Shell ShellType
// Scope is the activation scope (global or project)
Scope ActivationScope
// ShimsDir is the directory containing shim scripts
ShimsDir string
// ProjectDir is the project directory (for project-specific activation)
ProjectDir string
// ToolVersions maps tool names to their active versions
ToolVersions map[string]string
// EnvVars contains additional environment variables to set
EnvVars map[string]string
// Sources contains shell scripts to source
// ExePath is the absolute path to the UniRTM executable
ExePath string
Sources []string
// UseShims indicates whether to use shims (true) or PATH mode (false)
UseShims bool
// InjectedPaths is the list of absolute paths to inject into PATH (if not using shims)
InjectedPaths []string
}
ActivationConfig contains configuration for activation.
type ActivationManager ¶
type ActivationManager struct {
// contains filtered or unexported fields
}
ActivationManager manages environment activation for tools.
func NewActivationManager ¶
func NewActivationManager(shimsDir, dataDir string, registry *provider.Registry) *ActivationManager
NewActivationManager creates a new ActivationManager.
func (*ActivationManager) GenerateActivationScript ¶
func (m *ActivationManager) GenerateActivationScript(ctx context.Context, config ActivationConfig) (*ActivationScript, error)
GenerateActivationScript generates a shell-specific activation script.
The script modifies PATH to include the shims directory and sets environment variables for active tool versions. The script format depends on the target shell.
Requirements: 15.1, 15.2, 15.3
Example (Fish) ¶
ExampleActivationManager_GenerateActivationScript_fish demonstrates generating an activation script for fish shell.
package main
import (
"github.com/snowdreamtech/unirtm/internal/provider"
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
manager := service.NewActivationManager("/usr/local/unirtm/shims", "/var/lib/unirtm", provider.NewRegistry())
ctx := context.Background()
config := service.ActivationConfig{
Shell: service.ShellFish,
Scope: service.ScopeGlobal,
ShimsDir: "/usr/local/unirtm/shims",
ToolVersions: map[string]string{
"ruby": "3.2.0",
},
}
script, err := manager.GenerateActivationScript(ctx, config)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Shell: %s\n", script.Shell)
fmt.Println("Uses fish syntax:", containsString(script.Content, "set -gx"))
fmt.Println("Contains ruby version:", containsString(script.Content, "UNIRTM_RUBY_VERSION"))
}
// Helper function for examples
func containsString(s, substr string) bool {
return len(s) > 0 && len(substr) > 0 &&
(s == substr || len(s) >= len(substr) &&
(s[:len(substr)] == substr || s[len(s)-len(substr):] == substr ||
findSubstring(s, substr)))
}
func findSubstring(s, substr string) bool {
for i := 0; i <= len(s)-len(substr); i++ {
if s[i:i+len(substr)] == substr {
return true
}
}
return false
}
Output: Shell: fish Uses fish syntax: true Contains ruby version: true
Example (MultipleTools) ¶
ExampleActivationManager_GenerateActivationScript_multipleTools demonstrates generating an activation script with multiple tools.
package main
import (
"github.com/snowdreamtech/unirtm/internal/provider"
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
manager := service.NewActivationManager("/usr/local/unirtm/shims", "/var/lib/unirtm", provider.NewRegistry())
ctx := context.Background()
config := service.ActivationConfig{
Shell: service.ShellBash,
Scope: service.ScopeGlobal,
ShimsDir: "/usr/local/unirtm/shims",
ToolVersions: map[string]string{
"node": "20.0.0",
"python": "3.11.0",
"go": "1.21.0",
"ruby": "3.2.0",
},
}
script, err := manager.GenerateActivationScript(ctx, config)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Shell: %s\n", script.Shell)
fmt.Printf("Tool count: %d\n", len(config.ToolVersions))
fmt.Println("Contains all tools:",
containsString(script.Content, "UNIRTM_NODE_VERSION") &&
containsString(script.Content, "UNIRTM_PYTHON_VERSION") &&
containsString(script.Content, "UNIRTM_GO_VERSION") &&
containsString(script.Content, "UNIRTM_RUBY_VERSION"))
}
// Helper function for examples
func containsString(s, substr string) bool {
return len(s) > 0 && len(substr) > 0 &&
(s == substr || len(s) >= len(substr) &&
(s[:len(substr)] == substr || s[len(s)-len(substr):] == substr ||
findSubstring(s, substr)))
}
func findSubstring(s, substr string) bool {
for i := 0; i <= len(s)-len(substr); i++ {
if s[i:i+len(substr)] == substr {
return true
}
}
return false
}
Output: Shell: bash Tool count: 4 Contains all tools: true
Example (Powershell) ¶
ExampleActivationManager_GenerateActivationScript_powershell demonstrates generating an activation script for PowerShell.
package main
import (
"github.com/snowdreamtech/unirtm/internal/provider"
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
manager := service.NewActivationManager("/usr/local/unirtm/shims", "/var/lib/unirtm", provider.NewRegistry())
ctx := context.Background()
config := service.ActivationConfig{
Shell: service.ShellPowerShell,
Scope: service.ScopeGlobal,
ShimsDir: "/usr/local/unirtm/shims",
ToolVersions: map[string]string{
"dotnet": "8.0.0",
},
EnvVars: map[string]string{
"DOTNET_CLI_TELEMETRY_OPTOUT": "1",
},
}
script, err := manager.GenerateActivationScript(ctx, config)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Shell: %s\n", script.Shell)
fmt.Println("Uses PowerShell syntax:", containsString(script.Content, "$env:"))
fmt.Println("Contains dotnet version:", containsString(script.Content, "UNIRTM_DOTNET_VERSION"))
fmt.Println("Contains telemetry opt-out:", containsString(script.Content, "DOTNET_CLI_TELEMETRY_OPTOUT"))
}
// Helper function for examples
func containsString(s, substr string) bool {
return len(s) > 0 && len(substr) > 0 &&
(s == substr || len(s) >= len(substr) &&
(s[:len(substr)] == substr || s[len(s)-len(substr):] == substr ||
findSubstring(s, substr)))
}
func findSubstring(s, substr string) bool {
for i := 0; i <= len(s)-len(substr); i++ {
if s[i:i+len(substr)] == substr {
return true
}
}
return false
}
Output: Shell: powershell Uses PowerShell syntax: true Contains dotnet version: true Contains telemetry opt-out: true
func (*ActivationManager) GenerateGlobalActivation ¶
func (m *ActivationManager) GenerateGlobalActivation(ctx context.Context, shell ShellType, toolVersions map[string]string) (*ActivationScript, error)
GenerateGlobalActivation generates activation for global (system-wide) tool versions.
Requirements: 15.5
Example ¶
ExampleActivationManager_GenerateGlobalActivation demonstrates generating a global activation script for bash.
package main
import (
"github.com/snowdreamtech/unirtm/internal/provider"
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
manager := service.NewActivationManager("/usr/local/unirtm/shims", "/var/lib/unirtm", provider.NewRegistry())
ctx := context.Background()
toolVersions := map[string]string{
"node": "20.0.0",
"python": "3.11.0",
"go": "1.21.0",
}
script, err := manager.GenerateGlobalActivation(ctx, service.ShellBash, toolVersions)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Shell: %s\n", script.Shell)
fmt.Println("Script contains PATH modification:", containsString(script.Content, "export PATH="))
fmt.Println("Script contains node version:", containsString(script.Content, "UNIRTM_NODE_VERSION"))
fmt.Println("Script contains python version:", containsString(script.Content, "UNIRTM_PYTHON_VERSION"))
fmt.Println("Script contains go version:", containsString(script.Content, "UNIRTM_GO_VERSION"))
}
// Helper function for examples
func containsString(s, substr string) bool {
return len(s) > 0 && len(substr) > 0 &&
(s == substr || len(s) >= len(substr) &&
(s[:len(substr)] == substr || s[len(s)-len(substr):] == substr ||
findSubstring(s, substr)))
}
func findSubstring(s, substr string) bool {
for i := 0; i <= len(s)-len(substr); i++ {
if s[i:i+len(substr)] == substr {
return true
}
}
return false
}
Output: Shell: bash Script contains PATH modification: true Script contains node version: true Script contains python version: true Script contains go version: true
func (*ActivationManager) GenerateProjectActivation ¶
func (m *ActivationManager) GenerateProjectActivation(ctx context.Context, shell ShellType, projectDir string, toolVersions map[string]string, envVars map[string]string) (*ActivationScript, error)
GenerateProjectActivation generates activation for project-specific tool versions.
Requirements: 15.4
Example ¶
ExampleActivationManager_GenerateProjectActivation demonstrates generating a project-specific activation script.
package main
import (
"github.com/snowdreamtech/unirtm/internal/provider"
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
manager := service.NewActivationManager("/usr/local/unirtm/shims", "/var/lib/unirtm", provider.NewRegistry())
ctx := context.Background()
toolVersions := map[string]string{
"node": "18.0.0",
}
envVars := map[string]string{
"NODE_ENV": "development",
"DEBUG": "app:*",
}
script, err := manager.GenerateProjectActivation(
ctx,
service.ShellBash,
"/home/user/myproject",
toolVersions,
envVars,
)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Shell: %s\n", script.Shell)
fmt.Println("Script contains project directory:", containsString(script.Content, "UNIRTM_PROJECT_DIR"))
fmt.Println("Script contains NODE_ENV:", containsString(script.Content, "NODE_ENV"))
fmt.Println("Script contains DEBUG:", containsString(script.Content, "DEBUG"))
fmt.Println("Scope is project:", containsString(script.Content, "UNIRTM_ACTIVATION_SCOPE=\"project\""))
}
// Helper function for examples
func containsString(s, substr string) bool {
return len(s) > 0 && len(substr) > 0 &&
(s == substr || len(s) >= len(substr) &&
(s[:len(substr)] == substr || s[len(s)-len(substr):] == substr ||
findSubstring(s, substr)))
}
func findSubstring(s, substr string) bool {
for i := 0; i <= len(s)-len(substr); i++ {
if s[i:i+len(substr)] == substr {
return true
}
}
return false
}
Output: Shell: bash Script contains project directory: true Script contains NODE_ENV: true Script contains DEBUG: true Scope is project: true
type ActivationScope ¶
type ActivationScope string
ActivationScope represents the scope of activation.
const ( // ScopeGlobal represents global (system-wide) activation ScopeGlobal ActivationScope = "global" // ScopeProject represents project-specific activation ScopeProject ActivationScope = "project" )
type ActivationScript ¶
type ActivationScript struct {
// Shell is the target shell type
Shell ShellType
// Content is the script content
Content string
// Instructions are human-readable instructions for using the script
Instructions string
}
ActivationScript represents a generated activation script.
type AuditLogEntry ¶
type AuditLogEntry struct {
// Operation is the type of operation being performed
Operation OperationType
// Tool is the name of the tool (optional, may be empty for non-tool operations)
Tool string
// Version is the version of the tool (optional)
Version string
// Status is the operation status (success or failure)
Status OperationStatus
// Error is the error message if the operation failed (optional)
Error string
// Duration is the operation duration in milliseconds
Duration int64
// GpgVerification is the result of GPG signature verification
GpgVerification string
// Metadata contains additional operation-specific data (optional)
Metadata map[string]interface{}
}
AuditLogEntry represents a high-level audit log entry with convenience fields
type AuditService ¶
type AuditService struct {
// contains filtered or unexported fields
}
AuditService provides high-level audit logging functionality Validates Requirements: 7.8 (Audit logging), 8.1 (Log all operations), 8.5 (Audit log recording)
func NewAuditService ¶
func NewAuditService(repo repository.AuditRepository) *AuditService
NewAuditService creates a new audit service
func (*AuditService) GetLogsByOperation ¶
func (s *AuditService) GetLogsByOperation(ctx context.Context, operation OperationType, limit int) ([]*repository.AuditEntry, error)
GetLogsByOperation returns audit logs filtered by operation type
func (*AuditService) GetLogsByStatus ¶
func (s *AuditService) GetLogsByStatus(ctx context.Context, status OperationStatus, limit int) ([]*repository.AuditEntry, error)
GetLogsByStatus returns audit logs filtered by status
Example ¶
ExampleAuditService_GetLogsByStatus demonstrates how to query failed operations
package main
import (
"context"
"fmt"
"time"
"github.com/snowdreamtech/unirtm/internal/database"
"github.com/snowdreamtech/unirtm/internal/repository/sqlite"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
// Initialize database (in-memory for example)
db, err := database.Open(context.Background(), database.Config{
Path: ":memory:",
WALMode: false,
})
if err != nil {
panic(err)
}
defer db.Close()
// Create audit repository
auditRepo, err := sqlite.NewAuditRepository(db.Conn())
if err != nil {
panic(err)
}
defer auditRepo.Close()
// Create audit service
auditService := service.NewAuditService(auditRepo)
ctx := context.Background()
// Log successful and failed operations
_ = auditService.LogInstall(ctx, "node", "20.0.0", 2*time.Second, nil)
_ = auditService.LogInstall(ctx, "python", "3.11.0", 5*time.Second, fmt.Errorf("download failed"))
_ = auditService.LogInstall(ctx, "go", "1.21.0", 3*time.Second, fmt.Errorf("checksum mismatch"))
// Query failed operations
failedLogs, err := auditService.GetLogsByStatus(ctx, service.StatusFailure, 10)
if err != nil {
panic(err)
}
fmt.Printf("Found %d failed operations\n", len(failedLogs))
}
Output: Found 2 failed operations
func (*AuditService) GetLogsByTimeRange ¶
func (s *AuditService) GetLogsByTimeRange(ctx context.Context, startTime, endTime time.Time, limit int) ([]*repository.AuditEntry, error)
GetLogsByTimeRange returns audit logs within a time range
func (*AuditService) GetLogsByTool ¶
func (s *AuditService) GetLogsByTool(ctx context.Context, tool string, limit int) ([]*repository.AuditEntry, error)
GetLogsByTool returns audit logs filtered by tool name
Example ¶
ExampleAuditService_GetLogsByTool demonstrates how to query audit logs for a specific tool
package main
import (
"context"
"fmt"
"time"
"github.com/snowdreamtech/unirtm/internal/database"
"github.com/snowdreamtech/unirtm/internal/repository/sqlite"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
// Initialize database (in-memory for example)
db, err := database.Open(context.Background(), database.Config{
Path: ":memory:",
WALMode: false,
})
if err != nil {
panic(err)
}
defer db.Close()
// Create audit repository
auditRepo, err := sqlite.NewAuditRepository(db.Conn())
if err != nil {
panic(err)
}
defer auditRepo.Close()
// Create audit service
auditService := service.NewAuditService(auditRepo)
ctx := context.Background()
// Log operations for different tools
_ = auditService.LogInstall(ctx, "node", "20.0.0", 2*time.Second, nil)
_ = auditService.LogActivate(ctx, "node", "20.0.0", 100*time.Millisecond, nil)
_ = auditService.LogInstall(ctx, "python", "3.11.0", 3*time.Second, nil)
// Query logs for a specific tool
nodeLogs, err := auditService.GetLogsByTool(ctx, "node", 10)
if err != nil {
panic(err)
}
fmt.Printf("Found %d operations for node\n", len(nodeLogs))
}
Output: Found 2 operations for node
func (*AuditService) GetRecentLogs ¶
func (s *AuditService) GetRecentLogs(ctx context.Context, limit int) ([]*repository.AuditEntry, error)
GetRecentLogs returns the most recent audit logs
func (*AuditService) LogActivate ¶
func (s *AuditService) LogActivate(ctx context.Context, tool, version string, duration time.Duration, err error) error
LogActivate logs a tool activation operation
func (*AuditService) LogCachePurge ¶
func (s *AuditService) LogCachePurge(ctx context.Context, duration time.Duration, purgedCount int, err error) error
LogCachePurge logs a cache purge operation
func (*AuditService) LogConfigLoad ¶
func (s *AuditService) LogConfigLoad(ctx context.Context, configPath string, duration time.Duration, err error) error
LogConfigLoad logs a configuration load operation
func (*AuditService) LogConfigUpdate ¶
func (s *AuditService) LogConfigUpdate(ctx context.Context, configPath string, duration time.Duration, err error) error
LogConfigUpdate logs a configuration update operation
func (*AuditService) LogDeactivate ¶
func (s *AuditService) LogDeactivate(ctx context.Context, tool, version string, duration time.Duration, err error) error
LogDeactivate logs a tool deactivation operation
func (*AuditService) LogIndexUpdate ¶
func (s *AuditService) LogIndexUpdate(ctx context.Context, backend string, duration time.Duration, toolCount int, err error) error
LogIndexUpdate logs an index update operation
func (*AuditService) LogInstall ¶
func (s *AuditService) LogInstall(ctx context.Context, tool, version string, duration time.Duration, err error) error
LogInstall logs a tool installation operation
Example ¶
ExampleAuditService_LogInstall demonstrates how to use the audit service to log tool installations
package main
import (
"context"
"fmt"
"time"
"github.com/snowdreamtech/unirtm/internal/database"
"github.com/snowdreamtech/unirtm/internal/repository/sqlite"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
// Initialize database (in-memory for example)
db, err := database.Open(context.Background(), database.Config{
Path: ":memory:",
WALMode: false,
})
if err != nil {
panic(err)
}
defer db.Close()
// Create audit repository
auditRepo, err := sqlite.NewAuditRepository(db.Conn())
if err != nil {
panic(err)
}
defer auditRepo.Close()
// Create audit service
auditService := service.NewAuditService(auditRepo)
// Log a successful installation
ctx := context.Background()
err = auditService.LogInstall(ctx, "node", "20.0.0", 2*time.Second, nil)
if err != nil {
panic(err)
}
// Log a failed installation
installErr := fmt.Errorf("download failed: connection timeout")
err = auditService.LogInstall(ctx, "python", "3.11.0", 5*time.Second, installErr)
if err != nil {
panic(err)
}
// Query recent logs
logs, err := auditService.GetRecentLogs(ctx, 10)
if err != nil {
panic(err)
}
fmt.Printf("Found %d audit log entries\n", len(logs))
}
Output: Found 2 audit log entries
func (*AuditService) LogOperation ¶
func (s *AuditService) LogOperation(ctx context.Context, entry *AuditLogEntry) error
LogOperation logs an operation to the audit log This is the primary method for recording audit entries
Example ¶
ExampleAuditService_LogOperation demonstrates how to use the audit service with custom metadata
package main
import (
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/database"
"github.com/snowdreamtech/unirtm/internal/repository/sqlite"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
// Initialize database (in-memory for example)
db, err := database.Open(context.Background(), database.Config{
Path: ":memory:",
WALMode: false,
})
if err != nil {
panic(err)
}
defer db.Close()
// Create audit repository
auditRepo, err := sqlite.NewAuditRepository(db.Conn())
if err != nil {
panic(err)
}
defer auditRepo.Close()
// Create audit service
auditService := service.NewAuditService(auditRepo)
// Log an operation with custom metadata
ctx := context.Background()
entry := &service.AuditLogEntry{
Operation: service.OperationInstall,
Tool: "node",
Version: "20.0.0",
Status: service.StatusSuccess,
Duration: 2500,
Metadata: map[string]interface{}{
"backend": "github",
"download_url": "https://github.com/nodejs/node/releases/download/v20.0.0/node-v20.0.0.tar.gz",
"size_bytes": 45678901,
"checksum": "abc123def456",
},
}
err = auditService.LogOperation(ctx, entry)
if err != nil {
panic(err)
}
fmt.Println("Operation logged successfully")
}
Output: Operation logged successfully
func (*AuditService) LogUninstall ¶
func (s *AuditService) LogUninstall(ctx context.Context, tool, version string, duration time.Duration, err error) error
LogUninstall logs a tool uninstallation operation
func (*AuditService) LogUpdate ¶
func (s *AuditService) LogUpdate(ctx context.Context, tool, oldVersion, newVersion string, duration time.Duration, err error) error
LogUpdate logs a tool update operation
func (*AuditService) LogVersionResolve ¶
func (s *AuditService) LogVersionResolve(ctx context.Context, tool, versionSpec, resolvedVersion string, duration time.Duration, err error) error
LogVersionResolve logs a version resolution operation
func (*AuditService) QueryAuditLogs ¶
func (s *AuditService) QueryAuditLogs(ctx context.Context, filter repository.AuditFilter) ([]*repository.AuditEntry, error)
QueryAuditLogs queries audit logs with filters
Example ¶
ExampleAuditService_QueryAuditLogs demonstrates how to query audit logs with filters
package main
import (
"context"
"fmt"
"time"
"github.com/snowdreamtech/unirtm/internal/database"
"github.com/snowdreamtech/unirtm/internal/repository/sqlite"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
// Initialize database (in-memory for example)
db, err := database.Open(context.Background(), database.Config{
Path: ":memory:",
WALMode: false,
})
if err != nil {
panic(err)
}
defer db.Close()
// Create audit repository
auditRepo, err := sqlite.NewAuditRepository(db.Conn())
if err != nil {
panic(err)
}
defer auditRepo.Close()
// Create audit service
auditService := service.NewAuditService(auditRepo)
ctx := context.Background()
// Log some operations
_ = auditService.LogInstall(ctx, "node", "20.0.0", 2*time.Second, nil)
_ = auditService.LogInstall(ctx, "python", "3.11.0", 3*time.Second, nil)
_ = auditService.LogUninstall(ctx, "go", "1.20.0", 1*time.Second, nil)
// Query logs by operation type
installLogs, err := auditService.GetLogsByOperation(ctx, service.OperationInstall, 10)
if err != nil {
panic(err)
}
fmt.Printf("Found %d install operations\n", len(installLogs))
}
Output: Found 2 install operations
type AutoActivationManager ¶
type AutoActivationManager struct {
// contains filtered or unexported fields
}
AutoActivationManager manages automatic environment activation based on directory changes.
It detects when the user enters a directory with a UniRTM configuration file and automatically activates the project's toolchain. When leaving the directory, it restores the previous environment.
Requirements: 15.6, 15.7
Example (Deactivation) ¶
ExampleAutoActivationManager_deactivation demonstrates leaving a project.
package main
import (
"github.com/snowdreamtech/unirtm/internal/provider"
"context"
"fmt"
"os"
"path/filepath"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
// Create temporary project directory
tmpDir, _ := os.MkdirTemp("", "unirtm-example-*")
defer os.RemoveAll(tmpDir)
projectDir := filepath.Join(tmpDir, "myproject")
_ = os.MkdirAll(projectDir, 0755)
_ = os.WriteFile(filepath.Join(projectDir, "unirtm.toml"), []byte("# project"), 0644)
// Create managers
activationMgr := service.NewActivationManager("/tmp/shims", "/tmp/data", provider.NewRegistry())
autoMgr := service.NewAutoActivationManager(activationMgr)
// Start in project
currentState := &service.EnvironmentState{
ProjectDir: projectDir,
ToolVersions: map[string]string{
"python": "3.11.0",
},
EnvVars: make(map[string]string),
PreviousPath: "/usr/bin:/bin",
}
// Leave project
event := service.DirectoryChangeEvent{
OldDir: projectDir,
NewDir: tmpDir,
Shell: service.ShellBash,
}
ctx := context.Background()
change, err := autoMgr.HandleDirectoryChange(ctx, event, currentState)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Action: %s\n", change.Action)
fmt.Printf("Project deactivated: %t\n", change.NewState.ProjectDir == "")
fmt.Printf("Tools cleared: %t\n", len(change.NewState.ToolVersions) == 0)
}
Output: Action: deactivate Project deactivated: true Tools cleared: true
Example (ProjectSwitch) ¶
ExampleAutoActivationManager_projectSwitch demonstrates switching between projects.
package main
import (
"github.com/snowdreamtech/unirtm/internal/provider"
"context"
"fmt"
"os"
"path/filepath"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
// Create temporary project directories
tmpDir, _ := os.MkdirTemp("", "unirtm-example-*")
defer os.RemoveAll(tmpDir)
project1 := filepath.Join(tmpDir, "project1")
project2 := filepath.Join(tmpDir, "project2")
_ = os.MkdirAll(project1, 0755)
_ = os.MkdirAll(project2, 0755)
_ = os.WriteFile(filepath.Join(project1, "unirtm.toml"), []byte("# project1"), 0644)
_ = os.WriteFile(filepath.Join(project2, "unirtm.toml"), []byte("# project2"), 0644)
// Create managers
activationMgr := service.NewActivationManager("/tmp/shims", "/tmp/data", provider.NewRegistry())
autoMgr := service.NewAutoActivationManager(activationMgr)
// Start in project1
currentState := &service.EnvironmentState{
ProjectDir: project1,
ToolVersions: map[string]string{
"node": "18.0.0",
},
EnvVars: make(map[string]string),
PreviousPath: "/usr/bin:/bin",
}
// Switch to project2
event := service.DirectoryChangeEvent{
OldDir: project1,
NewDir: project2,
Shell: service.ShellBash,
}
ctx := context.Background()
change, err := autoMgr.HandleDirectoryChange(ctx, event, currentState)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Action: %s\n", change.Action)
fmt.Printf("Old project: %s\n", filepath.Base(currentState.ProjectDir))
fmt.Printf("New project: %s\n", filepath.Base(change.NewState.ProjectDir))
}
Output: Action: switch Old project: project1 New project: project2
func NewAutoActivationManager ¶
func NewAutoActivationManager(activationManager *ActivationManager) *AutoActivationManager
NewAutoActivationManager creates a new AutoActivationManager.
func (*AutoActivationManager) GenerateHookEnvScript ¶
func (m *AutoActivationManager) GenerateHookEnvScript(shell ShellType, exePath string) (string, error)
GenerateHookEnvScript generates a shell hook script that can be evaluated on every prompt.
This script is designed to be evaluated by the shell on every prompt (e.g., via PROMPT_COMMAND in bash or precmd in zsh). It detects directory changes and outputs the appropriate activation or deactivation commands.
Requirements: 15.6, 15.7
Example ¶
ExampleAutoActivationManager_GenerateHookEnvScript demonstrates how to generate a shell hook script for automatic activation.
package main
import (
"github.com/snowdreamtech/unirtm/internal/provider"
"fmt"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
activationMgr := service.NewActivationManager("/tmp/shims", "/tmp/data", provider.NewRegistry())
autoMgr := service.NewAutoActivationManager(activationMgr)
// Generate hook script for bash
hookScript, err := autoMgr.GenerateHookEnvScript(service.ShellBash, "/usr/local/bin/unirtm")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
// The hook script can be added to ~/.bashrc
fmt.Println("# Add this to your ~/.bashrc:")
fmt.Println(hookScript)
// Output will include:
// # Add this to your ~/.bashrc:
// # UniRTM auto-activation hook
// _unirtm_hook() {
// ...
// }
}
Output:
func (*AutoActivationManager) HandleDirectoryChange ¶
func (m *AutoActivationManager) HandleDirectoryChange(ctx context.Context, event DirectoryChangeEvent, currentState *EnvironmentState) (*ActivationChange, error)
HandleDirectoryChange handles a directory change event and returns the activation changes needed.
This is the main entry point for auto-activation. It detects whether the directory change requires activating, deactivating, or switching project environments.
Requirements: 15.6, 15.7
Example ¶
ExampleAutoActivationManager_HandleDirectoryChange demonstrates how to use the Auto-Activation Manager to handle directory changes and automatically activate project toolchains.
package main
import (
"github.com/snowdreamtech/unirtm/internal/provider"
"context"
"fmt"
"os"
"path/filepath"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
// Create temporary project directory for demonstration
tmpDir, _ := os.MkdirTemp("", "unirtm-example-*")
defer os.RemoveAll(tmpDir)
projectDir := filepath.Join(tmpDir, "myproject")
_ = os.MkdirAll(projectDir, 0755)
_ = os.WriteFile(filepath.Join(projectDir, "unirtm.toml"), []byte("# project config"), 0644)
// Create managers
activationMgr := service.NewActivationManager("/tmp/shims", "/tmp/data", provider.NewRegistry())
autoMgr := service.NewAutoActivationManager(activationMgr)
// Initial state (no project active)
currentState := &service.EnvironmentState{
ProjectDir: "",
ToolVersions: make(map[string]string),
EnvVars: make(map[string]string),
PreviousPath: "/usr/bin:/bin",
}
// Simulate entering the project directory
event := service.DirectoryChangeEvent{
OldDir: tmpDir,
NewDir: projectDir,
Shell: service.ShellBash,
}
ctx := context.Background()
change, err := autoMgr.HandleDirectoryChange(ctx, event, currentState)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Action: %s\n", change.Action)
fmt.Printf("Project sub-directory: %s\n", filepath.Base(change.NewState.ProjectDir))
fmt.Printf("Script generated: %t\n", len(change.Script) > 0)
}
Output: Action: activate Project sub-directory: myproject Script generated: true
func (*AutoActivationManager) LoadConfigByDir ¶
func (m *AutoActivationManager) LoadConfigByDir(projectDir string) (map[string]string, map[string]string, []string, error)
LoadConfigByDir loads UniRTM configuration from the specified directory.
type BackendRegistry ¶
type BackendRegistry interface {
// ResolveVersion resolves a version specification to a concrete version
ResolveVersion(ctx context.Context, tool string, versionSpec string) (string, error)
}
BackendRegistry defines the interface for accessing backend information.
type CacheManager ¶
type CacheManager struct {
// contains filtered or unexported fields
}
CacheManager manages cache storage with TTL, checksum verification, and automatic cleanup Validates Requirements: 10.1, 10.2, 10.3, 10.4, 10.5, 10.6, 10.7, 10.8
func NewCacheManager ¶
func NewCacheManager(repo repository.CacheRepository, auditRepo repository.AuditRepository, config CacheManagerConfig) (*CacheManager, error)
NewCacheManager creates a new cache manager instance
func (*CacheManager) AutoCleanup ¶
func (cm *CacheManager) AutoCleanup(ctx context.Context) error
AutoCleanup performs automatic cleanup when cache size exceeds threshold Validates Requirement: 10.7 (Support automatic cleanup when size exceeds threshold)
func (*CacheManager) Delete ¶
func (cm *CacheManager) Delete(ctx context.Context, key string) error
Delete removes a cache entry
func (*CacheManager) Get ¶
Get retrieves a cache entry with checksum verification Validates Requirements: 10.4 (Verify checksum before use), 10.8 (Track cache hits/misses)
func (*CacheManager) GetCacheSize ¶
func (cm *CacheManager) GetCacheSize() (int64, error)
GetCacheSize returns the current cache size in bytes Validates Requirement: 10.7 (Track cache size)
func (*CacheManager) GetStats ¶
func (cm *CacheManager) GetStats() CacheStats
GetStats returns the current cache statistics Validates Requirement: 10.8 (Record cache hits and misses for performance monitoring)
func (*CacheManager) GetWithChecksum ¶
func (cm *CacheManager) GetWithChecksum(ctx context.Context, key string, expectedChecksum string) ([]byte, error)
GetWithChecksum retrieves a cache entry and verifies its checksum Validates Requirements: 10.4 (Verify checksum), 10.5 (Delete and re-download on failure)
func (*CacheManager) PurgeAll ¶
func (cm *CacheManager) PurgeAll(ctx context.Context) error
PurgeAll removes all cache entries Validates Requirement: 10.6 (Support manual cache purging - clear all)
func (*CacheManager) PurgeByPrefix ¶
func (cm *CacheManager) PurgeByPrefix(ctx context.Context, prefix string) error
PurgeByPrefix removes all cache entries with keys matching the given prefix Validates Requirement: 10.6 (Support manual cache purging - clear tool-specific)
func (*CacheManager) PurgeExpired ¶
func (cm *CacheManager) PurgeExpired(ctx context.Context) error
PurgeExpired removes all expired cache entries Validates Requirement: 10.6 (Support manual cache purging - clear expired)
func (*CacheManager) ResetStats ¶
func (cm *CacheManager) ResetStats()
ResetStats resets the cache statistics
type CacheManagerConfig ¶
type CacheManagerConfig struct {
// CacheDir is the directory where cached artifacts are stored
CacheDir string
// MaxCacheSize is the maximum cache size in bytes (default 5GB)
MaxCacheSize int64
}
CacheManagerConfig holds configuration for the cache manager
type CacheStats ¶
CacheStats tracks cache hit/miss statistics for performance monitoring Validates Requirement: 10.8 (Record cache hits and misses)
type ChecksumAlgorithm ¶
type ChecksumAlgorithm string
ChecksumAlgorithm represents a checksum algorithm.
const ( AlgorithmSHA256 ChecksumAlgorithm = "sha256" AlgorithmSHA512 ChecksumAlgorithm = "sha512" )
type CleanupManager ¶
type CleanupManager struct {
// contains filtered or unexported fields
}
CleanupManager removes orphaned files and partial installations.
Validates Requirement: 3.4
func NewCleanupManager ¶
func NewCleanupManager(installRepo repository.InstallationRepository, installsDir string) *CleanupManager
NewCleanupManager creates a new CleanupManager.
func (*CleanupManager) CleanOrphaned ¶
CleanOrphaned removes orphaned installation directories.
Validates Requirement: 3.4
func (*CleanupManager) FindOrphaned ¶
func (cm *CleanupManager) FindOrphaned(ctx context.Context) ([]string, error)
FindOrphaned finds installation directories that have no corresponding database record.
Validates Requirement: 3.4
type ConcurrentInstallResult ¶
ConcurrentInstallResult represents the result of a single concurrent installation.
type ConcurrentManager ¶
type ConcurrentManager struct {
// contains filtered or unexported fields
}
ConcurrentManager manages parallel tool installations with controlled concurrency.
It respects dependency order, limits concurrent operations to avoid resource exhaustion, serializes database writes, and reports progress per-operation.
Validates Requirements: 18.1, 18.2, 18.3, 18.4, 18.5, 18.6, 18.7
func NewConcurrentManager ¶
func NewConcurrentManager(im Installer, config ConcurrentManagerConfig) *ConcurrentManager
NewConcurrentManager creates a new ConcurrentManager.
Validates Requirement: 18.2 (configurable concurrency limit)
func (*ConcurrentManager) InstallAll ¶
func (cm *ConcurrentManager) InstallAll(ctx context.Context, requests []ToolInstallRequest) ([]ConcurrentInstallResult, error)
InstallAll installs multiple tools concurrently, respecting dependency order.
It:
- Topologically sorts by DependsOn to determine installation order (Req 18.6)
- Uses errgroup for parallel execution within each dependency layer (Req 18.1)
- Limits concurrency to maxConcurrency (Req 18.2)
- Reports progress via progressFn (Req 18.5)
- Cancels dependents if a dependency fails (Req 18.7)
Validates Requirements: 18.1, 18.2, 18.4, 18.5, 18.6, 18.7
type ConcurrentManagerConfig ¶
type ConcurrentManagerConfig struct {
// MaxConcurrency is the maximum parallel operations (0 = CPU count).
MaxConcurrency int
// ProgressFn is an optional progress callback.
ProgressFn func(tool, version, status string)
}
ConcurrentManagerConfig holds configuration for ConcurrentManager.
type ConfigValidationResult ¶
type ConfigValidationResult struct {
// Issues contains all detected problems (errors and warnings).
Issues []ValidationIssue
// Valid is true only when there are no error-severity issues.
Valid bool
}
ConfigValidationResult holds all issues found during validation.
Validates Requirements: 13.1–13.7
func (*ConfigValidationResult) HasErrors ¶
func (r *ConfigValidationResult) HasErrors() bool
HasErrors returns true if any error-severity issues exist.
func (*ConfigValidationResult) Summary ¶
func (r *ConfigValidationResult) Summary() string
Summary returns a concise human-readable summary of the validation result.
type ConfigValidator ¶
type ConfigValidator struct {
// contains filtered or unexported fields
}
ConfigValidator performs semantic validation of UniRTM configuration.
It goes beyond basic TOML syntax to verify:
- Tool names exist in the index (Req 13.1)
- Version specifiers are syntactically valid (Req 13.2)
- Backend references are registered (Req 13.3)
- Unknown top-level fields generate warnings (Req 13.4)
- Environment references are valid (Req 13.5)
- Validation-only mode (Req 13.6)
- All errors reported, not just first (Req 13.7)
Validates Requirements: 13.1, 13.2, 13.3, 13.4, 13.5, 13.6, 13.7
func NewConfigValidator ¶
func NewConfigValidator(indexRepo repository.IndexRepository, registeredBackends []string) *ConfigValidator
NewConfigValidator creates a new ConfigValidator.
func (*ConfigValidator) Validate ¶
func (cv *ConfigValidator) Validate(ctx context.Context, cfg *config.Config) *ConfigValidationResult
Validate performs full semantic validation of the given configuration.
All issues are collected and returned (Req 13.7 — report all, not just first).
type ConflictingRequester ¶
ConflictingRequester represents a tool that requires a specific version.
type Dependency ¶
type Dependency struct {
Tool string // Tool name
VersionConstraint string // Version constraint (e.g., ">=1.20.0", "^3.11", "latest")
}
Dependency represents a tool dependency with version constraints.
type DependencyConflict ¶
type DependencyConflict struct {
Tool string
Requesters []ConflictingRequester
}
DependencyConflict represents a version conflict between dependencies.
type DependencyGraph ¶
type DependencyGraph struct {
// contains filtered or unexported fields
}
DependencyGraph represents the dependency relationships between tools.
type DependencyResolver ¶
type DependencyResolver struct {
// contains filtered or unexported fields
}
DependencyResolver manages tool dependency resolution and installation ordering. It parses dependency declarations, builds dependency graphs, detects circular dependencies, and determines the correct installation order using topological sort.
func NewDependencyResolver ¶
func NewDependencyResolver( providerRegistry ProviderRegistry, backendRegistry BackendRegistry, versionManager *VersionManager, ) *DependencyResolver
NewDependencyResolver creates a new DependencyResolver.
func (*DependencyResolver) DetectCircularDependencies ¶
func (r *DependencyResolver) DetectCircularDependencies(graph *DependencyGraph) error
DetectCircularDependencies checks for circular dependencies in the graph. Returns an error if a circular dependency is detected.
Validates: Requirement 16.3
func (*DependencyResolver) ParseDependencies ¶
func (r *DependencyResolver) ParseDependencies(ctx context.Context, tools []string) (*DependencyGraph, error)
ParseDependencies parses dependency declarations from provider metadata for the given tools. It returns a dependency graph containing all tools and their dependencies.
Validates: Requirement 16.1
func (*DependencyResolver) ResolveDependencies ¶
func (r *DependencyResolver) ResolveDependencies(ctx context.Context, tools []string, requestedVersions map[string]string) (*InstallationOrder, error)
ResolveDependencies is the main entry point that combines all dependency resolution steps. It parses dependencies, detects circular dependencies, resolves version constraints, and returns the installation order.
Validates: Requirements 16.1, 16.2, 16.3, 16.4, 16.5, 16.6, 16.7
func (*DependencyResolver) ResolveVersionConstraints ¶
func (r *DependencyResolver) ResolveVersionConstraints(ctx context.Context, graph *DependencyGraph, requestedVersions map[string]string) error
ResolveVersionConstraints resolves version constraints for all tools in the dependency graph. It checks for conflicts where multiple tools depend on different versions of the same tool.
Validates: Requirements 16.6, 16.7
func (*DependencyResolver) TopologicalSort ¶
func (r *DependencyResolver) TopologicalSort(graph *DependencyGraph) (*InstallationOrder, error)
TopologicalSort performs a topological sort on the dependency graph to determine the correct installation order. Tools with no dependencies come first, followed by tools that depend on them.
Validates: Requirement 16.4
type DirectoryChangeEvent ¶
type DirectoryChangeEvent struct {
// OldDir is the previous working directory
OldDir string
// NewDir is the new working directory
NewDir string
// Shell is the current shell type
Shell ShellType
}
DirectoryChangeEvent represents a directory change event.
type EnvironmentState ¶
type EnvironmentState struct {
// ProjectDir is the project directory (empty if no project is active)
ProjectDir string
// ToolVersions maps tool names to their active versions
ToolVersions map[string]string
// EnvVars contains environment variables set by the activation
EnvVars map[string]string
// PreviousPath is the PATH before activation
PreviousPath string
}
EnvironmentState represents the state of the environment at a point in time.
type GenerateOptions ¶
type GenerateOptions struct {
// Tools is the subset of tools to refresh. Empty = all tools from config.
Tools []string
// Platforms is the list of platform keys to generate entries for.
// Empty = only current platform. Use lockfile.StandardPlatforms for all.
Platforms []string
}
GenerateOptions controls what `unirtm lock` generates.
type Generator ¶
type Generator struct {
// contains filtered or unexported fields
}
Generator creates shim scripts for installed tools.
func NewGenerator ¶
NewGenerator creates a new shim Generator.
func (*Generator) GenerateShim ¶
GenerateShim creates a shim script for the given tool.
On Unix systems it creates a bash/sh script; on Windows it creates both a .cmd batch file and a .ps1 PowerShell script.
Validates Requirements: 14.1, 14.2, 14.3, 14.4
func (*Generator) RemoveShim ¶
RemoveShim removes the shim script(s) for the given tool.
func (*Generator) ShimExists ¶
ShimExists reports whether a shim script exists for the given tool.
type IncompleteOperation ¶
type IncompleteOperation struct {
// Tool is the name of the tool that was being installed/updated.
Tool string
// Version is the version that was being installed/updated.
Version string
// PartialPath is the path of the partial installation (if any).
PartialPath string
// StartedAt is when the operation started.
StartedAt time.Time
// AuditID is the ID of the audit log entry for this operation.
AuditID int64
}
IncompleteOperation represents an operation that did not complete successfully.
type IndexManager ¶
type IndexManager struct {
// contains filtered or unexported fields
}
IndexManager manages tool index storage, retrieval, and updates Validates Requirements: 11.1, 11.2, 11.3, 11.4, 11.5, 11.6, 11.7, 11.8
Example (BackendManagement) ¶
This example demonstrates backend management
package main
import (
"fmt"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
// Create index manager
indexManager, err := service.NewIndexManager(
nil, // indexRepo
nil, // auditRepo
nil, // backends
service.IndexManagerConfig{},
)
if err != nil {
fmt.Println(err)
}
// Register a backend
// githubBackend := backend.NewGitHubBackend(...)
// indexManager.RegisterBackend("github", githubBackend)
// List registered backends
backends := indexManager.ListBackends()
fmt.Printf("Registered backends: %v\n", backends)
// Unregister a backend
indexManager.UnregisterBackend("github")
}
Output:
Example (Basic) ¶
This example demonstrates basic tool index management operations
package main
import (
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
// Note: This example uses mock implementations for demonstration
// In production, use actual repository and backend implementations
ctx := context.Background()
// Create index manager (using mocks for example)
indexManager, err := service.NewIndexManager(
nil, // indexRepo - use actual implementation
nil, // auditRepo - use actual implementation
nil, // backends - register actual backends
service.IndexManagerConfig{},
)
if err != nil {
fmt.Println(err)
}
// Add a tool to the index
err = indexManager.UpsertTool(ctx,
"node",
"Node.js JavaScript runtime",
"https://nodejs.org",
"MIT",
"github",
&service.ToolMetadata{
AvailableVersions: []string{"20.0.0", "18.0.0", "16.0.0"},
Tags: []string{"runtime", "javascript", "nodejs"},
Stars: 95000,
},
)
if err != nil {
fmt.Println(err)
}
// Retrieve the tool
entry, err := indexManager.GetTool(ctx, "node")
if err != nil {
fmt.Println(err)
}
fmt.Printf("Tool: %s\n", entry.Tool)
fmt.Printf("Description: %s\n", entry.Description)
fmt.Printf("Backend: %s\n", entry.Backend)
}
Output:
Example (FilterByBackend) ¶
This example demonstrates filtering tools by backend
package main
import (
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
ctx := context.Background()
// Create index manager
indexManager, err := service.NewIndexManager(
nil, // indexRepo
nil, // auditRepo
nil, // backends
service.IndexManagerConfig{},
)
if err != nil {
fmt.Println(err)
}
// Filter tools by backend
githubTools, err := indexManager.FilterByBackend(ctx, "github")
if err != nil {
fmt.Println(err)
}
fmt.Printf("Found %d tools from GitHub backend\n", len(githubTools))
}
Output:
Example (Metadata) ¶
This example demonstrates getting tool metadata
package main
import (
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
ctx := context.Background()
// Create index manager
indexManager, err := service.NewIndexManager(
nil, // indexRepo
nil, // auditRepo
nil, // backends
service.IndexManagerConfig{},
)
if err != nil {
fmt.Println(err)
}
// Get tool metadata
metadata, err := indexManager.GetToolMetadata(ctx, "node")
if err != nil {
fmt.Println(err)
}
fmt.Printf("Available versions: %v\n", metadata.AvailableVersions)
fmt.Printf("Tags: %v\n", metadata.Tags)
fmt.Printf("Stars: %d\n", metadata.Stars)
}
Output:
Example (Offline) ¶
This example demonstrates offline operation
package main
import (
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
ctx := context.Background()
// Create index manager
indexManager, err := service.NewIndexManager(
nil, // indexRepo
nil, // auditRepo
nil, // backends
service.IndexManagerConfig{},
)
if err != nil {
fmt.Println(err)
}
// Check if offline operation is possible
capable, err := indexManager.IsOfflineCapable(ctx)
if err != nil {
fmt.Println(err)
}
if !capable {
fmt.Println("No cached index available. Please run 'unirtm index update' when online.")
return
}
// Search offline
results, err := indexManager.SearchTools(ctx, service.SearchOptions{
Query: "python",
})
if err != nil {
fmt.Println(err)
}
fmt.Printf("Found %d tools matching 'python'\n", len(results))
}
Output:
Example (Pagination) ¶
This example demonstrates pagination
package main
import (
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
ctx := context.Background()
// Create index manager
indexManager, err := service.NewIndexManager(
nil, // indexRepo
nil, // auditRepo
nil, // backends
service.IndexManagerConfig{},
)
if err != nil {
fmt.Println(err)
}
// Search with pagination
pageSize := 10
page := 0
for {
results, err := indexManager.SearchTools(ctx, service.SearchOptions{
Query: "runtime",
Limit: pageSize,
Offset: page * pageSize,
})
if err != nil {
fmt.Println(err)
}
if len(results) == 0 {
break
}
fmt.Printf("Page %d: %d results\n", page+1, len(results))
for _, tool := range results {
fmt.Printf(" - %s\n", tool.Tool)
}
page++
}
}
Output:
Example (Search) ¶
This example demonstrates searching for tools
package main
import (
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
ctx := context.Background()
// Create index manager (using mocks for example)
indexManager, err := service.NewIndexManager(
nil, // indexRepo
nil, // auditRepo
nil, // backends
service.IndexManagerConfig{},
)
if err != nil {
fmt.Println(err)
}
// Search for tools
results, err := indexManager.SearchTools(ctx, service.SearchOptions{
Query: "javascript",
})
if err != nil {
fmt.Println(err)
}
for _, tool := range results {
fmt.Printf("%s: %s\n", tool.Tool, tool.Description)
}
}
Output:
Example (StaleDetection) ¶
This example demonstrates stale index detection
package main
import (
"context"
"fmt"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
ctx := context.Background()
// Create index manager with 7-day stale timeout
indexManager, err := service.NewIndexManager(
nil, // indexRepo
nil, // auditRepo
nil, // backends
service.IndexManagerConfig{
StaleTimeout: 7 * 24 * 60 * 60 * 1000000000, // 7 days in nanoseconds
},
)
if err != nil {
fmt.Println(err)
}
// Check if index is stale
isStale, err := indexManager.IsStale(ctx)
if err != nil {
fmt.Println(err)
}
if isStale {
fmt.Println("Index is stale, updating...")
err = indexManager.UpdateFromAllBackends(ctx)
if err != nil {
fmt.Printf("Failed to update index: %v", err)
}
}
}
Output:
func NewIndexManager ¶
func NewIndexManager(repo repository.IndexRepository, auditRepo repository.AuditRepository, backends map[string]backend.Backend, config IndexManagerConfig) (*IndexManager, error)
NewIndexManager creates a new index manager instance
func (*IndexManager) DeleteTool ¶
func (im *IndexManager) DeleteTool(ctx context.Context, tool string) error
DeleteTool removes a tool from the index
func (*IndexManager) FilterByBackend ¶
func (im *IndexManager) FilterByBackend(ctx context.Context, backendName string) ([]*repository.IndexEntry, error)
FilterByBackend filters tools by backend type Validates Requirement: 11.5 (Filter by backend type)
func (*IndexManager) GetStaleAge ¶
GetStaleAge returns how long ago the index was last updated
func (*IndexManager) GetTool ¶
func (im *IndexManager) GetTool(ctx context.Context, tool string) (*repository.IndexEntry, error)
GetTool retrieves a tool from the index by name
func (*IndexManager) GetToolMetadata ¶
func (im *IndexManager) GetToolMetadata(ctx context.Context, tool string) (*ToolMetadata, error)
GetToolMetadata retrieves and parses the metadata for a tool
func (*IndexManager) IsOfflineCapable ¶
func (im *IndexManager) IsOfflineCapable(ctx context.Context) (bool, error)
IsOfflineCapable checks if the index has cached data for offline operation Validates Requirement: 11.8 (Support offline operation using cached index)
func (*IndexManager) IsStale ¶
func (im *IndexManager) IsStale(ctx context.Context) (bool, error)
IsStale checks if the index is stale (older than the configured timeout) Validates Requirement: 11.7 (Detect stale index)
func (*IndexManager) ListBackends ¶
func (im *IndexManager) ListBackends() []string
ListBackends returns the names of all registered backends
func (*IndexManager) ListTools ¶
func (im *IndexManager) ListTools(ctx context.Context) ([]*repository.IndexEntry, error)
ListTools lists all tools in the index Validates Requirement: 11.1 (Maintain searchable index)
func (*IndexManager) PromptForUpdate ¶
PromptForUpdate checks if the index is stale and returns a prompt message Validates Requirement: 11.7 (Prompt for update when stale)
func (*IndexManager) RegisterBackend ¶
func (im *IndexManager) RegisterBackend(backendName string, b backend.Backend)
RegisterBackend registers a backend for index updates
func (*IndexManager) SearchTools ¶
func (im *IndexManager) SearchTools(ctx context.Context, options SearchOptions) ([]*repository.IndexEntry, error)
SearchTools searches for tools by name, description, or tags Validates Requirement: 11.4 (Search by name, description, tags)
func (*IndexManager) SupportsOffline ¶
func (im *IndexManager) SupportsOffline() bool
SupportsOffline indicates whether the index manager can operate offline Validates Requirement: 11.8 (Support offline operation)
func (*IndexManager) UnregisterBackend ¶
func (im *IndexManager) UnregisterBackend(backendName string)
UnregisterBackend removes a backend from the index manager
func (*IndexManager) UpdateFromAllBackends ¶
func (im *IndexManager) UpdateFromAllBackends(ctx context.Context) error
UpdateFromAllBackends updates the index from all registered backends Validates Requirement: 11.2 (Update from multiple sources)
func (*IndexManager) UpdateFromBackend ¶
func (im *IndexManager) UpdateFromBackend(ctx context.Context, backendName string) error
UpdateFromBackend updates the index from a specific backend Validates Requirement: 11.2 (Update from multiple sources)
func (*IndexManager) UpsertTool ¶
func (im *IndexManager) UpsertTool(ctx context.Context, tool string, description string, homepage string, license string, backendName string, metadata *ToolMetadata) error
UpsertTool creates or updates a tool in the index Validates Requirement: 11.1 (Maintain searchable index)
type IndexManagerConfig ¶
type IndexManagerConfig struct {
// StaleTimeout is the duration after which the index is considered stale (default 7 days)
StaleTimeout time.Duration
}
IndexManagerConfig holds configuration for the index manager
type InstallationManager ¶
type InstallationManager struct {
// contains filtered or unexported fields
}
InstallationManager manages tool installation workflow.
func NewInstallationManager ¶
func NewInstallationManager( backendRegistry *backend.Registry, providerRegistry *provider.Registry, downloadManager *download.Manager, installRepo repository.InstallationRepository, txManager transaction.TransactionManager, settings *config.Settings, ) *InstallationManager
NewInstallationManager creates a new installation manager without lockfile support.
func NewInstallationManagerWithLock ¶
func NewInstallationManagerWithLock( backendRegistry *backend.Registry, providerRegistry *provider.Registry, downloadManager *download.Manager, installRepo repository.InstallationRepository, txManager transaction.TransactionManager, lockService *LockService, settings *config.Settings, ) *InstallationManager
NewInstallationManagerWithLock creates an InstallationManager that reads and writes unirtm.lock for reproducible, API-call-free installations.
func (*InstallationManager) AutoDetectBackend ¶
func (im *InstallationManager) AutoDetectBackend(toolName string) string
AutoDetectBackend attempts to identify the best backend for a given tool name.
func (*InstallationManager) Close ¶ added in v0.3.6
func (im *InstallationManager) Close() error
Close releases the underlying database connection held by the manager. It is safe to call Close on a nil or already-closed manager.
func (*InstallationManager) EnsureInstalled ¶
func (im *InstallationManager) EnsureInstalled(ctx context.Context, tools map[string]config.ToolConfig) error
EnsureInstalled checks if all tools in the configuration are installed, and installs any missing ones.
func (*InstallationManager) EnsureInstalledFromSpecs ¶
func (im *InstallationManager) EnsureInstalledFromSpecs(ctx context.Context, tools map[string]ToolSpec) error
EnsureInstalledFromSpecs checks if all tools in the specs are installed, and installs any missing ones.
func (*InstallationManager) Install ¶
func (im *InstallationManager) Install(ctx context.Context, toolKey, tool, version, backendName string) error
Install performs the complete installation workflow for a tool. Workflow: check → download → verify → extract → activate → record
func (*InstallationManager) IsInstalled ¶
func (im *InstallationManager) IsInstalled(ctx context.Context, tool, versionSpec, backendName string) (bool, *repository.Installation)
IsInstalled checks if a tool version is installed, considering version variants (v-prefix).
func (*InstallationManager) ParseToolSpec ¶
func (im *InstallationManager) ParseToolSpec(spec string) (backend, tool, version string, explicit bool)
ParseToolSpec parses a tool specification string (e.g., "node@20", "github:cli/cli@v2.0.0") into its constituent parts: backend, tool name, version, and whether the version was explicit.
func (*InstallationManager) ResolveExecutable ¶
func (im *InstallationManager) ResolveExecutable(ctx context.Context, exeName string, platform backend.Platform) (string, map[string]string, error)
ResolveExecutable finds the absolute path and environment variables for a given executable name by searching through installed tools in the current context.
func (*InstallationManager) ResolveToolEnvBySpec ¶
func (im *InstallationManager) ResolveToolEnvBySpec( toolName, version, backendName string, ) map[string]string
ResolveToolEnvBySpec returns the environment variables exported by an installed tool identified by its name, version, and backend. It is used by the exec sub-command to inject per-tool environment variables (e.g. GOROOT, JAVA_HOME, UNIRTM_<TOOL>_VERSION) and bin-directory PATH entries.
If the tool is not installed or the provider does not export env vars the function returns an empty (non-nil) map and a nil error.
func (*InstallationManager) SelectVersionInteractive ¶
func (im *InstallationManager) SelectVersionInteractive(ctx context.Context, tool, backendName string) (string, error)
SelectVersionInteractive opens an interactive menu to select a tool version.
func (*InstallationManager) SetAliases ¶
func (im *InstallationManager) SetAliases(aliases map[string]map[string]string)
SetAliases sets the version aliases for tools.
func (*InstallationManager) SetDB ¶ added in v0.3.6
func (im *InstallationManager) SetDB(db *database.DB)
SetDB stores the underlying database handle so it can be closed with Close(). This must be called after NewInstallationManagerWithLock when the caller owns the database lifetime.
func (*InstallationManager) SetToolConfigs ¶
func (im *InstallationManager) SetToolConfigs(toolConfigs map[string]config.ToolConfig)
SetToolConfigs sets the tool configurations for hooks.
func (*InstallationManager) SortTools ¶
func (im *InstallationManager) SortTools(tools map[string]config.ToolConfig) []ToolToInstall
SortTools sorts tools such that dependencies are installed before dependent tools.
func (*InstallationManager) SortToolsFromSpecs ¶
func (im *InstallationManager) SortToolsFromSpecs(tools map[string]ToolSpec) []ToolToInstall
SortToolsFromSpecs sorts tools such that dependencies are installed before dependent tools.
type InstallationOrder ¶
type InstallationOrder struct {
// Tools is the ordered list of tool names
Tools []string
// Versions maps tool names to their resolved versions
Versions map[string]string
}
InstallationOrder represents the ordered list of tools to install.
type Installer ¶ added in v0.2.0
type Installer interface {
IsInstalled(ctx context.Context, tool, version, backend string) (bool, *repository.Installation)
Install(ctx context.Context, toolKey, tool, version, backend string) error
}
Installer defines the installation interface required by ConcurrentManager.
type LockService ¶
type LockService struct {
// contains filtered or unexported fields
}
LockService manages the unirtm.lock file lifecycle:
- Resolving download info from the lockfile (bypassing remote API calls)
- Writing back resolved info after a successful install
- Generating / refreshing lockfile entries for multiple platforms
- Enforcing strict mode (UNIRTM_LOCKED=1): fail if URL not in lockfile
func NewLockService ¶
func NewLockService(opts LockServiceOptions) (*LockService, error)
NewLockService creates a LockService, loading the lockfile from disk if it exists.
func (*LockService) CheckStrict ¶
func (ls *LockService) CheckStrict(lockKey, version string, platform backend.Platform) error
CheckStrict verifies that the lockfile contains a URL for the given lockKey on the current platform when strict mode is enabled. Returns an error (which callers must propagate) when the URL is absent.
func (*LockService) Generate ¶
func (ls *LockService) Generate( ctx context.Context, tools map[string]ToolSpec, opts GenerateOptions, ) error
Generate resolves download info from the backend for each (tool, platform) pair and writes the result into the lockfile.
ctx is used for backend API calls (cancellation, deadline). tools is a map of toolName → {version, backendName} from the project config.
func (*LockService) IsEmpty ¶
func (ls *LockService) IsEmpty() bool
IsEmpty reports whether the lockfile contains any tool entries.
func (*LockService) IsStrictMode ¶
func (ls *LockService) IsStrictMode() bool
IsStrictMode reports whether strict mode is active.
func (*LockService) Path ¶
func (ls *LockService) Path() string
Path returns the filesystem path of the managed lockfile.
func (*LockService) RecordInstall ¶
func (ls *LockService) RecordInstall( lockKey, backendName string, info *backend.VersionInfo, ) error
RecordInstall writes the resolved VersionInfo back into the lockfile for the current platform. The lockfile is saved to disk immediately so that subsequent runs can use the cached URL.
This is called by InstallationManager after a successful download.
func (*LockService) RemoveTool ¶
func (ls *LockService) RemoveTool(lockKey string) error
RemoveTool removes all lockfile entries for a tool (called on uninstall).
func (*LockService) Resolve ¶
func (ls *LockService) Resolve( lockKey, version string, platform backend.Platform, ) (*backend.VersionInfo, bool)
Resolve returns a *backend.VersionInfo populated from the lockfile for the given lockKey, version and current platform. Returns (nil, false) when the lockfile has no entry for this combination.
Callers (InstallationManager) should use the returned VersionInfo directly and skip the remote backend API call when ok==true.
func (*LockService) SetBackendRegistry ¶
func (ls *LockService) SetBackendRegistry(r *backend.Registry)
SetBackendRegistry wires the backend registry used by Generate().
func (*LockService) Validate ¶
func (ls *LockService) Validate() error
Validate runs structural validation on the in-memory lockfile.
type LockServiceOptions ¶
type LockServiceOptions struct {
// LockfilePath overrides the default lock file location.
// When empty, GetLockFilePath() from env/paths is used.
LockfilePath string
// StrictMode mirrors the UNIRTM_LOCKED env var / settings.locked setting.
// When true, Install() will fail if the tool+platform URL is absent from
// the lockfile (preventing any outbound API call).
StrictMode bool
}
LockServiceOptions configures a LockService.
type MigrationManager ¶
type MigrationManager struct{}
MigrationManager converts mise/asdf configuration to UniRTM format.
Validates Requirements: 21.1, 21.2, 21.3, 21.4, 21.5, 21.6, 21.7
func NewMigrationManager ¶
func NewMigrationManager() *MigrationManager
NewMigrationManager creates a new MigrationManager.
func (*MigrationManager) FormatReport ¶
func (mm *MigrationManager) FormatReport(report *MigrationReport) string
FormatReport returns a human-readable migration report string.
Validates Requirement: 21.7 (generate migration report)
func (*MigrationManager) MigrateDirectory ¶
func (mm *MigrationManager) MigrateDirectory(ctx context.Context, dir string, dryRun bool) ([]*MigrationReport, error)
MigrateDirectory scans a directory for mise/asdf config files and migrates them.
Validates Requirement: 21.4
func (*MigrationManager) MigrateFile ¶
func (mm *MigrationManager) MigrateFile(ctx context.Context, sourcePath string, outputPath string, dryRun bool) (*MigrationReport, error)
MigrateFile converts a single mise/asdf configuration file to UniRTM format.
It auto-detects the source format from the filename.
Validates Requirements: 21.1, 21.2, 21.3, 21.6
type MigrationReport ¶
type MigrationReport struct {
Source string
Tools []MigrationTool
OutputFile string
UnsupportedFields []string
Errors []string
DryRun bool
GeneratedAt time.Time
}
MigrationReport summarizes the result of a migration operation.
type MigrationSource ¶
type MigrationSource string
MigrationSource represents the source format of a migration.
const ( // MigrationSourceMiseToml represents a .mise.toml file. MigrationSourceMiseToml MigrationSource = "mise.toml" // MigrationSourceToolVersions represents an asdf/mise .tool-versions file. MigrationSourceToolVersions MigrationSource = ".tool-versions" )
type MigrationTool ¶
type MigrationTool struct {
Name string
Version string
Backend string
Provider string
Source MigrationSource
}
MigrationTool represents a single tool discovered during migration.
type OfflineManager ¶
type OfflineManager struct {
// contains filtered or unexported fields
}
OfflineManager detects network availability and provides offline operation support.
Validates Requirements: 19.1, 19.2, 19.3, 19.4, 19.5, 19.6, 19.7
func NewOfflineManager ¶
func NewOfflineManager() *OfflineManager
NewOfflineManager creates a new OfflineManager.
func (*OfflineManager) CanOperateOffline ¶
func (om *OfflineManager) CanOperateOffline(operation string) bool
CanOperateOffline reports whether the given operation can be performed offline.
Validates Requirements: 19.2, 19.3, 19.4, 19.5
func (*OfflineManager) IsOnline ¶
func (om *OfflineManager) IsOnline(ctx context.Context) bool
IsOnline checks whether network connectivity is available.
It caches the result for cacheDuration to avoid repeated probes.
Validates Requirement: 19.1 (network availability detection)
func (*OfflineManager) RequireOnline ¶
func (om *OfflineManager) RequireOnline(ctx context.Context, operation string) error
RequireOnline checks network connectivity and returns an error if offline.
Validates Requirement: 19.6 (clear feedback when network required but unavailable)
func (*OfflineManager) SkipIfOffline ¶
func (om *OfflineManager) SkipIfOffline(ctx context.Context, operationName string) bool
SkipIfOffline logs a message and returns true if the operation should be skipped because we are offline. Used for optional network operations.
Validates Requirement: 19.7 (skip optional network operations when offline)
type OperationMetric ¶
type OperationMetric struct {
Tool string
Version string
Phase OperationPhase
StartedAt time.Time
Duration time.Duration
Success bool
}
OperationMetric records the duration of a single timed operation.
Validates Requirement: 17.1 (track operation durations)
type OperationPhase ¶
type OperationPhase string
OperationPhase represents a timed phase of a tool operation.
const ( PhaseDownload OperationPhase = "download" PhaseExtract OperationPhase = "extract" PhaseInstall OperationPhase = "install" PhaseActivate OperationPhase = "activate" PhaseCacheHit OperationPhase = "cache_hit" PhaseCacheMiss OperationPhase = "cache_miss" )
type OperationStatus ¶
type OperationStatus string
OperationStatus represents the status of an operation
const ( // StatusSuccess indicates the operation completed successfully StatusSuccess OperationStatus = "success" // StatusFailure indicates the operation failed StatusFailure OperationStatus = "failure" )
type OperationType ¶
type OperationType string
OperationType represents the type of operation being audited
const ( // OperationInstall represents a tool installation operation OperationInstall OperationType = "install" // OperationUninstall represents a tool uninstallation operation OperationUninstall OperationType = "uninstall" // OperationActivate represents a tool activation operation OperationActivate OperationType = "activate" // OperationDeactivate represents a tool deactivation operation OperationDeactivate OperationType = "deactivate" // OperationUpdate represents a tool update operation OperationUpdate OperationType = "update" // OperationCachePurge represents a cache purge operation OperationCachePurge OperationType = "cache_purge" // OperationConfigLoad represents a configuration load operation OperationConfigLoad OperationType = "config_load" // OperationConfigUpdate represents a configuration update operation OperationConfigUpdate OperationType = "config_update" // OperationIndexUpdate represents an index update operation OperationIndexUpdate OperationType = "index_update" // OperationVersionResolve represents a version resolution operation OperationVersionResolve OperationType = "version_resolve" )
type PerformanceMonitor ¶
type PerformanceMonitor struct {
// contains filtered or unexported fields
}
PerformanceMonitor tracks operation durations and cache hit rates.
Validates Requirements: 17.1, 17.2, 17.3, 17.4, 17.5, 17.6, 17.7
func NewPerformanceMonitor ¶
func NewPerformanceMonitor(auditRepo repository.AuditRepository) *PerformanceMonitor
NewPerformanceMonitor creates a new PerformanceMonitor.
func (*PerformanceMonitor) AllReports ¶
func (pm *PerformanceMonitor) AllReports() []*PerformanceReport
AllReports generates a performance report for every phase that has data.
func (*PerformanceMonitor) CacheHitRate ¶
func (pm *PerformanceMonitor) CacheHitRate() float64
CacheHitRate returns the current cache hit rate as a percentage (0-100).
Validates Requirement: 17.2 (track cache hit rates)
func (*PerformanceMonitor) DetectRegressions ¶
func (pm *PerformanceMonitor) DetectRegressions(threshold float64) map[OperationPhase]float64
DetectRegressions compares current p95 against baselines.
Returns a map of phase → regression percentage (positive = slower than baseline).
Validates Requirement: 17.7
func (*PerformanceMonitor) FormatReport ¶
func (pm *PerformanceMonitor) FormatReport(r *PerformanceReport) string
FormatReport formats a PerformanceReport as a human-readable string.
func (*PerformanceMonitor) Record ¶
func (pm *PerformanceMonitor) Record(ctx context.Context, metric OperationMetric)
Record records an operation metric.
Validates Requirements: 17.1, 17.2, 17.3, 17.4
func (*PerformanceMonitor) Report ¶
func (pm *PerformanceMonitor) Report(phase OperationPhase) *PerformanceReport
Report generates a performance report for the given phase.
Validates Requirements: 17.5, 17.6 (percentile reports)
func (*PerformanceMonitor) SetBaseline ¶
func (pm *PerformanceMonitor) SetBaseline(phase OperationPhase, d time.Duration)
SetBaseline sets the baseline duration for regression detection.
Validates Requirement: 17.7 (detect performance regressions)
func (*PerformanceMonitor) Track ¶
func (pm *PerformanceMonitor) Track(ctx context.Context, tool, version string, phase OperationPhase) func(success bool)
Track is a convenience helper that times a function call and records the result.
Usage:
done := pm.Track(ctx, tool, version, PhaseDownload) err := doDownload(...) done(err == nil)
type PerformanceReport ¶
type PerformanceReport struct {
Phase OperationPhase
Count int
Average time.Duration
P50 time.Duration
P95 time.Duration
P99 time.Duration
Min time.Duration
Max time.Duration
}
PerformanceReport summarizes performance metrics.
Validates Requirements: 17.5 (performance data querying), 17.6 (reports)
type PluginManager ¶
type PluginManager struct {
// contains filtered or unexported fields
}
PluginManager handles discovery, loading, and registration of Go plugins.
Validates Requirements: 22.1, 22.2
func NewPluginManager ¶
func NewPluginManager(pluginsDir string, br *backend.Registry, pr *provider.Registry) *PluginManager
NewPluginManager creates a new PluginManager.
Validates Requirements: 22.1, 22.2
func (*PluginManager) Cleanup ¶
func (pm *PluginManager) Cleanup()
Cleanup kills all the running plugin processes.
func (*PluginManager) ListLoaded ¶
func (pm *PluginManager) ListLoaded() []PluginMetadata
ListLoaded returns metadata for all loaded plugins.
func (*PluginManager) LoadAll ¶
func (pm *PluginManager) LoadAll(ctx context.Context) error
LoadAll discovers and loads all plugins from the plugins directory.
Validates Requirements: 22.1, 22.4 (validate compatibility), 22.5 (isolate failures)
func (*PluginManager) PluginsDir ¶
func (pm *PluginManager) PluginsDir() string
PluginsDir returns the directory where plugins are loaded from.
type PluginMetadata ¶
type PluginMetadata struct {
Name string
Type string // "backend" or "provider"
APIVersion string
Path string
}
PluginMetadata holds information about a loaded plugin.
type ProgressReporter ¶
ProgressReporter is a callback for concurrent download progress reporting.
type ProviderMetadata ¶
type ProviderMetadata struct {
Name string
Dependencies []Dependency
}
ProviderMetadata contains metadata about a tool provider including dependencies.
type ProviderRegistry ¶
type ProviderRegistry interface {
// GetProvider returns the provider for a given tool name
GetProvider(tool string) (ProviderMetadata, error)
}
ProviderRegistry defines the interface for accessing provider metadata.
type RecoveryAction ¶
type RecoveryAction string
RecoveryAction represents the action to take for an incomplete operation.
const ( // RecoveryActionRetry retries the incomplete operation. RecoveryActionRetry RecoveryAction = "retry" // RecoveryActionRollback rolls back the incomplete operation. RecoveryActionRollback RecoveryAction = "rollback" // RecoveryActionIgnore ignores the incomplete operation. RecoveryActionIgnore RecoveryAction = "ignore" )
type RecoveryManager ¶
type RecoveryManager struct {
// contains filtered or unexported fields
}
RecoveryManager detects and recovers from incomplete operations.
It checks for in-progress audit log entries and partial installation directories on startup, then offers retry/rollback/ignore options.
Validates Requirements: 3.6, 12.4, 12.5
func NewRecoveryManager ¶
func NewRecoveryManager( installRepo repository.InstallationRepository, auditRepo repository.AuditRepository, installsDir string, ) *RecoveryManager
NewRecoveryManager creates a new RecoveryManager.
func (*RecoveryManager) DetectIncomplete ¶
func (rm *RecoveryManager) DetectIncomplete(ctx context.Context) ([]IncompleteOperation, error)
DetectIncomplete scans the audit log for in-progress operations and cross-references them with the filesystem to find partial installations.
Validates Requirements: 12.4, 12.5
func (*RecoveryManager) Recover ¶
func (rm *RecoveryManager) Recover(ctx context.Context, op IncompleteOperation, action RecoveryAction) error
Recover processes an incomplete operation according to the given action.
Validates Requirements: 3.6, 12.4, 12.5
func (*RecoveryManager) RecoverAll ¶
func (rm *RecoveryManager) RecoverAll(ctx context.Context) (*RecoveryReport, error)
RecoverAll runs recovery for all detected incomplete operations using the rollback action by default.
Validates Requirements: 3.6, 12.4, 12.5
type RecoveryReport ¶
type RecoveryReport struct {
// Detected lists incomplete operations that were found.
Detected []IncompleteOperation
// Cleaned lists paths that were cleaned up.
Cleaned []string
// Errors lists errors encountered during recovery.
Errors []string
}
RecoveryReport summarizes the recovery process.
type SearchOptions ¶
type SearchOptions struct {
// Query is the search query string (matches name, description, tags)
Query string
// Backend filters results by backend type (empty = all backends)
Backend string
// Limit limits the number of results (0 = no limit)
Limit int
// Offset skips the first N results (for pagination)
Offset int
}
SearchOptions defines options for searching the tool index
type SecurityManager ¶
type SecurityManager struct {
// contains filtered or unexported fields
}
SecurityManager handles checksum verification, signature checking, and security audit logging for installed tools.
Validates Requirements: 20.3, 20.4, 20.5, 20.6, 20.7
func NewSecurityManager ¶
func NewSecurityManager(auditRepo repository.AuditRepository) *SecurityManager
NewSecurityManager creates a new SecurityManager.
func (*SecurityManager) VerifyChecksum ¶
func (sm *SecurityManager) VerifyChecksum(ctx context.Context, tool, version, filePath, expected string) (*SecurityVerificationResult, error)
VerifyChecksum verifies the checksum of a downloaded file.
Validates Requirements: 20.3 (checksum verification), 20.5 (store checksum in database)
func (*SecurityManager) VerifyInstallation ¶
func (sm *SecurityManager) VerifyInstallation(ctx context.Context, installation *repository.Installation, binaryPath string) (*SecurityVerificationResult, error)
VerifyInstallation verifies that an installed tool's checksum matches the stored value.
Validates Requirement: 20.5 (checksum storage and re-verification)
type SecurityVerificationResult ¶
type SecurityVerificationResult struct {
Tool string
Version string
FilePath string
Algorithm ChecksumAlgorithm
Expected string
Actual string
Passed bool
Warning string
}
SecurityVerificationResult represents the result of a security check.
type ShellConfigManager ¶
type ShellConfigManager struct {
// contains filtered or unexported fields
}
ShellConfigManager handles persistent configuration changes in shell RC files.
func NewShellConfigManager ¶
func NewShellConfigManager(formatter output.Formatter, dryRun bool) *ShellConfigManager
NewShellConfigManager creates a new ShellConfigManager.
func (*ShellConfigManager) GetConfigPath ¶
func (m *ShellConfigManager) GetConfigPath(shell ShellType) (string, error)
GetConfigPath returns the standard configuration file path for the given shell.
type ShellType ¶
type ShellType string
ShellType represents the type of shell for activation scripts.
func DetectShell ¶
DetectShell detects the current shell from the environment.
It checks the SHELL environment variable and returns the corresponding ShellType. If the shell cannot be detected, it returns a sensible default for the platform.
Example ¶
ExampleDetectShell demonstrates detecting the current shell.
package main
import (
"fmt"
"github.com/snowdreamtech/unirtm/internal/service"
)
func main() {
shell, err := service.DetectShell()
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Detected shell type: %s\n", shell)
fmt.Println("Shell is supported:",
shell == service.ShellBash ||
shell == service.ShellZsh ||
shell == service.ShellFish ||
shell == service.ShellPowerShell)
// Output will vary by platform, but should always be supported
// Example output on Linux:
// Detected shell type: bash
// Shell is supported: true
}
Output:
type ToolInstallRequest ¶
type ToolInstallRequest struct {
ToolKey string // The full key as specified in the configuration
Tool string // The stripped tool name
Version string
Backend string
// DependsOn lists tool names that must be installed before this one.
DependsOn []string
}
ToolInstallRequest specifies a tool and version to install.
type ToolMetadata ¶
type ToolMetadata struct {
// AvailableVersions is a list of available versions for the tool
AvailableVersions []string `json:"available_versions,omitempty"`
// Tags are searchable tags for the tool
Tags []string `json:"tags,omitempty"`
// ReleaseDate is the date of the latest release
ReleaseDate string `json:"release_date,omitempty"`
// Stars is the number of GitHub stars (if applicable)
Stars int `json:"stars,omitempty"`
// LastUpdated is when this metadata was last updated
LastUpdated time.Time `json:"last_updated"`
}
ToolMetadata represents extended metadata for a tool in the index
type ToolToInstall ¶
type ToolToInstall struct {
OriginalName string
ToolName string
BackendName string
Version string
Config config.ToolConfig
}
ToolToInstall represents a tool with its resolved backend information for sorting.
type UpdateInfo ¶
type UpdateInfo struct {
Tool string // Tool name
CurrentVersion string // Currently installed version
LatestVersion string // Latest available version
Backend string // Backend used for the tool
UpdateRequired bool // Whether an update is available
}
UpdateInfo represents information about an available update for a tool.
type UpdateManager ¶
type UpdateManager struct {
// contains filtered or unexported fields
}
UpdateManager manages tool updates with version checking, preview, and rollback support.
Validates Requirements: 25.1, 25.2, 25.3, 25.4, 25.5, 25.6, 25.7
func NewUpdateManager ¶
func NewUpdateManager( backendRegistry *backend.Registry, providerRegistry *provider.Registry, downloadManager *download.Manager, installRepo repository.InstallationRepository, auditRepo repository.AuditRepository, txManager transaction.TransactionManager, configManager *config.Config, ) *UpdateManager
NewUpdateManager creates a new update manager.
func (*UpdateManager) CheckForUpdates ¶
func (um *UpdateManager) CheckForUpdates(ctx context.Context) ([]UpdateInfo, error)
CheckForUpdates checks for newer versions of installed tools.
Validates Requirement 25.1: Check for newer versions of installed tools
func (*UpdateManager) DisableAutomaticUpdates ¶
func (um *UpdateManager) DisableAutomaticUpdates(ctx context.Context) error
DisableAutomaticUpdates disables automatic updates.
func (*UpdateManager) EnableAutomaticUpdates ¶
func (um *UpdateManager) EnableAutomaticUpdates(ctx context.Context, schedule string) error
EnableAutomaticUpdates enables automatic updates with the specified schedule.
Validates Requirement 25.6: Support automatic updates (opt-in, configurable schedule)
Note: This method stores the automatic update configuration. The actual scheduling and execution would be handled by a separate scheduler service or cron job that calls UpdateAll periodically.
func (*UpdateManager) PreviewUpdates ¶
func (um *UpdateManager) PreviewUpdates(ctx context.Context) (*UpdatePreview, error)
PreviewUpdates shows a preview of what will be updated before applying.
Validates Requirement 25.5: Show a preview of what will be updated before applying
func (*UpdateManager) UpdateAll ¶
func (um *UpdateManager) UpdateAll(ctx context.Context) ([]UpdateResult, error)
UpdateAll updates all tools to their latest versions.
Validates Requirement 25.3: Support updating all tools to their latest versions Validates Requirement 25.4: Respect version constraints in configuration files
func (*UpdateManager) UpdateTool ¶
func (um *UpdateManager) UpdateTool(ctx context.Context, tool, targetVersion string) (*UpdateResult, error)
UpdateTool updates a specific tool to a specific version.
Validates Requirement 25.2: Support updating a specific tool to a specific version Validates Requirement 25.7: Rollback to the previous version when an update fails
type UpdatePreview ¶
type UpdatePreview struct {
Updates []UpdateInfo // List of tools that will be updated
TotalUpdates int // Total number of updates
EstimatedTime time.Duration // Estimated time for all updates
}
UpdatePreview represents a preview of what will be updated.
type UpdateResult ¶
type UpdateResult struct {
Tool string // Tool name
OldVersion string // Previous version
NewVersion string // New version after update
Success bool // Whether the update succeeded
Error string // Error message if update failed
Duration time.Duration // Time taken for the update
RolledBack bool // Whether a rollback was performed
RollbackReason string // Reason for rollback if applicable
}
UpdateResult represents the result of an update operation.
type ValidationIssue ¶
type ValidationIssue struct {
Severity ValidationSeverity
Field string
Message string
}
ValidationIssue represents a single configuration validation problem.
type ValidationSeverity ¶
type ValidationSeverity string
ValidationSeverity represents the severity of a validation issue.
const ( SeverityError ValidationSeverity = "error" SeverityWarning ValidationSeverity = "warning" )
type VersionManager ¶
type VersionManager struct {
// contains filtered or unexported fields
}
VersionManager handles version constraint parsing and resolution. It enforces explicit version requirements and delegates to backends for resolution.
func NewVersionManager ¶
func NewVersionManager(backends map[string]backend.Backend) *VersionManager
NewVersionManager creates a new VersionManager with the given backends.
func (*VersionManager) ListAvailableVersions ¶
func (vm *VersionManager) ListAvailableVersions(ctx context.Context, backendName, tool string, platform backend.Platform) ([]backend.VersionInfo, error)
ListAvailableVersions lists all available versions for a tool from the specified backend. This is useful for displaying available versions to users.
Returns a list of VersionInfo objects in descending order (newest first).
func (*VersionManager) ParseVersionConstraint ¶
func (vm *VersionManager) ParseVersionConstraint(versionStr string) (*version.Version, error)
ParseVersionConstraint parses a version constraint string into a Version object. This is a convenience wrapper around ParseVersion that enforces explicit version requirements.
Returns an error if: - The version string is empty (explicit version required) - The version string is invalid
func (*VersionManager) ResolveVersion ¶
func (vm *VersionManager) ResolveVersion(ctx context.Context, backendName, tool, versionSpec string, platform backend.Platform) (*backend.VersionInfo, error)
ResolveVersion resolves a version specification to a concrete version using the specified backend.
Parameters: - ctx: Context for cancellation and timeouts - backendName: Name of the backend to use for resolution (e.g., "github", "aqua", "http") - tool: Name of the tool to resolve the version for - versionSpec: Version specification (exact version, range, or alias) - platform: Target platform for the resolution
Returns: - The resolved VersionInfo with concrete version and download information - An error if resolution fails
Resolution behavior: - Exact versions (e.g., "1.20.0"): Delegates to backend.GetDownloadInfo - Aliases (e.g., "latest", "lts", "stable"): Delegates to backend.ResolveVersion - Ranges (e.g., ">=1.20.0", "^3.11", "~2.7.0"): Delegates to backend.ResolveVersion
func (*VersionManager) SupportsChecksum ¶
func (vm *VersionManager) SupportsChecksum(backendName string) (bool, error)
SupportsChecksum checks if the specified backend supports checksum verification.
func (*VersionManager) SupportsGPG ¶
func (vm *VersionManager) SupportsGPG(backendName string) (bool, error)
SupportsGPG checks if the specified backend supports GPG signature verification.
func (*VersionManager) ValidateVersionConstraint ¶
func (vm *VersionManager) ValidateVersionConstraint(versionStr string) error
ValidateVersionConstraint validates a version constraint string without resolving it. This is useful for configuration validation.
Returns an error if the version constraint is invalid.