repository

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 23, 2025 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Copyright (c) 2025 Guilherme Silva Sousa Licensed under the MIT License See LICENSE file in the project root for full license information. Package repository provides interfaces and implementations for managing command repositories.

The repository package defines a flexible system for discovering, loading, and managing commands from various sources including local directories, Git repositories, and remote catalogs. It provides a unified interface that allows ccmd to work with multiple repository types seamlessly.

Core Concepts

Repository: A source of commands, which can be local, remote, or version-controlled. Each repository type implements the Repository interface to provide consistent access to commands regardless of the underlying storage mechanism.

Manager: Handles the lifecycle of repository instances and maintains a registry of available repository types. New repository types can be registered at runtime.

Workspace: Provides a unified view across multiple repositories, handling command resolution, version management, and repository prioritization.

Repository Types

The package supports several repository types out of the box:

  • Local: Commands stored in local directories
  • Git: Commands in Git repositories (with branch/tag support)
  • HTTP: Commands served from HTTP endpoints
  • S3: Commands stored in S3-compatible object storage

Usage Example

// Create a repository manager
manager := repository.NewManager()

// Register repository types
manager.Register("local", repository.NewLocalFactory())
manager.Register("git", repository.NewGitFactory())

// Create a repository instance
repo, err := manager.Create("local", map[string]interface{}{
    "path": "/path/to/commands",
})
if err != nil {
    log.Fatal(err)
}

// Initialize and discover commands
ctx := context.Background()
if err := repo.Initialize(ctx); err != nil {
    log.Fatal(err)
}

commands, err := repo.Discover(ctx)
if err != nil {
    log.Fatal(err)
}

Extending with Custom Repository Types

Custom repository types can be added by implementing the Repository interface and registering a factory function:

type MyCustomRepo struct {
    // implementation
}

func (r *MyCustomRepo) Initialize(ctx context.Context) error {
    // implementation
}

// ... implement other Repository methods

// Register the custom type
manager.Register("custom", func(config map[string]interface{}) (Repository, error) {
    return &MyCustomRepo{
        // initialize from config
    }, nil
})

Error Handling

The package defines specific error types for common failure scenarios:

  • ErrRepositoryNotFound: Repository doesn't exist or is inaccessible
  • ErrCommandNotFound: Command doesn't exist in the repository
  • ErrInvalidConfiguration: Repository configuration is invalid
  • ErrAuthenticationFailed: Repository requires authentication

Performance Considerations

For remote repositories, implementations should consider:

  • Caching discovered commands to reduce network calls
  • Lazy loading of command details and resources
  • Parallel discovery for improved performance
  • Progress reporting for long-running operations

Security Considerations

Repository implementations must:

  • Validate all file paths to prevent directory traversal
  • Sanitize command metadata to prevent injection attacks
  • Handle credentials securely (never log or expose them)
  • Verify checksums/signatures for downloaded content

Copyright (c) 2025 Guilherme Silva Sousa Licensed under the MIT License See LICENSE file in the project root for full license information.

Copyright (c) 2025 Guilherme Silva Sousa Licensed under the MIT License See LICENSE file in the project root for full license information.

Copyright (c) 2025 Guilherme Silva Sousa Licensed under the MIT License See LICENSE file in the project root for full license information.

Copyright (c) 2025 Guilherme Silva Sousa Licensed under the MIT License See LICENSE file in the project root for full license information.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrRepositoryNotFound indicates the repository doesn't exist or is inaccessible
	ErrRepositoryNotFound = fmt.Errorf("repository not found")

	// ErrCommandNotFound indicates the command doesn't exist in the repository
	ErrCommandNotFound = fmt.Errorf("command not found")

	// ErrInvalidConfiguration indicates the repository configuration is invalid
	ErrInvalidConfiguration = fmt.Errorf("invalid repository configuration")

	// ErrAuthenticationFailed indicates authentication to the repository failed
	ErrAuthenticationFailed = fmt.Errorf("authentication failed")

	// ErrResourceNotFound indicates the requested resource doesn't exist
	ErrResourceNotFound = fmt.Errorf("resource not found")

	// ErrUnsupportedOperation indicates the operation is not supported by this repository type
	ErrUnsupportedOperation = fmt.Errorf("unsupported operation")

	// ErrCacheExpired indicates the cache is outdated and needs refresh
	ErrCacheExpired = fmt.Errorf("cache expired")

	// ErrNetworkError indicates a network-related error occurred
	ErrNetworkError = fmt.Errorf("network error")

	// ErrVersionConflict indicates multiple versions exist and resolution is ambiguous
	ErrVersionConflict = fmt.Errorf("version conflict")

	// ErrPermissionDenied indicates insufficient permissions to access the repository
	ErrPermissionDenied = fmt.Errorf("permission denied")
)

