Skip to content

Commit

Permalink
refactor(pkg/godot/artifact)!: simplify artifact.Artifact and `arti…
Browse files Browse the repository at this point in the history
…fact/checksum.Checksums` implementations (#129)

* refactor: reorganize Artifact interface; require manual implementation of Artifact() to register artifacts

* refactor: simplify checksums artifact implementation
  • Loading branch information
coffeebeats authored Nov 5, 2023
1 parent 83fb6f1 commit c03c08c
Show file tree
Hide file tree
Showing 34 changed files with 339 additions and 300 deletions.
2 changes: 1 addition & 1 deletion cmd/gdenv/ls.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func printSources(ctx context.Context, storePath string) error {
log.Printf("Installed source code versions (%s):", storePath)

for _, src := range sources {
log.Printf(" %s", src.Artifact.Artifact.Version())
log.Printf(" %s", src.Artifact.Inner.Version())
}

return nil
Expand Down
6 changes: 3 additions & 3 deletions cmd/gdenv/vendor.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ func NewVendor() *cli.Command {

// Extracts the cached source code folder into the specified 'out' path.
func vendor(ctx context.Context, v version.Version, storePath, out string) error {
src := source.Archive{Artifact: source.New(v)}
src := source.Archive{Inner: source.New(v)}

srcPath, err := store.Source(storePath, src.Artifact)
srcPath, err := store.Source(storePath, src.Inner)
if err != nil {
return err
}
Expand All @@ -85,7 +85,7 @@ func vendor(ctx context.Context, v version.Version, storePath, out string) error
return err
}

out = filepath.Join(wd, src.Artifact.Name())
out = filepath.Join(wd, src.Inner.Name())
}

out = filepath.Clean(out)
Expand Down
8 changes: 4 additions & 4 deletions pkg/download/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"github.com/coffeebeats/gdenv/pkg/progress"
)

type progressKey[T artifact.Versioned] struct{}
type progressKey[T artifact.Artifact] struct{}

/* -------------------------------------------------------------------------- */
/* Function: WithProgress */
Expand All @@ -23,7 +23,7 @@ type progressKey[T artifact.Versioned] struct{}
// WithProgress creates a sub-context with an associated progress reporter. The
// result can be passed to download functions in this package to get updates on
// the download progress for that specific artifact.
func WithProgress[T artifact.Versioned](
func WithProgress[T artifact.Artifact](
ctx context.Context,
p *progress.Progress,
) context.Context {
Expand All @@ -36,7 +36,7 @@ func WithProgress[T artifact.Versioned](

// Download uses the provided mirror to download the specified artifact and
// returns an 'artifact.Local' wrapper pointing to it.
func Download[T artifact.Versioned](
func Download[T artifact.Artifact](
ctx context.Context,
a T,
out string,
Expand Down Expand Up @@ -85,7 +85,7 @@ func Download[T artifact.Versioned](
/* -------------------------------------------------------------------------- */

// availableMirrors returns the list of possible 'Mirror' hosts.
func availableMirrors[T artifact.Versioned]() []mirror.Mirror[T] {
func availableMirrors[T artifact.Artifact]() []mirror.Mirror[T] {
return []mirror.Mirror[T]{mirror.GitHub[T]{}, mirror.TuxFamily[T]{}}
}

Expand Down
8 changes: 5 additions & 3 deletions pkg/download/executable.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,16 @@ func ExecutableWithChecksumValidation(
ex executable.Executable,
out string,
) (artifact.Local[executable.Archive], error) {
chArchive, chChecksums := make(chan artifact.Local[executable.Archive]), make(chan artifact.Local[checksum.Executable])
chArchive := make(chan artifact.Local[executable.Archive])
defer close(chArchive)

chChecksums := make(chan artifact.Local[executable.Checksums])
defer close(chChecksums)

eg, ctxDownload := errgroup.WithContext(ctx)

eg.Go(func() error {
exArchive := executable.Archive{Artifact: ex}
exArchive := executable.Archive{Inner: ex}

result, err := Download(ctxDownload, exArchive, out)
if err != nil {
Expand All @@ -44,7 +46,7 @@ func ExecutableWithChecksumValidation(
})

eg.Go(func() error {
checksums, err := checksum.NewExecutable(ex.Version())
checksums, err := executable.NewChecksums(ex.Version())
if err != nil {
return err
}
Expand Down
18 changes: 10 additions & 8 deletions pkg/download/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,24 @@ func SourceWithChecksumValidation(
v version.Version,
out string,
) (artifact.Local[source.Archive], error) {
chSource, chChecksums := make(chan artifact.Local[source.Archive]), make(chan artifact.Local[checksum.Source])
defer close(chSource)
chArchive := make(chan artifact.Local[source.Archive])
defer close(chArchive)

chChecksums := make(chan artifact.Local[source.Checksums])
defer close(chChecksums)

eg, ctxDownload := errgroup.WithContext(ctx)

eg.Go(func() error {
srcArchive := source.Archive{Artifact: source.New(v)}
srcArchive := source.Archive{Inner: source.New(v)}

result, err := Download(ctxDownload, srcArchive, out)
if err != nil {
return err
}

select {
case chSource <- result:
case chArchive <- result:
case <-ctx.Done():
return ctx.Err()
}
Expand All @@ -45,7 +47,7 @@ func SourceWithChecksumValidation(
})

eg.Go(func() error {
checksums, err := checksum.NewSource(v)
checksums, err := source.NewChecksums(v)
if err != nil {
return err
}
Expand All @@ -64,15 +66,15 @@ func SourceWithChecksumValidation(
return nil
})

sourceArchive, checksums := <-chSource, <-chChecksums
srcArchive, checksums := <-chArchive, <-chChecksums

if err := eg.Wait(); err != nil {
return artifact.Local[source.Archive]{}, err
}

if err := checksum.Compare[source.Archive](ctx, sourceArchive, checksums); err != nil {
if err := checksum.Compare[source.Archive](ctx, srcArchive, checksums); err != nil {
return artifact.Local[source.Archive]{}, err
}

return sourceArchive, nil
return srcArchive, nil
}
4 changes: 2 additions & 2 deletions pkg/godot/artifact/archive/archive.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type Local = artifact.Local[Archive]

// An interface representing a compressed 'Artifact' archive.
type Archive interface {
artifact.Versioned
artifact.Artifact

extract(ctx context.Context, path, out string) error
}
Expand All @@ -50,7 +50,7 @@ type Archive interface {
// An interface representing an 'Artifact' that can be compressed into an
// archive.
type Archivable interface {
artifact.Versioned
artifact.Artifact

Archivable()
}
Expand Down
9 changes: 7 additions & 2 deletions pkg/godot/artifact/archive/archive_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,18 @@ type MockArchive[T Archivable] struct {

var _ Archive = (*MockArchive[artifacttest.MockArtifact])(nil)

/* ----------------------------- Impl: Artifact ----------------------------- */
/* ------------------------- Impl: artifact.Artifact ------------------------ */

// Artifact "registers" 'MockArchive' as a Godot release artifact.
func (a MockArchive[T]) Artifact() {}

/* -------------------------- Impl: artifact.Named -------------------------- */

func (a MockArchive[T]) Name() string {
return a.name
}

/* ----------------------------- Impl: Versioned ---------------------------- */
/* ------------------------ Impl: artifact.Versioned ------------------------ */

func (a MockArchive[T]) Version() version.Version {
return a.version
Expand Down
15 changes: 10 additions & 5 deletions pkg/godot/artifact/archive/tarxz.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,29 @@ const extensionTarXZ = ".tar.xz"

// A struct representing an 'XZ'-compressed archive.
type TarXZ[T Archivable] struct {
Artifact T
Inner T
}

/* ----------------------------- Impl: Artifact ----------------------------- */
/* ------------------------- Impl: artifact.Artifact ------------------------ */

// Artifact "registers" 'TarXZ' as a Godot release artifact.
func (a TarXZ[T]) Artifact() {}

/* -------------------------- Impl: artifact.Named -------------------------- */

func (a TarXZ[T]) Name() string {
name := a.Artifact.Name()
name := a.Inner.Name()
if name != "" {
name += extensionTarXZ
}

return name
}

/* ----------------------------- Impl: Versioned ---------------------------- */
/* ------------------------ Impl: artifact.Versioned ------------------------ */

func (a TarXZ[T]) Version() version.Version {
return a.Artifact.Version()
return a.Inner.Version()
}

/* ------------------------------ Impl: Archive ----------------------------- */
Expand Down
2 changes: 1 addition & 1 deletion pkg/godot/artifact/archive/tarxz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func TestTarXZVersion(t *testing.T) {
for i, tc := range tests {
t.Run(fmt.Sprintf("%d-%s", i, tc.artifact.Version()), func(t *testing.T) {
// Given: An archive wrapping the specified artifact.
a := TarXZ[Archivable]{Artifact: tc.artifact}
a := TarXZ[Archivable]{Inner: tc.artifact}

// When: The archive's version is determined.
got := a.Version()
Expand Down
15 changes: 10 additions & 5 deletions pkg/godot/artifact/archive/zip.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,29 @@ const extensionZip = ".zip"

// A struct representing a 'zip'-compressed archive.
type Zip[T Archivable] struct {
Artifact T
Inner T
}

/* ----------------------------- Impl: Artifact ----------------------------- */
/* ------------------------- Impl: artifact.Artifact ------------------------ */

// Artifact "registers" 'Zip' as a Godot release artifact.
func (a Zip[T]) Artifact() {}

/* -------------------------- Impl: artifact.Named -------------------------- */

func (a Zip[T]) Name() string {
name := a.Artifact.Name()
name := a.Inner.Name()
if name != "" {
name += extensionZip
}

return name
}

/* ----------------------------- Impl: Versioned ---------------------------- */
/* ------------------------ Impl: artifact.Versioned ------------------------ */

func (a Zip[T]) Version() version.Version {
return a.Artifact.Version()
return a.Inner.Version()
}

/* ------------------------------ Impl: Archive ----------------------------- */
Expand Down
2 changes: 1 addition & 1 deletion pkg/godot/artifact/archive/zip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func TestZipVersion(t *testing.T) {
for i, tc := range tests {
t.Run(fmt.Sprintf("%d-%s", i, tc.artifact.Version()), func(t *testing.T) {
// Given: An archive wrapping the specified artifact.
a := Zip[Archivable]{Artifact: tc.artifact}
a := Zip[Archivable]{Inner: tc.artifact}

// When: The archive's version is determined.
got := a.Version()
Expand Down
14 changes: 10 additions & 4 deletions pkg/godot/artifact/artifact.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ var ErrMissingPath = errors.New("missing path")
// An interface for different Godot-related files andfolder structures which
// 'gdenv' needs to interact with.
type Artifact interface {
Named
Versioned

Artifact()
}

/* ---------------------------- Interface: Named ---------------------------- */

// An interface for any artifacts which have a specific name.
type Named interface {
Name() string
}

Expand All @@ -26,17 +36,13 @@ type Artifact interface {
// An interface for any artifacts which are tied to a specific operating system
// and CPU architecture.
type Platformed interface {
Artifact

Platform() platform.Platform
}

/* -------------------------- Interface: Versioned -------------------------- */

// An interface for any artifacts which are tied to a specific version of Godot.
type Versioned interface {
Artifact

Version() version.Version
}

Expand Down
11 changes: 8 additions & 3 deletions pkg/godot/artifact/artifacttest/artifact.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,23 @@ func NewWithVersion(v version.Version) MockArtifact {
return MockArtifact{name: "", version: v}
}

/* ----------------------------- Impl: Artifact ----------------------------- */
/* ------------------------- Impl: artifact.Artifact ------------------------ */

// Artifact "registers" 'MockArtifact' as a Godot release artifact.
func (a MockArtifact) Artifact() {}

/* -------------------------- Impl: artifact.Named -------------------------- */

func (a MockArtifact) Name() string {
return a.name
}

/* ----------------------------- Impl: Versioned ---------------------------- */
/* ------------------------ Impl: artifact.Versioned ------------------------ */

func (a MockArtifact) Version() version.Version {
return a.version
}

/* ---------------------------- Impl: Archivable ---------------------------- */
/* ------------------------ Impl: archive.Archivable ------------------------ */

func (a MockArtifact) Archivable() {}
Loading

0 comments on commit c03c08c

Please sign in to comment.