Skip to content

Commit

Permalink
Major refactor of all internals (#30)
Browse files Browse the repository at this point in the history
* Moved viper loaded config to config package
* Created internal interfaces to:
  * GitManager
  * ExecManager
  * RepositoryManager
  * RepositoriesManager
  * CopyManager
* Implemented gomock
* Moved packages to repo patern
* Removed go integration tests, and instead use afero for filesystem
  testing
* Switched output to slog
* Removed/moved unnecessary packages
* Added current configuration debug log
* Corrected exec to return Stderr

All tests currently passing.
  • Loading branch information
retr0h committed Nov 23, 2023
1 parent a6bff51 commit 18c26ee
Show file tree
Hide file tree
Showing 35 changed files with 1,796 additions and 1,148 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License

Copyright (c) 2018 John Dewey
Copyright (c) 2018-2023 John Dewey

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ often shared, but Ansible's [Galaxy][] has no mechanism to handle this.

## Port

This project is a port of [Gilt][], it is
not 100% compatible with the python version, and aims to correct some poor decisions
made in the python version of Gilt.
This project is a port of [Gilt][], it is not 100% compatible with the python
version, and aims to correct poor decisions made in the python version of
Gilt.

This version of Gilt does not provide built in locking, unlike our python friend.
This version of Gilt does not provide built in locking, branches, tags, and
post commands unlike our python friend. However, these features will be added
in the future.

## Installation

Expand Down
14 changes: 11 additions & 3 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ tasks:
unit:int:
desc: Integration test packages
cmds:
- go test -tags=integration -parallel 5 -race -v ./...
- task: unit:bats

unit:bats:
Expand All @@ -85,10 +84,11 @@ tasks:
cov:
desc: Generate coverage
cmds:
- go test -race -coverprofile cover.out -v 2>&1 ./... | go-junit-report --set-exit-code > result.xml || (cat result.xml && echo "fail" && exit 1)
- go test -race -coverprofile=cover.out -v $(go list ./... | egrep -v '(/test|/test/mock)$') 2>&1 | go-junit-report --set-exit-code > result.xml || (cat result.xml && echo "fail" && exit 1)
- $(go env GOPATH)/bin/gocover-cobertura < cover.out > cobertura.xml
- go tool cover -func=cover.out

covmap:
cov:map:
desc: Generate coverage and show heatmap
cmds:
- task: cov
Expand All @@ -111,3 +111,11 @@ tasks:
desc: Build ARCH compatible binary.
cmds:
- goreleaser release --snapshot --clean

mockgen:
desc: Generate mock for interface
cmds:
- mockgen -source=internal/git.go -destination=internal/git/git_mock.go -package=git
- mockgen -source=internal/repository.go -destination=internal/repository/repository_mock.go -package=repository
- mockgen -source=internal/git/types.go -destination=internal/git/exec_mock.go -package=git
- mockgen -source=internal/repository/types.go -destination=internal/repository/copy_mock.go -package=repository
67 changes: 28 additions & 39 deletions cmd/overlay.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,42 +22,34 @@ package cmd

import (
"log/slog"
"os"
"os/user"
"path/filepath"
"strconv"

"github.com/spf13/cobra"
)

func expandUser(path string) (string, error) {
if len(path) == 0 || path[0] != '~' {
return path, nil
}

usr, err := user.Current()
if err != nil {
return "", err
}

return filepath.Join(usr.HomeDir, path[1:]), nil
}

// getGiltDir create the GiltDir if it doesn't exist.
func getGiltDir() (string, error) {
expandedGiltDir, err := expandUser(r.GiltDir)
if err != nil {
return "", err
}
func logRepositoriesGroup() []any {
logGroups := make([]any, 0, len(appConfig.Repositories))

cacheGiltDir := filepath.Join(expandedGiltDir, "cache")

if _, err := os.Stat(cacheGiltDir); os.IsNotExist(err) {
if err := os.Mkdir(cacheGiltDir, 0o755); err != nil {
return "", err
for i, repo := range appConfig.Repositories {
var sourceGroups []any
for i, s := range repo.Sources {
group := slog.Group(strconv.Itoa(i),
slog.String("Src", s.Src),
slog.String("DstFile", s.DstFile),
slog.String("DstDir", s.DstDir),
)
sourceGroups = append(sourceGroups, group)
}
group := slog.Group(strconv.Itoa(i),
slog.String("Git", repo.Git),
slog.String("Version", repo.Version),
slog.String("DstDir", repo.DstDir),
slog.Group("Sources", sourceGroups...),
)
logGroups = append(logGroups, group)
}

return cacheGiltDir, nil
return logGroups
}

// overlayCmd represents the overlay command
Expand All @@ -72,18 +64,15 @@ var overlayCmd = &cobra.Command{
// We are logging errors, no need for cobra to re-log the error
cmd.SilenceErrors = true

cacheDir, err := getGiltDir()
if err != nil {
logger.Error(
"error expanding dir",
slog.String("giltDir", r.GiltDir),
slog.String("err", err.Error()),
)
return err
}
logger.Debug(
"current configuration",
slog.String("GiltDir", appConfig.GiltDir),
slog.String("GiltFile", appConfig.GiltFile),
slog.Bool("Debug", appConfig.Debug),
slog.Group("Repository", logRepositoriesGroup()...),
)

r.GiltDir = cacheDir
if err := r.Overlay(); err != nil {
if err := repos.Overlay(); err != nil {
logger.Error(
"error overlaying repositories",
slog.String("err", err.Error()),
Expand Down
61 changes: 47 additions & 14 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,33 +27,35 @@ import (
"time"

"github.com/lmittmann/tint"
"github.com/spf13/afero"
"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/retr0h/go-gilt/internal"
"github.com/retr0h/go-gilt/internal/config"
"github.com/retr0h/go-gilt/internal/git"
"github.com/retr0h/go-gilt/internal/repositories"
"github.com/retr0h/go-gilt/internal/repository"
)

var (
r repositories.Repositories
logger *slog.Logger
repos internal.RepositoriesManager
logger *slog.Logger
appConfig config.Repositories
)

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "go-gilt",
Short: "A GIT layering command line tool",
Long: `
,o888888o. 8 8888 8 8888 8888888 8888888888
8888 '88. 8 8888 8 8888 8 8888
,8 8888 '8. 8 8888 8 8888 8 8888
88 8888 8 8888 8 8888 8 8888
88 8888 8 8888 8 8888 8 8888
88 8888 8 8888 8 8888 8 8888
88 8888 8888888 8 8888 8 8888 8 8888
'8 8888 .8' 8 8888 8 8888 8 8888
8888 ,88' 8 8888 8 8888 8 8888
'8888888P' 8 8888 8 888888888888 8 8888
o o
o | |
o--o | -o-
| | | | |
o--O | o o
|
o--o
A GIT layering command line tool.
Expand Down Expand Up @@ -117,12 +119,43 @@ func initConfig() {
os.Exit(1)
}

if err := viper.Unmarshal(&r); err != nil {
if err := viper.Unmarshal(&appConfig); err != nil {
logger.Error(
"failed to unmarshal config",
slog.String("Giltfile", viper.ConfigFileUsed()),
slog.String("err", err.Error()),
)
os.Exit(1)
}

appFs := afero.NewOsFs()

repoManager := repository.NewCopy(
appFs,
logger,
)

execManager := git.NewExecManagerCmd(
appConfig.Debug,
logger,
)

g := git.New(
appFs,
appConfig.Debug,
execManager,
logger,
)

repos = repositories.New(
appFs,
appConfig,
repository.New(
appFs,
repoManager,
g,
logger,
),
logger,
)
}
5 changes: 2 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ module github.com/retr0h/go-gilt
go 1.21.0

require (
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d
github.com/golang/mock v1.4.4
github.com/lmittmann/tint v1.0.3
github.com/logrusorgru/aurora/v4 v4.0.0
github.com/spf13/afero v1.10.0
github.com/spf13/cobra v1.8.0
github.com/spf13/viper v1.17.0
github.com/stretchr/testify v1.8.4
go.hein.dev/go-version v0.1.0
sigs.k8s.io/yaml v1.4.0
)

require (
Expand All @@ -37,4 +35,5 @@ require (
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)
5 changes: 1 addition & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFU
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
Expand Down Expand Up @@ -162,8 +163,6 @@ github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d h1:cVtBfNW5XTHiKQe7jDaDBSh/EVM4XLPutLAGboIXuM0=
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
Expand All @@ -179,8 +178,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lmittmann/tint v1.0.3 h1:W5PHeA2D8bBJVvabNfQD/XW9HPLZK1XoPZH0cq8NouQ=
github.com/lmittmann/tint v1.0.3/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
github.com/logrusorgru/aurora/v4 v4.0.0 h1:sRjfPpun/63iADiSvGGjgA1cAYegEWMPCJdUpJYn9JA=
github.com/logrusorgru/aurora/v4 v4.0.0/go.mod h1:lP0iIa2nrnT/qoFXcOZSrZQpJ1o6n2CUf/hyHi2Q4ZQ=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
Expand Down
58 changes: 58 additions & 0 deletions internal/config/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) 2023 John Dewey

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

package config

// Repositories perform repository operations.
type Repositories struct {
// Debug enable or disable debug option set from CLI.
Debug bool `mapstruture:"debug"`
// GiltFile path to Gilt's config file option set from CLI.
GiltFile string `mapstructure:"giltFile"`
// GiltDir path to Gilt's clone dir option set from CLI.
GiltDir string `mapstructure:"giltDir"`
// Repositories a slice of repository configurations to overlay.
Repositories []Repository `mapstruture:"repositories"`
}

// Sources mapping of files and/or directories needing copied.
type Sources struct {
// Src source file or directory to copy.
Src string `mapstructure:"src"`
// DstFile destination of file copy.
DstFile string `mapstructure:"dstFile"`
// DstDir destination of directory copy.
DstDir string `mapstructure:"dstDir"`
}

// Repository contains the repository's details for cloning.
type Repository struct {
// Git url of Git repository to clone.
Git string `mapstructure:"git"`
// Version of Git repository to use.
Version string `mapstructure:"version"`
// DstDir destination directory to copy clone to.
DstDir string `mapstructure:"dstDir"`
// Sources containing files and/or directories to copy.
Sources []Sources `mapstructure:"sources"`

// Directory to clone into.
CloneDir string
}
28 changes: 28 additions & 0 deletions internal/git.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) 2023 John Dewey

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

package internal

// GitManager manager responsible for Git operations.
type GitManager interface {
Clone(gitURL string, cloneDir string) error
Reset(cloneDir string, gitVersion string) error
CheckoutIndex(dstDir string, cloneDir string) error
}
Loading

0 comments on commit 18c26ee

Please sign in to comment.