Common error types for repository operations

View Source
var DefaultManager = NewManager()

DefaultManager is the global repository manager instance

Functions

func List

func List() []string

List returns all registered types from the default manager

func NewCommandError

func NewCommandError(commandID, op string, err error) error

NewCommandError creates a new CommandError

func NewRepositoryError

func NewRepositoryError(op, repo string, err error, details string) error

NewRepositoryError creates a new repository Error

func Register

func Register(repoType string, factory Factory)

Register adds a repository type to the default manager

Types

type CacheableRepository

type CacheableRepository interface {
	Repository

	// RefreshCache updates the local cache with latest repository data.
	//
	// Parameters:
	//   - ctx: Context for cancellation and deadline control
	//
	// Returns:
	//   - error: Any error during cache refresh
	RefreshCache(ctx context.Context) error

	// ClearCache removes all cached data for this repository.
	//
	// Returns:
	//   - error: Any error during cache clearing
	ClearCache() error

	// GetCacheInfo returns information about the current cache state.
	//
	// Returns:
	//   - model.CacheInfo: Cache statistics and metadata
	//
	// TODO: Define CacheInfo model structure
	GetCacheInfo() model.CacheInfo
}

CacheableRepository extends Repository with caching capabilities. Implementations can use this to improve performance for remote repositories.

type CommandError

type CommandError struct {
	CommandID string // Command identifier
	Op        string // Operation that failed
	Err       error  // Underlying error
}

CommandError provides detailed error information for command operations

func (*CommandError) Error

func (e *CommandError) Error() string

func (*CommandError) Unwrap

func (e *CommandError) Unwrap() error

type Error

type Error struct {
	Op         string // Operation that failed
	Repository string // Repository identifier
	Err        error  // Underlying error
	Details    string // Additional details
}

Error provides detailed error information for repository operations

func (*Error) Error

func (e *Error) Error() string

func (*Error) Unwrap

func (e *Error) Unwrap() error

type Factory

type Factory func(config map[string]interface{}) (Repository, error)

Factory is a function that creates a new Repository instance. It receives configuration specific to the repository type.

Parameters:

  • config: Type-specific configuration map

Returns:

  • Repository: New repository instance
  • error: Any error during creation

Example configurations:

type Manager

type Manager interface {
	// Register adds a new repository type with its factory function.
	//
	// Parameters:
	//   - repoType: Unique identifier for the repository type
	//   - factory: Function to create instances of this type
	Register(repoType string, factory Factory)

	// Create instantiates a new repository of the specified type.
	//
	// Parameters:
	//   - repoType: Type of repository to create
	//   - config: Configuration for the repository
	//
	// Returns:
	//   - Repository: New repository instance
	//   - error: Any error during creation
	Create(repoType string, config map[string]interface{}) (Repository, error)

	// List returns all registered repository types.
	//
	// Returns:
	//   - []string: List of registered type identifiers
	List() []string
}

Manager handles multiple repository instances and provides unified access. It maintains a registry of repository types and can create instances dynamically.

func NewManager

func NewManager() Manager

NewManager creates a new repository manager instance

type Repository

