-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add registry and global storage
Signed-off-by: Kasper J. Hermansen <[email protected]>
- Loading branch information
Showing
7 changed files
with
245 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package extensions | ||
|
||
// Extension is the descriptor of a single extension, it is used to add description to the cli, as well as calling the specific extension in question | ||
type Extension struct{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,50 @@ | ||
package extensions | ||
|
||
import "context" | ||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/lunarway/shuttle/internal/global" | ||
) | ||
|
||
// ExtensionsManager is the entry into installing, updating and using extensions. It is the orchestrator of all the parts that consist of extensions | ||
type ExtensionsManager struct { | ||
registry string | ||
globalStore *global.GlobalStore | ||
} | ||
|
||
func NewExtensionsManager(registry string) *ExtensionsManager { | ||
func NewExtensionsManager(globalStore *global.GlobalStore) *ExtensionsManager { | ||
return &ExtensionsManager{ | ||
registry: registry, | ||
globalStore: globalStore, | ||
} | ||
} | ||
|
||
// Init will initialize a repository with a sample extension package | ||
func (e *ExtensionsManager) Init(ctx context.Context) error { | ||
return nil | ||
} | ||
|
||
// GetAll will return all known and installed extensions | ||
func (e *ExtensionsManager) GetAll(ctx context.Context) ([]Extension, error) { | ||
return nil, nil | ||
} | ||
|
||
// Install will ensure that all known extensions are installed and ready for use | ||
func (e *ExtensionsManager) Install(ctx context.Context) error { | ||
return nil | ||
} | ||
|
||
func (e *ExtensionsManager) Update(ctx context.Context) error { | ||
// Update will fetch the latest extensions from a registry and install them afterwards so that they're ready for use | ||
func (e *ExtensionsManager) Update(ctx context.Context, registry string) error { | ||
reg, err := NewRegistry(registry, e.globalStore) | ||
if err != nil { | ||
return fmt.Errorf("failed to update extensions: %w", err) | ||
} | ||
|
||
if err := reg.Update(ctx); err != nil { | ||
return err | ||
} | ||
|
||
// 3. Initiate install | ||
|
||
return nil | ||
} | ||
|
||
type Extension struct{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package extensions | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/lunarway/shuttle/internal/global" | ||
) | ||
|
||
// gitRegistry represents a type of registry backed by a remote git registry, whether folder or url based. it is denoted by the variable git=github.com/lunarway/shuttle-extensions.git as an example | ||
type gitRegistry struct { | ||
url string | ||
globalStore *global.GlobalStore | ||
} | ||
|
||
func (*gitRegistry) Get(ctx context.Context) error { | ||
panic("unimplemented") | ||
} | ||
|
||
func (g *gitRegistry) Update(ctx context.Context) error { | ||
registry := getRegistryPath(g.globalStore) | ||
|
||
if exists(registry) { | ||
if err := g.fetchGitRepository(ctx); err != nil { | ||
return fmt.Errorf("failed to update registry: %w", err) | ||
} | ||
} else { | ||
if err := ensureExists(registry); err != nil { | ||
return fmt.Errorf("failed to create registry path: %w", err) | ||
} | ||
|
||
if err := g.cloneGitRepository(ctx); err != nil { | ||
return fmt.Errorf("failed to clone registry: %w", err) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func newGitRegistry(url string, globalStore *global.GlobalStore) Registry { | ||
return &gitRegistry{ | ||
url: url, | ||
globalStore: globalStore, | ||
} | ||
} | ||
|
||
func (g *gitRegistry) fetchGitRepository(ctx context.Context) error { | ||
panic("unimplemented") | ||
} | ||
|
||
func (g *gitRegistry) cloneGitRepository(ctx context.Context) error { | ||
panic("unimplemented") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package extensions | ||
|
||
import ( | ||
"errors" | ||
"os" | ||
"path" | ||
|
||
"github.com/lunarway/shuttle/internal/global" | ||
) | ||
|
||
func getRegistryPath(globalStore *global.GlobalStore) string { | ||
return path.Join(globalStore.Root(), "registry") | ||
} | ||
|
||
func getExtensionsPath(globalStore *global.GlobalStore) string { | ||
return path.Join(globalStore.Root(), "extensions") | ||
} | ||
|
||
func getExtensionsCachePath(globalStore *global.GlobalStore) string { | ||
return path.Join(getExtensionsPath(globalStore), "cache") | ||
} | ||
|
||
func ensureExists(dirPath string) error { | ||
return os.MkdirAll(dirPath, 0o666) | ||
} | ||
|
||
func exists(dirPath string) bool { | ||
_, err := os.Stat(dirPath) | ||
|
||
if errors.Is(err, os.ErrNotExist) { | ||
return false | ||
} | ||
|
||
if err != nil { | ||
return false | ||
} | ||
|
||
return true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package extensions | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/lunarway/shuttle/internal/global" | ||
) | ||
|
||
// Registry represents some kind of upstream registry where extension metadata lives, such as which ones should be downloaded, which versions they're on and how to download them | ||
type Registry interface { | ||
Get(ctx context.Context) error | ||
Update(ctx context.Context) error | ||
} | ||
|
||
// NewRegistry is a shim for concrete implementations of the registries, such as gitRegistry | ||
func NewRegistry(registry string, globalStore *global.GlobalStore) (Registry, error) { | ||
registryType, registryUrl, ok := strings.Cut(registry, "=") | ||
if !ok { | ||
return nil, fmt.Errorf("registry was not a valid url: %s", registry) | ||
} | ||
|
||
switch registryType { | ||
case "git": | ||
return newGitRegistry(registryUrl, globalStore), nil | ||
default: | ||
return nil, fmt.Errorf("registry type was not valid: %s", registryType) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package global | ||
|
||
import "os" | ||
|
||
// GlobalStore represents the ~/.shuttle folder it acts as an abstraction for said folder and ensures operations against it are consistent and controlled | ||
type GlobalStore struct { | ||
options *GlobalStoreOptions | ||
} | ||
|
||
type GlobalStoreOption func(options *GlobalStoreOptions) | ||
|
||
func WithShuttleConfig(shuttleConfig string) GlobalStoreOption { | ||
return func(options *GlobalStoreOptions) { | ||
options.ShuttleConfig = shuttleConfig | ||
} | ||
} | ||
|
||
type GlobalStoreOptions struct { | ||
ShuttleConfig string | ||
} | ||
|
||
func newDefaultGlobalStoreOptions() *GlobalStoreOptions { | ||
return &GlobalStoreOptions{ | ||
ShuttleConfig: "$HOME/.shuttle", | ||
} | ||
} | ||
|
||
func NewGlobalStore(options ...GlobalStoreOption) *GlobalStore { | ||
defaultOptions := newDefaultGlobalStoreOptions() | ||
for _, opt := range options { | ||
opt(defaultOptions) | ||
} | ||
|
||
return &GlobalStore{ | ||
options: defaultOptions, | ||
} | ||
} | ||
|
||
func (gs *GlobalStore) Root() string { | ||
return os.ExpandEnv(gs.options.ShuttleConfig) | ||
} |