type Repository interface {
	// Initialize sets up the repository connection and prepares for operations.
	// It should validate connectivity, check authentication, and prepare any
	// necessary local storage or caches.
	//
	// Parameters:
	//   - ctx: Context for cancellation and deadline control
	//
	// Returns:
	//   - error: Any error encountered during initialization
	Initialize(ctx context.Context) error

	// Discover searches for available commands in the repository.
	// It should recursively scan for ccmd.yaml files and build a catalog
	// of available commands with their metadata.
	//
	// Parameters:
	//   - ctx: Context for cancellation and deadline control
	//
	// Returns:
	//   - []model.CommandInfo: List of discovered commands with metadata
	//   - error: Any error encountered during discovery
	//
	// Note: Implementations should handle large repositories efficiently,
	// potentially using pagination or streaming for better performance.
	Discover(ctx context.Context) ([]model.CommandInfo, error)

	// Load retrieves a specific command by its identifier.
	// The identifier format depends on the repository type:
	//   - Local: file path relative to repository root
	//   - Git: combination of repository URL and path
	//   - Remote: URL or catalog-specific identifier
	//
	// Parameters:
	//   - ctx: Context for cancellation and deadline control
	//   - id: Unique identifier for the command
	//
	// Returns:
	//   - *model.Command: The loaded command with full configuration
	//   - error: Any error encountered during loading
	Load(ctx context.Context, id string) (*model.Command, error)

	// GetResource retrieves a resource file associated with a command.
	// Resources can include templates, configuration files, or documentation.
	//
	// Parameters:
	//   - ctx: Context for cancellation and deadline control
	//   - commandID: Identifier of the command owning the resource
	//   - resourcePath: Path to the resource relative to the command
	//
	// Returns:
	//   - io.ReadCloser: Reader for the resource content (caller must close)
	//   - error: Any error encountered accessing the resource
	//
	// Note: Implementations should validate resource paths to prevent
	// directory traversal attacks.
	GetResource(ctx context.Context, commandID, resourcePath string) (io.ReadCloser, error)

	// Type returns the repository type identifier.
	// Common types include "local", "git", "http", "s3", etc.
	//
	// Returns:
	//   - string: Repository type identifier
	Type() string

	// Info returns metadata about the repository.
	// This includes connection details, capabilities, and current status.
	//
	// Returns:
	//   - model.RepositoryInfo: Repository metadata and status
	//
	// TODO: Define RepositoryInfo model structure including:
	//   - Connection status and health
	//   - Supported features and limitations
	//   - Cache status and statistics
	//   - Authentication status
	Info() model.RepositoryInfo
}

Repository defines the interface for managing command repositories. It provides operations for discovering, loading, and accessing commands from various sources like local directories, Git repositories, and remote catalogs.

Implementation consideration: In Docker-in-Docker environments, git operations may fail with authentication issues. Implementations should handle these gracefully and provide fallback options (e.g., using cached data or local repositories).

func Create

func Create(repoType string, config map[string]interface{}) (Repository, error)

Create creates a repository using the default manager

type Workspace

type Workspace interface {
	// AddRepository adds a new repository to the workspace.
	//
	// Parameters:
	//   - repo: Repository instance to add
	//   - name: Unique name for this repository in the workspace
	//
	// Returns:
	//   - error: Any error during addition
	AddRepository(repo Repository, name string) error

	// RemoveRepository removes a repository from the workspace.
	//
	// Parameters:
	//   - name: Name of the repository to remove
	//
	// Returns:
	//   - error: Any error during removal
	RemoveRepository(name string) error

	// ListCommands returns all available commands across all repositories.
	//
	// Parameters:
	//   - ctx: Context for cancellation and deadline control
	//
	// Returns:
	//   - []model.CommandInfo: Aggregated list of all commands
	//   - error: Any error during listing
	ListCommands(ctx context.Context) ([]model.CommandInfo, error)

	// ResolveCommand finds and loads a command by name across all repositories.
	// It should handle version resolution and repository priority.
	//
	// Parameters:
	//   - ctx: Context for cancellation and deadline control
	//   - name: Command name to resolve
	//   - version: Specific version or version constraint (optional)
	//
	// Returns:
	//   - *model.Command: Resolved and loaded command
	//   - error: Any error during resolution
	ResolveCommand(ctx context.Context, name, version string) (*model.Command, error)
}

Workspace provides a unified interface for accessing multiple repositories. It manages repository lifecycle and provides command resolution across sources.

func NewWorkspace

func NewWorkspace() Workspace

NewWorkspace creates a new workspace instance

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL