feat: translation support
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
See #483
This commit is contained in:
@ -3,6 +3,7 @@
|
|||||||
[](https://build.coopcloud.tech/toolshed/abra)
|
[](https://build.coopcloud.tech/toolshed/abra)
|
||||||
[](https://goreportcard.com/report/git.coopcloud.tech/toolshed/abra)
|
[](https://goreportcard.com/report/git.coopcloud.tech/toolshed/abra)
|
||||||
[](https://pkg.go.dev/coopcloud.tech/abra)
|
[](https://pkg.go.dev/coopcloud.tech/abra)
|
||||||
|
[](https://translate.coopcloud.tech/engage/co-op-cloud/)
|
||||||
|
|
||||||
The Co-op Cloud utility belt 🎩🐇
|
The Co-op Cloud utility belt 🎩🐇
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package autocomplete
|
package autocomplete
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"coopcloud.tech/abra/pkg/app"
|
"coopcloud.tech/abra/pkg/app"
|
||||||
appPkg "coopcloud.tech/abra/pkg/app"
|
appPkg "coopcloud.tech/abra/pkg/app"
|
||||||
"coopcloud.tech/abra/pkg/recipe"
|
"coopcloud.tech/abra/pkg/recipe"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ import (
|
|||||||
func AppNameComplete() ([]string, cobra.ShellCompDirective) {
|
func AppNameComplete() ([]string, cobra.ShellCompDirective) {
|
||||||
appFiles, err := app.LoadAppFiles("")
|
appFiles, err := app.LoadAppFiles("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Sprintf("autocomplete failed: %s", err)
|
err := gotext.Get("autocomplete failed: %s", err)
|
||||||
return []string{err}, cobra.ShellCompDirectiveError
|
return []string{err}, cobra.ShellCompDirectiveError
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ func AppNameComplete() ([]string, cobra.ShellCompDirective) {
|
|||||||
func ServiceNameComplete(appName string) ([]string, cobra.ShellCompDirective) {
|
func ServiceNameComplete(appName string) ([]string, cobra.ShellCompDirective) {
|
||||||
serviceNames, err := app.GetAppServiceNames(appName)
|
serviceNames, err := app.GetAppServiceNames(appName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Sprintf("autocomplete failed: %s", err)
|
err := gotext.Get("autocomplete failed: %s", err)
|
||||||
return []string{err}, cobra.ShellCompDirectiveError
|
return []string{err}, cobra.ShellCompDirectiveError
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ func ServiceNameComplete(appName string) ([]string, cobra.ShellCompDirective) {
|
|||||||
func RecipeNameComplete() ([]string, cobra.ShellCompDirective) {
|
func RecipeNameComplete() ([]string, cobra.ShellCompDirective) {
|
||||||
catl, err := recipe.ReadRecipeCatalogue(false)
|
catl, err := recipe.ReadRecipeCatalogue(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Sprintf("autocomplete failed: %s", err)
|
err := gotext.Get("autocomplete failed: %s", err)
|
||||||
return []string{err}, cobra.ShellCompDirectiveError
|
return []string{err}, cobra.ShellCompDirectiveError
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ func RecipeNameComplete() ([]string, cobra.ShellCompDirective) {
|
|||||||
func RecipeVersionComplete(recipeName string) ([]string, cobra.ShellCompDirective) {
|
func RecipeVersionComplete(recipeName string) ([]string, cobra.ShellCompDirective) {
|
||||||
catl, err := recipe.ReadRecipeCatalogue(true)
|
catl, err := recipe.ReadRecipeCatalogue(true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Sprintf("autocomplete failed: %s", err)
|
err := gotext.Get("autocomplete failed: %s", err)
|
||||||
return []string{err}, cobra.ShellCompDirectiveError
|
return []string{err}, cobra.ShellCompDirectiveError
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ func RecipeVersionComplete(recipeName string) ([]string, cobra.ShellCompDirectiv
|
|||||||
func ServerNameComplete() ([]string, cobra.ShellCompDirective) {
|
func ServerNameComplete() ([]string, cobra.ShellCompDirective) {
|
||||||
files, err := app.LoadAppFiles("")
|
files, err := app.LoadAppFiles("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Sprintf("autocomplete failed: %s", err)
|
err := gotext.Get("autocomplete failed: %s", err)
|
||||||
return []string{err}, cobra.ShellCompDirectiveError
|
return []string{err}, cobra.ShellCompDirectiveError
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,13 +90,13 @@ func ServerNameComplete() ([]string, cobra.ShellCompDirective) {
|
|||||||
func CommandNameComplete(appName string) ([]string, cobra.ShellCompDirective) {
|
func CommandNameComplete(appName string) ([]string, cobra.ShellCompDirective) {
|
||||||
app, err := app.Get(appName)
|
app, err := app.Get(appName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Sprintf("autocomplete failed: %s", err)
|
err := gotext.Get("autocomplete failed: %s", err)
|
||||||
return []string{err}, cobra.ShellCompDirectiveError
|
return []string{err}, cobra.ShellCompDirectiveError
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdNames, err := appPkg.ReadAbraShCmdNames(app.Recipe.AbraShPath)
|
cmdNames, err := appPkg.ReadAbraShCmdNames(app.Recipe.AbraShPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Sprintf("autocomplete failed: %s", err)
|
err := gotext.Get("autocomplete failed: %s", err)
|
||||||
return []string{err}, cobra.ShellCompDirectiveError
|
return []string{err}, cobra.ShellCompDirectiveError
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ func SecretComplete(recipeName string) ([]string, cobra.ShellCompDirective) {
|
|||||||
|
|
||||||
config, err := r.GetComposeConfig(nil)
|
config, err := r.GetComposeConfig(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Sprintf("autocomplete failed: %s", err)
|
err := gotext.Get("autocomplete failed: %s", err)
|
||||||
return []string{err}, cobra.ShellCompDirectiveError
|
return []string{err}, cobra.ShellCompDirectiveError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package catalogue
|
package catalogue
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@ -10,13 +11,14 @@ import (
|
|||||||
gitPkg "coopcloud.tech/abra/pkg/git"
|
gitPkg "coopcloud.tech/abra/pkg/git"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EnsureCatalogue ensures that the catalogue is cloned locally & present.
|
// EnsureCatalogue ensures that the catalogue is cloned locally & present.
|
||||||
func EnsureCatalogue() error {
|
func EnsureCatalogue() error {
|
||||||
catalogueDir := path.Join(config.ABRA_DIR, "catalogue")
|
catalogueDir := path.Join(config.ABRA_DIR, "catalogue")
|
||||||
if _, err := os.Stat(catalogueDir); err != nil && os.IsNotExist(err) {
|
if _, err := os.Stat(catalogueDir); err != nil && os.IsNotExist(err) {
|
||||||
log.Debugf("catalogue is missing, retrieving now")
|
log.Debug(gotext.Get("catalogue is missing, retrieving now"))
|
||||||
|
|
||||||
url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, config.CATALOGUE_JSON_REPO_NAME)
|
url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, config.CATALOGUE_JSON_REPO_NAME)
|
||||||
if err := gitPkg.Clone(catalogueDir, url); err != nil {
|
if err := gitPkg.Clone(catalogueDir, url); err != nil {
|
||||||
@ -35,8 +37,7 @@ func EnsureIsClean() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !isClean {
|
if !isClean {
|
||||||
msg := "%s has locally unstaged changes? please commit/remove your changes before proceeding"
|
return errors.New(gotext.Get("%s has locally unstaged changes? please commit/remove your changes before proceeding", config.CATALOGUE_DIR))
|
||||||
return fmt.Errorf(msg, config.CATALOGUE_DIR)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -55,8 +56,7 @@ func EnsureUpToDate() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(remotes) == 0 {
|
if len(remotes) == 0 {
|
||||||
msg := "cannot ensure %s is up-to-date, no git remotes configured"
|
log.Debugf(gotext.Get("cannot ensure %s is up-to-date, no git remotes configured", config.CATALOGUE_DIR))
|
||||||
log.Debugf(msg, config.CATALOGUE_DIR)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ func EnsureUpToDate() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("fetched latest git changes for %s", config.CATALOGUE_DIR)
|
log.Debugf(gotext.Get("fetched latest git changes for %s", config.CATALOGUE_DIR))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ package client
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
@ -14,6 +13,7 @@ import (
|
|||||||
sshPkg "coopcloud.tech/abra/pkg/ssh"
|
sshPkg "coopcloud.tech/abra/pkg/ssh"
|
||||||
commandconnPkg "coopcloud.tech/abra/pkg/upstream/commandconn"
|
commandconnPkg "coopcloud.tech/abra/pkg/upstream/commandconn"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Conf is a Docker client configuration.
|
// Conf is a Docker client configuration.
|
||||||
@ -41,7 +41,7 @@ func New(serverName string, opts ...Opt) (*client.Client, error) {
|
|||||||
if serverName != "default" {
|
if serverName != "default" {
|
||||||
context, err := GetContext(serverName)
|
context, err := GetContext(serverName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unknown server, run \"abra server add %s\"?", serverName)
|
return nil, errors.New(gotext.Get("unknown server, run \"abra server add %s\"?", serverName))
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxEndpoint, err := contextPkg.GetContextEndpoint(context)
|
ctxEndpoint, err := contextPkg.GetContextEndpoint(context)
|
||||||
@ -85,7 +85,7 @@ func New(serverName string, opts ...Opt) (*client.Client, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("created client for %s", serverName)
|
log.Debugf(gotext.Get("created client for %s", serverName))
|
||||||
|
|
||||||
info, err := cl.Info(context.Background())
|
info, err := cl.Info(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -94,10 +94,10 @@ func New(serverName string, opts ...Opt) (*client.Client, error) {
|
|||||||
|
|
||||||
if info.Swarm.LocalNodeState == "inactive" {
|
if info.Swarm.LocalNodeState == "inactive" {
|
||||||
if serverName != "default" {
|
if serverName != "default" {
|
||||||
return cl, fmt.Errorf("swarm mode not enabled on %s?", serverName)
|
return cl, errors.New(gotext.Get("swarm mode not enabled on %s?", serverName))
|
||||||
}
|
}
|
||||||
|
|
||||||
return cl, errors.New("swarm mode not enabled on local server?")
|
return cl, errors.New(gotext.Get("swarm mode not enabled on local server?"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return cl, nil
|
return cl, nil
|
||||||
|
@ -2,11 +2,12 @@ package client
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"errors"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/swarm"
|
"github.com/docker/docker/api/types/swarm"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetConfigs(cl *client.Client, ctx context.Context, server string, fs filters.Args) ([]swarm.Config, error) {
|
func GetConfigs(cl *client.Client, ctx context.Context, server string, fs filters.Args) ([]swarm.Config, error) {
|
||||||
@ -31,7 +32,7 @@ func GetConfigNames(configs []swarm.Config) []string {
|
|||||||
func RemoveConfigs(cl *client.Client, ctx context.Context, configNames []string, force bool) error {
|
func RemoveConfigs(cl *client.Client, ctx context.Context, configNames []string, force bool) error {
|
||||||
for _, confName := range configNames {
|
for _, confName := range configNames {
|
||||||
if err := cl.ConfigRemove(context.Background(), confName); err != nil {
|
if err := cl.ConfigRemove(context.Background(), confName); err != nil {
|
||||||
return fmt.Errorf("conf %s: %s", confName, err)
|
return errors.New(gotext.Get("conf %s: %s", confName, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
dConfig "github.com/docker/cli/cli/config"
|
dConfig "github.com/docker/cli/cli/config"
|
||||||
"github.com/docker/cli/cli/context/docker"
|
"github.com/docker/cli/cli/context/docker"
|
||||||
contextStore "github.com/docker/cli/cli/context/store"
|
contextStore "github.com/docker/cli/cli/context/store"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Context = contextStore.Metadata
|
type Context = contextStore.Metadata
|
||||||
@ -22,7 +23,7 @@ func CreateContext(contextName string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("created the %s context", contextName)
|
log.Debugf(gotext.Get("created the %s context", contextName))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -62,7 +63,7 @@ func createContext(name string, host string) error {
|
|||||||
|
|
||||||
func DeleteContext(name string) error {
|
func DeleteContext(name string) error {
|
||||||
if name == "default" {
|
if name == "default" {
|
||||||
return errors.New("context 'default' cannot be removed")
|
return errors.New(gotext.Get("context 'default' cannot be removed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := GetContext(name); err != nil {
|
if _, err := GetContext(name); err != nil {
|
||||||
|
@ -2,11 +2,13 @@ package client
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/containers/image/docker"
|
"github.com/containers/image/docker"
|
||||||
"github.com/containers/image/types"
|
"github.com/containers/image/types"
|
||||||
"github.com/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetRegistryTags retrieves all tags of an image from a container registry.
|
// GetRegistryTags retrieves all tags of an image from a container registry.
|
||||||
@ -15,7 +17,7 @@ func GetRegistryTags(img reference.Named) ([]string, error) {
|
|||||||
|
|
||||||
ref, err := docker.ParseReference(fmt.Sprintf("//%s", img))
|
ref, err := docker.ParseReference(fmt.Sprintf("//%s", img))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return tags, fmt.Errorf("failed to parse image %s, saw: %s", img, err.Error())
|
return tags, errors.New(gotext.Get("failed to parse image %s, saw: %s", img, err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
@ -2,6 +2,7 @@ package client
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -9,6 +10,7 @@ import (
|
|||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/volume"
|
"github.com/docker/docker/api/types/volume"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetVolumes(cl *client.Client, ctx context.Context, server string, fs filters.Args) ([]*volume.Volume, error) {
|
func GetVolumes(cl *client.Client, ctx context.Context, server string, fs filters.Args) ([]*volume.Volume, error) {
|
||||||
@ -54,9 +56,9 @@ func retryFunc(retries int, fn func() error) error {
|
|||||||
}
|
}
|
||||||
if i+1 < retries {
|
if i+1 < retries {
|
||||||
sleep := time.Duration(i+1) * time.Duration(i+1)
|
sleep := time.Duration(i+1) * time.Duration(i+1)
|
||||||
log.Infof("%s: waiting %d seconds before next retry", err, sleep)
|
log.Infof(gotext.Get("%s: waiting %d seconds before next retry", err, sleep))
|
||||||
time.Sleep(sleep * time.Second)
|
time.Sleep(sleep * time.Second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fmt.Errorf("%d retries failed", retries)
|
return errors.New(gotext.Get("%d retries failed", retries))
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -16,13 +17,13 @@ func LoadAbraConfig() Abra {
|
|||||||
wd, _ := os.Getwd()
|
wd, _ := os.Getwd()
|
||||||
configFile := findAbraConfig(wd)
|
configFile := findAbraConfig(wd)
|
||||||
if configFile == "" {
|
if configFile == "" {
|
||||||
log.Debugf("no config file found")
|
log.Debugf(gotext.Get("no config file found"))
|
||||||
return Abra{}
|
return Abra{}
|
||||||
}
|
}
|
||||||
data, err := os.ReadFile(configFile)
|
data, err := os.ReadFile(configFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Do nothing, when an error occurs
|
// Do nothing, when an error occurs
|
||||||
log.Debugf("error reading config file: %s", err)
|
log.Debugf(gotext.Get("error reading config file: %s", err))
|
||||||
return Abra{}
|
return Abra{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,10 +31,10 @@ func LoadAbraConfig() Abra {
|
|||||||
err = yaml.Unmarshal(data, &config)
|
err = yaml.Unmarshal(data, &config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Do nothing, when an error occurs
|
// Do nothing, when an error occurs
|
||||||
log.Debugf("error loading config file: %s", err)
|
log.Debugf(gotext.Get("error loading config file: %s", err))
|
||||||
return Abra{}
|
return Abra{}
|
||||||
}
|
}
|
||||||
log.Debugf("config file loaded from: %s", configFile)
|
log.Debugf(gotext.Get("config file loaded from: %s", configFile))
|
||||||
config.configPath = filepath.Dir(configFile)
|
config.configPath = filepath.Dir(configFile)
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
@ -73,26 +74,24 @@ type Abra struct {
|
|||||||
// 3. use $HOME/.abra when above two options failed
|
// 3. use $HOME/.abra when above two options failed
|
||||||
func (a Abra) GetAbraDir() string {
|
func (a Abra) GetAbraDir() string {
|
||||||
if dir, exists := os.LookupEnv("ABRA_DIR"); exists && dir != "" {
|
if dir, exists := os.LookupEnv("ABRA_DIR"); exists && dir != "" {
|
||||||
log.Debug("read abra dir from $ABRA_DIR")
|
log.Debug(gotext.Get("read abra dir from $ABRA_DIR"))
|
||||||
return dir
|
return dir
|
||||||
}
|
}
|
||||||
if a.AbraDir != "" {
|
if a.AbraDir != "" {
|
||||||
log.Debug("read abra dir from config file")
|
log.Debug(gotext.Get("read abra dir from config file"))
|
||||||
if path.IsAbs(a.AbraDir) {
|
if path.IsAbs(a.AbraDir) {
|
||||||
return a.AbraDir
|
return a.AbraDir
|
||||||
}
|
}
|
||||||
// Make the path absolute
|
// Make the path absolute
|
||||||
return path.Join(a.configPath, a.AbraDir)
|
return path.Join(a.configPath, a.AbraDir)
|
||||||
}
|
}
|
||||||
log.Debug("using default abra dir")
|
log.Debug(gotext.Get("using default abra dir"))
|
||||||
return os.ExpandEnv("$HOME/.abra")
|
return os.ExpandEnv("$HOME/.abra")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a Abra) GetServersDir() string { return path.Join(a.GetAbraDir(), "servers") }
|
func (a Abra) GetServersDir() string { return path.Join(a.GetAbraDir(), "servers") }
|
||||||
func (a Abra) GetRecipesDir() string { return path.Join(a.GetAbraDir(), "recipes") }
|
func (a Abra) GetRecipesDir() string { return path.Join(a.GetAbraDir(), "recipes") }
|
||||||
func (a Abra) GetLogsDir() string { return path.Join(a.GetAbraDir(), "logs") }
|
func (a Abra) GetLogsDir() string { return path.Join(a.GetAbraDir(), "logs") }
|
||||||
func (a Abra) GetVendorDir() string { return path.Join(a.GetAbraDir(), "vendor") }
|
|
||||||
func (a Abra) GetBackupDir() string { return path.Join(a.GetAbraDir(), "backups") }
|
|
||||||
func (a Abra) GetCatalogueDir() string { return path.Join(a.GetAbraDir(), "catalogue") }
|
func (a Abra) GetCatalogueDir() string { return path.Join(a.GetAbraDir(), "catalogue") }
|
||||||
|
|
||||||
var config = LoadAbraConfig()
|
var config = LoadAbraConfig()
|
||||||
@ -102,8 +101,6 @@ var (
|
|||||||
SERVERS_DIR = config.GetServersDir()
|
SERVERS_DIR = config.GetServersDir()
|
||||||
RECIPES_DIR = config.GetRecipesDir()
|
RECIPES_DIR = config.GetRecipesDir()
|
||||||
LOGS_DIR = config.GetLogsDir()
|
LOGS_DIR = config.GetLogsDir()
|
||||||
VENDOR_DIR = config.GetVendorDir()
|
|
||||||
BACKUP_DIR = config.GetBackupDir()
|
|
||||||
CATALOGUE_DIR = config.GetCatalogueDir()
|
CATALOGUE_DIR = config.GetCatalogueDir()
|
||||||
RECIPES_JSON = path.Join(config.GetCatalogueDir(), "recipes.json")
|
RECIPES_JSON = path.Join(config.GetCatalogueDir(), "recipes.json")
|
||||||
REPOS_BASE_URL = "https://git.coopcloud.tech/coop-cloud"
|
REPOS_BASE_URL = "https://git.coopcloud.tech/coop-cloud"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"errors"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@ -10,6 +10,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
const MAX_SANITISED_APP_NAME_LENGTH = 45
|
const MAX_SANITISED_APP_NAME_LENGTH = 45
|
||||||
@ -33,7 +34,7 @@ func GetServers() ([]string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("retrieved %v servers: %s", len(filtered), filtered)
|
log.Debugf(gotext.Get("retrieved %v servers: %s", len(filtered), filtered))
|
||||||
|
|
||||||
return filtered, nil
|
return filtered, nil
|
||||||
}
|
}
|
||||||
@ -46,7 +47,7 @@ func ReadServerNames() ([]string, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("read %s from %s", strings.Join(serverNames, ","), SERVERS_DIR)
|
log.Debugf(gotext.Get("read %s from %s", strings.Join(serverNames, ","), SERVERS_DIR))
|
||||||
|
|
||||||
return serverNames, nil
|
return serverNames, nil
|
||||||
}
|
}
|
||||||
@ -70,7 +71,7 @@ func GetAllFilesInDirectory(directory string) ([]fs.FileInfo, error) {
|
|||||||
|
|
||||||
realPath, err := filepath.EvalSymlinks(filePath)
|
realPath, err := filepath.EvalSymlinks(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("broken symlink in your abra config folders: %s", filePath)
|
log.Warnf(gotext.Get("broken symlink in your abra config folders: %s", filePath))
|
||||||
} else {
|
} else {
|
||||||
realFile, err := os.Stat(realPath)
|
realFile, err := os.Stat(realPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -94,7 +95,7 @@ func GetAllFoldersInDirectory(directory string) ([]string, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(files) == 0 {
|
if len(files) == 0 {
|
||||||
return nil, fmt.Errorf("directory is empty: %s", directory)
|
return nil, errors.New(gotext.Get("directory is empty: %s", directory))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
@ -103,7 +104,7 @@ func GetAllFoldersInDirectory(directory string) ([]string, error) {
|
|||||||
filePath := path.Join(directory, file.Name())
|
filePath := path.Join(directory, file.Name())
|
||||||
realDir, err := filepath.EvalSymlinks(filePath)
|
realDir, err := filepath.EvalSymlinks(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("broken symlink in your abra config folders: %s", filePath)
|
log.Warnf(gotext.Get("broken symlink in your abra config folders: %s", filePath))
|
||||||
} else if stat, err := os.Stat(realDir); err == nil && stat.IsDir() {
|
} else if stat, err := os.Stat(realDir); err == nil && stat.IsDir() {
|
||||||
// path is a directory
|
// path is a directory
|
||||||
folders = append(folders, file.Name())
|
folders = append(folders, file.Name())
|
||||||
|
@ -2,6 +2,7 @@ package container
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -12,6 +13,7 @@ import (
|
|||||||
containerTypes "github.com/docker/docker/api/types/container"
|
containerTypes "github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetContainer retrieves a container. If noInput is false and the retrievd
|
// GetContainer retrieves a container. If noInput is false and the retrievd
|
||||||
@ -26,7 +28,7 @@ func GetContainer(c context.Context, cl *client.Client, filters filters.Args, no
|
|||||||
|
|
||||||
if len(containers) == 0 {
|
if len(containers) == 0 {
|
||||||
filter := filters.Get("name")[0]
|
filter := filters.Get("name")[0]
|
||||||
return types.Container{}, fmt.Errorf("no containers matching the %v filter found?", filter)
|
return types.Container{}, errors.New(gotext.Get("no containers matching the %v filter found?", filter))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(containers) > 1 {
|
if len(containers) > 1 {
|
||||||
@ -35,19 +37,19 @@ func GetContainer(c context.Context, cl *client.Client, filters filters.Args, no
|
|||||||
containerName := strings.Join(container.Names, " ")
|
containerName := strings.Join(container.Names, " ")
|
||||||
trimmed := strings.TrimPrefix(containerName, "/")
|
trimmed := strings.TrimPrefix(containerName, "/")
|
||||||
created := formatter.HumanDuration(container.Created)
|
created := formatter.HumanDuration(container.Created)
|
||||||
containersRaw = append(containersRaw, fmt.Sprintf("%s (created %v)", trimmed, created))
|
containersRaw = append(containersRaw, gotext.Get("%s (created %v)", trimmed, created))
|
||||||
}
|
}
|
||||||
|
|
||||||
if noInput {
|
if noInput {
|
||||||
err := fmt.Errorf("expected 1 container but found %v: %s", len(containers), strings.Join(containersRaw, " "))
|
err := errors.New(gotext.Get("expected 1 container but found %v: %s", len(containers), strings.Join(containersRaw, " ")))
|
||||||
return types.Container{}, err
|
return types.Container{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Warnf("ambiguous container list received, prompting for input")
|
log.Warnf(gotext.Get("ambiguous container list received, prompting for input"))
|
||||||
|
|
||||||
var response string
|
var response string
|
||||||
prompt := &survey.Select{
|
prompt := &survey.Select{
|
||||||
Message: "which container are you looking for?",
|
Message: gotext.Get("which container are you looking for?"),
|
||||||
Options: containersRaw,
|
Options: containersRaw,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +66,7 @@ func GetContainer(c context.Context, cl *client.Client, filters filters.Args, no
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Fatal("failed to match chosen container")
|
log.Fatal(gotext.Get("failed to match chosen container"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return containers[0], nil
|
return containers[0], nil
|
||||||
@ -79,5 +81,6 @@ func GetContainerFromStackAndService(cl *client.Client, stack, service string) (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return types.Container{}, err
|
return types.Container{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return container, nil
|
return container, nil
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/docker/cli/cli/context"
|
"github.com/docker/cli/cli/context"
|
||||||
contextStore "github.com/docker/cli/cli/context/store"
|
contextStore "github.com/docker/cli/cli/context/store"
|
||||||
cliflags "github.com/docker/cli/cli/flags"
|
cliflags "github.com/docker/cli/cli/flags"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewDefaultDockerContextStore() *command.ContextStoreWithDefault {
|
func NewDefaultDockerContextStore() *command.ContextStoreWithDefault {
|
||||||
@ -30,7 +31,7 @@ func NewDefaultDockerContextStore() *command.ContextStoreWithDefault {
|
|||||||
func GetContextEndpoint(ctx contextStore.Metadata) (string, error) {
|
func GetContextEndpoint(ctx contextStore.Metadata) (string, error) {
|
||||||
endpointmeta, ok := ctx.Endpoints["docker"].(context.EndpointMetaBase)
|
endpointmeta, ok := ctx.Endpoints["docker"].(context.EndpointMetaBase)
|
||||||
if !ok {
|
if !ok {
|
||||||
err := errors.New("context lacks Docker endpoint")
|
err := errors.New(gotext.Get("context lacks Docker endpoint"))
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return endpointmeta.Host, nil
|
return endpointmeta.Host, nil
|
||||||
|
@ -1,19 +1,21 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EnsureIPv4 ensures that an ipv4 address is set for a domain name
|
// EnsureIPv4 ensures that an ipv4 address is set for a domain name
|
||||||
func EnsureIPv4(domainName string) (string, error) {
|
func EnsureIPv4(domainName string) (string, error) {
|
||||||
ipv4, err := net.ResolveIPAddr("ip4", domainName)
|
ipv4, err := net.ResolveIPAddr("ip4", domainName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("%s: unable to resolve IPv4 address: %s", domainName, err)
|
return "", errors.New(gotext.Get("%s: unable to resolve IPv4 address: %s", domainName, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if ipv4 == nil {
|
if ipv4 == nil {
|
||||||
return "", fmt.Errorf("%s: no IPv4 available", domainName)
|
return "", errors.New(gotext.Get("%s: no IPv4 available", domainName))
|
||||||
}
|
}
|
||||||
|
|
||||||
return ipv4.String(), nil
|
return ipv4.String(), nil
|
||||||
@ -33,7 +35,7 @@ func EnsureDomainsResolveSameIPv4(domainName, server string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if domainIPv4 == "" {
|
if domainIPv4 == "" {
|
||||||
return ipv4, fmt.Errorf("cannot resolve ipv4 for %s?", domainName)
|
return ipv4, errors.New(gotext.Get("cannot resolve ipv4 for %s?", domainName))
|
||||||
}
|
}
|
||||||
|
|
||||||
serverIPv4, err := EnsureIPv4(server)
|
serverIPv4, err := EnsureIPv4(server)
|
||||||
@ -42,12 +44,16 @@ func EnsureDomainsResolveSameIPv4(domainName, server string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if serverIPv4 == "" {
|
if serverIPv4 == "" {
|
||||||
return ipv4, fmt.Errorf("cannot resolve ipv4 for %s?", server)
|
return ipv4, errors.New(gotext.Get("cannot resolve ipv4 for %s?", server))
|
||||||
}
|
}
|
||||||
|
|
||||||
if domainIPv4 != serverIPv4 {
|
if domainIPv4 != serverIPv4 {
|
||||||
err := "app domain %s (%s) does not appear to resolve to app server %s (%s)?"
|
return ipv4, errors.New(
|
||||||
return ipv4, fmt.Errorf(err, domainName, domainIPv4, server, serverIPv4)
|
gotext.Get(
|
||||||
|
"app domain %s (%s) does not appear to resolve to app server %s (%s)?",
|
||||||
|
domainName, domainIPv4, server, serverIPv4,
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ipv4, nil
|
return ipv4, nil
|
||||||
|
@ -2,13 +2,14 @@ package envfile
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"git.coopcloud.tech/toolshed/godotenv"
|
"git.coopcloud.tech/toolshed/godotenv"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AppEnv is a map of the values in an apps env config
|
// AppEnv is a map of the values in an apps env config
|
||||||
@ -38,7 +39,7 @@ func ReadEnvWithModifiers(filePath string) (AppEnv, AppModifiers, error) {
|
|||||||
return nil, mods, err
|
return nil, mods, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("read %s from %s", envVars, filePath)
|
log.Debugf(gotext.Get("read %s from %s", envVars, filePath))
|
||||||
|
|
||||||
return envVars, mods, nil
|
return envVars, mods, nil
|
||||||
}
|
}
|
||||||
@ -69,16 +70,16 @@ func ReadAbraShEnvVars(abraSh string) (map[string]string, error) {
|
|||||||
envVarDef := splitVals[len(splitVals)-1]
|
envVarDef := splitVals[len(splitVals)-1]
|
||||||
keyVal := strings.Split(envVarDef, "=")
|
keyVal := strings.Split(envVarDef, "=")
|
||||||
if len(keyVal) != 2 {
|
if len(keyVal) != 2 {
|
||||||
return envVars, fmt.Errorf("couldn't parse %s", txt)
|
return envVars, errors.New(gotext.Get("couldn't parse %s", txt))
|
||||||
}
|
}
|
||||||
envVars[keyVal[0]] = keyVal[1]
|
envVars[keyVal[0]] = keyVal[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(envVars) > 0 {
|
if len(envVars) > 0 {
|
||||||
log.Debugf("read %s from %s", envVars, abraSh)
|
log.Debugf(gotext.Get("read %s from %s", envVars, abraSh))
|
||||||
} else {
|
} else {
|
||||||
log.Debugf("read 0 env var exports from %s", abraSh)
|
log.Debugf(gotext.Get("read 0 env var exports from %s", abraSh))
|
||||||
}
|
}
|
||||||
|
|
||||||
return envVars, nil
|
return envVars, nil
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
"github.com/charmbracelet/lipgloss/table"
|
"github.com/charmbracelet/lipgloss/table"
|
||||||
"github.com/docker/go-units"
|
"github.com/docker/go-units"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
|
|
||||||
"coopcloud.tech/abra/pkg/config"
|
"coopcloud.tech/abra/pkg/config"
|
||||||
@ -42,7 +43,7 @@ func RemoveSha(str string) string {
|
|||||||
func HumanDuration(timestamp int64) string {
|
func HumanDuration(timestamp int64) string {
|
||||||
date := time.Unix(timestamp, 0)
|
date := time.Unix(timestamp, 0)
|
||||||
now := time.Now().UTC()
|
now := time.Now().UTC()
|
||||||
return units.HumanDuration(now.Sub(date)) + " ago"
|
return units.HumanDuration(now.Sub(date)) + gotext.Get(" ago")
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateTable prepares a table layout for output.
|
// CreateTable prepares a table layout for output.
|
||||||
@ -76,7 +77,7 @@ func CreateTable() (*table.Table, error) {
|
|||||||
func PrintTable(t *table.Table) error {
|
func PrintTable(t *table.Table) error {
|
||||||
if isAbraCI, ok := os.LookupEnv("ABRA_CI"); ok && isAbraCI == "1" {
|
if isAbraCI, ok := os.LookupEnv("ABRA_CI"); ok && isAbraCI == "1" {
|
||||||
// NOTE(d1): no width limits for CI testing since we test against outputs
|
// NOTE(d1): no width limits for CI testing since we test against outputs
|
||||||
log.Debug("detected ABRA_CI=1")
|
log.Debug(gotext.Get("detected ABRA_CI=1"))
|
||||||
fmt.Println(t)
|
fmt.Println(t)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -130,7 +131,7 @@ func CreateOverview(header string, rows [][]string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(row) > 2 {
|
if len(row) > 2 {
|
||||||
panic("CreateOverview: only accepts rows of len == 2")
|
panic(gotext.Get("CreateOverview: only accepts rows of len == 2"))
|
||||||
}
|
}
|
||||||
|
|
||||||
lenOffset := 4
|
lenOffset := 4
|
||||||
@ -234,7 +235,7 @@ func StripTagMeta(image string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if originalImage != image {
|
if originalImage != image {
|
||||||
log.Debugf("stripped %s to %s for parsing", originalImage, image)
|
log.Debugf(gotext.Get("stripped %s to %s for parsing", originalImage, image))
|
||||||
}
|
}
|
||||||
|
|
||||||
return image
|
return image
|
||||||
|
@ -3,6 +3,7 @@ package git
|
|||||||
import (
|
import (
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Add adds a file to the git index.
|
// Add adds a file to the git index.
|
||||||
@ -18,7 +19,7 @@ func Add(repoPath, path string, dryRun bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if dryRun {
|
if dryRun {
|
||||||
log.Debugf("dry run: adding %s", path)
|
log.Debugf(gotext.Get("dry run: adding %s", path))
|
||||||
} else {
|
} else {
|
||||||
worktree.Add(path)
|
worktree.Add(path)
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package git
|
package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
"github.com/go-git/go-git/v5/plumbing"
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Check if a branch exists in a repo. Use this and not repository.Branch(),
|
// Check if a branch exists in a repo. Use this and not repository.Branch(),
|
||||||
@ -63,7 +65,7 @@ func GetDefaultBranch(repo *git.Repository, repoPath string) (plumbing.Reference
|
|||||||
|
|
||||||
if !HasBranch(repo, "master") {
|
if !HasBranch(repo, "master") {
|
||||||
if !HasBranch(repo, "main") {
|
if !HasBranch(repo, "main") {
|
||||||
return "", fmt.Errorf("failed to select default branch in %s", repoPath)
|
return "", errors.New(gotext.Get("failed to select default branch in %s", repoPath))
|
||||||
}
|
}
|
||||||
branch = "main"
|
branch = "main"
|
||||||
}
|
}
|
||||||
@ -90,11 +92,11 @@ func CheckoutDefaultBranch(repo *git.Repository, repoPath string) (plumbing.Refe
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := worktree.Checkout(checkOutOpts); err != nil {
|
if err := worktree.Checkout(checkOutOpts); err != nil {
|
||||||
log.Debugf("failed to check out %s in %s", branch, repoPath)
|
log.Debugf(gotext.Get("failed to check out %s in %s", branch, repoPath))
|
||||||
return branch, err
|
return branch, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("successfully checked out %v in %s", branch, repoPath)
|
log.Debugf(gotext.Get("successfully checked out %v in %s", branch, repoPath))
|
||||||
|
|
||||||
return branch, nil
|
return branch, nil
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package git
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
@ -10,6 +11,7 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
"github.com/go-git/go-git/v5/plumbing"
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
// gitCloneIgnoreErr checks whether we can ignore a git clone error or not.
|
// gitCloneIgnoreErr checks whether we can ignore a git clone error or not.
|
||||||
@ -44,7 +46,7 @@ func Clone(dir, url string) error {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||||
log.Debugf("git clone: %s", url)
|
log.Debugf(gotext.Get("git clone: %s", url))
|
||||||
|
|
||||||
_, err := git.PlainCloneContext(ctx, dir, false, &git.CloneOptions{
|
_, err := git.PlainCloneContext(ctx, dir, false, &git.CloneOptions{
|
||||||
URL: url,
|
URL: url,
|
||||||
@ -54,16 +56,16 @@ func Clone(dir, url string) error {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err != nil && gitCloneIgnoreErr(err) {
|
if err != nil && gitCloneIgnoreErr(err) {
|
||||||
log.Debugf("git clone: %s cloned successfully", dir)
|
log.Debugf(gotext.Get("git clone: %s cloned successfully", dir))
|
||||||
errCh <- nil
|
errCh <- nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ctx.Err(); err != nil {
|
if err := ctx.Err(); err != nil {
|
||||||
errCh <- fmt.Errorf("git clone %s: cancelled due to interrupt", dir)
|
errCh <- errors.New(gotext.Get("git clone %s: cancelled due to interrupt", dir))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("git clone: main branch failed, attempting master branch")
|
log.Debug(gotext.Get("git clone: main branch failed, attempting master branch"))
|
||||||
|
|
||||||
_, err := git.PlainCloneContext(ctx, dir, false, &git.CloneOptions{
|
_, err := git.PlainCloneContext(ctx, dir, false, &git.CloneOptions{
|
||||||
URL: url,
|
URL: url,
|
||||||
@ -73,7 +75,7 @@ func Clone(dir, url string) error {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err != nil && gitCloneIgnoreErr(err) {
|
if err != nil && gitCloneIgnoreErr(err) {
|
||||||
log.Debugf("git clone: %s cloned successfully", dir)
|
log.Debugf(gotext.Get("git clone: %s cloned successfully", dir))
|
||||||
errCh <- nil
|
errCh <- nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,9 +84,9 @@ func Clone(dir, url string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("git clone: %s cloned successfully", dir)
|
log.Debugf(gotext.Get("git clone: %s cloned successfully", dir))
|
||||||
} else {
|
} else {
|
||||||
log.Debugf("git clone: %s already exists", dir)
|
log.Debugf(gotext.Get("git clone: %s already exists", dir))
|
||||||
}
|
}
|
||||||
|
|
||||||
errCh <- nil
|
errCh <- nil
|
||||||
@ -95,9 +97,9 @@ func Clone(dir, url string) error {
|
|||||||
cancelCtx()
|
cancelCtx()
|
||||||
fmt.Println() // NOTE(d1): newline after ^C
|
fmt.Println() // NOTE(d1): newline after ^C
|
||||||
if err := os.RemoveAll(dir); err != nil {
|
if err := os.RemoveAll(dir); err != nil {
|
||||||
return fmt.Errorf("unable to clean up git clone of %s: %s", dir, err)
|
return errors.New(gotext.Get("unable to clean up git clone of %s: %s", dir, err))
|
||||||
}
|
}
|
||||||
return fmt.Errorf("git clone %s: cancelled due to interrupt", dir)
|
return errors.New(gotext.Get("git clone %s: cancelled due to interrupt", dir))
|
||||||
case err := <-errCh:
|
case err := <-errCh:
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
package git
|
package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"errors"
|
||||||
|
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Commit runs a git commit
|
// Commit runs a git commit
|
||||||
func Commit(repoPath, commitMessage string, dryRun bool) error {
|
func Commit(repoPath, commitMessage string, dryRun bool) error {
|
||||||
if commitMessage == "" {
|
if commitMessage == "" {
|
||||||
return fmt.Errorf("no commit message specified?")
|
return errors.New(gotext.Get("no commit message specified?"))
|
||||||
}
|
}
|
||||||
|
|
||||||
commitRepo, err := git.PlainOpen(repoPath)
|
commitRepo, err := git.PlainOpen(repoPath)
|
||||||
@ -38,9 +39,9 @@ func Commit(repoPath, commitMessage string, dryRun bool) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Debug("git changes commited")
|
log.Debug(gotext.Get("git changes commited"))
|
||||||
} else {
|
} else {
|
||||||
log.Debug("dry run: no changes commited")
|
log.Debug(gotext.Get("dry run: no changes commited"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
package git
|
package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EnsureGitRepo ensures a git repo .git folder exists
|
// EnsureGitRepo ensures a git repo .git folder exists
|
||||||
func EnsureGitRepo(repoPath string) error {
|
func EnsureGitRepo(repoPath string) error {
|
||||||
if _, err := os.Stat(repoPath); os.IsNotExist(err) {
|
if _, err := os.Stat(repoPath); os.IsNotExist(err) {
|
||||||
return fmt.Errorf("no .git directory in %s?", repoPath)
|
return errors.New(gotext.Get("no .git directory in %s?", repoPath))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
// getGitDiffArgs builds the `git diff` invocation args. It removes the usage
|
// getGitDiffArgs builds the `git diff` invocation args. It removes the usage
|
||||||
@ -26,7 +27,7 @@ func getGitDiffArgs(repoPath string) []string {
|
|||||||
// skips if it cannot find the command on the system.
|
// skips if it cannot find the command on the system.
|
||||||
func DiffUnstaged(path string) error {
|
func DiffUnstaged(path string) error {
|
||||||
if _, err := exec.LookPath("git"); err != nil {
|
if _, err := exec.LookPath("git"); err != nil {
|
||||||
log.Warnf("unable to locate git command, cannot output diff")
|
log.Warnf(gotext.Get("unable to locate git command, cannot output diff"))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,40 +1,41 @@
|
|||||||
package git
|
package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"errors"
|
||||||
|
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
"github.com/go-git/go-git/v5/plumbing"
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
"github.com/go-git/go-git/v5/plumbing/object"
|
"github.com/go-git/go-git/v5/plumbing/object"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Init inits a new repo and commits all the stuff if you want
|
// Init inits a new repo and commits all the stuff if you want
|
||||||
func Init(repoPath string, commit bool, gitName, gitEmail string) error {
|
func Init(repoPath string, commit bool, gitName, gitEmail string) error {
|
||||||
repo, err := git.PlainInit(repoPath, false)
|
repo, err := git.PlainInit(repoPath, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("git init: %s", err)
|
return errors.New(gotext.Get("git init: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = SwitchToMain(repo); err != nil {
|
if err = SwitchToMain(repo); err != nil {
|
||||||
return fmt.Errorf("git branch rename: %s", err)
|
return errors.New(gotext.Get("git branch rename: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("initialised new git repo in %s", repoPath)
|
log.Debugf(gotext.Get("initialised new git repo in %s", repoPath))
|
||||||
|
|
||||||
if commit {
|
if commit {
|
||||||
commitRepo, err := git.PlainOpen(repoPath)
|
commitRepo, err := git.PlainOpen(repoPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("git open: %s", err)
|
return errors.New(gotext.Get("git open: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
commitWorktree, err := commitRepo.Worktree()
|
commitWorktree, err := commitRepo.Worktree()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("git worktree: %s", err)
|
return errors.New(gotext.Get("git worktree: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := commitWorktree.AddWithOptions(&git.AddOptions{All: true}); err != nil {
|
if err := commitWorktree.AddWithOptions(&git.AddOptions{All: true}); err != nil {
|
||||||
return fmt.Errorf("git add: %s", err)
|
return errors.New(gotext.Get("git add: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
var author *object.Signature
|
var author *object.Signature
|
||||||
@ -43,10 +44,10 @@ func Init(repoPath string, commit bool, gitName, gitEmail string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, err = commitWorktree.Commit("init", &git.CommitOptions{Author: author}); err != nil {
|
if _, err = commitWorktree.Commit("init", &git.CommitOptions{Author: author}); err != nil {
|
||||||
return fmt.Errorf("git commit: %s", err)
|
return errors.New(gotext.Get("git commit: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("init committed all files for new git repo in %s", repoPath)
|
log.Debugf(gotext.Get("init committed all files for new git repo in %s", repoPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -56,20 +57,20 @@ func Init(repoPath string, commit bool, gitName, gitEmail string) error {
|
|||||||
func SwitchToMain(repo *git.Repository) error {
|
func SwitchToMain(repo *git.Repository) error {
|
||||||
ref := plumbing.NewSymbolicReference(plumbing.HEAD, plumbing.ReferenceName("refs/heads/main"))
|
ref := plumbing.NewSymbolicReference(plumbing.HEAD, plumbing.ReferenceName("refs/heads/main"))
|
||||||
if err := repo.Storer.SetReference(ref); err != nil {
|
if err := repo.Storer.SetReference(ref); err != nil {
|
||||||
return fmt.Errorf("set reference: %s", err)
|
return errors.New(gotext.Get("set reference: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, err := repo.Config()
|
cfg, err := repo.Config()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("repo config: %s", err)
|
return errors.New(gotext.Get("repo config: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.Init.DefaultBranch = "main"
|
cfg.Init.DefaultBranch = "main"
|
||||||
if err := repo.SetConfig(cfg); err != nil {
|
if err := repo.SetConfig(cfg); err != nil {
|
||||||
return fmt.Errorf("repo set config: %s", err)
|
return errors.New(gotext.Get("repo set config: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug("set 'main' as the default branch")
|
log.Debug(gotext.Get("set 'main' as the default branch"))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,13 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
"github.com/go-git/go-git/v5/config"
|
"github.com/go-git/go-git/v5/config"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Push pushes the latest changes & optionally tags to the default remote
|
// Push pushes the latest changes & optionally tags to the default remote
|
||||||
func Push(repoDir string, remote string, tags bool, dryRun bool) error {
|
func Push(repoDir string, remote string, tags bool, dryRun bool) error {
|
||||||
if dryRun {
|
if dryRun {
|
||||||
log.Debugf("dry run: no git changes pushed in %s", repoDir)
|
log.Debugf(gotext.Get("dry run: no git changes pushed in %s", repoDir))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +28,7 @@ func Push(repoDir string, remote string, tags bool, dryRun bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("git changes pushed")
|
log.Debugf(gotext.Get("git changes pushed"))
|
||||||
|
|
||||||
if tags {
|
if tags {
|
||||||
opts.RefSpecs = append(opts.RefSpecs, config.RefSpec("+refs/tags/*:refs/tags/*"))
|
opts.RefSpecs = append(opts.RefSpecs, config.RefSpec("+refs/tags/*:refs/tags/*"))
|
||||||
@ -36,7 +37,7 @@ func Push(repoDir string, remote string, tags bool, dryRun bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("git tags pushed")
|
log.Debugf(gotext.Get("git tags pushed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -2,7 +2,6 @@ package git
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
@ -13,6 +12,7 @@ import (
|
|||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
gitConfigPkg "github.com/go-git/go-git/v5/config"
|
gitConfigPkg "github.com/go-git/go-git/v5/config"
|
||||||
"github.com/go-git/go-git/v5/plumbing/format/gitignore"
|
"github.com/go-git/go-git/v5/plumbing/format/gitignore"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsClean checks if a repo has unstaged changes
|
// IsClean checks if a repo has unstaged changes
|
||||||
@ -23,12 +23,12 @@ func IsClean(repoPath string) (bool, error) {
|
|||||||
return false, git.ErrRepositoryNotExists
|
return false, git.ErrRepositoryNotExists
|
||||||
}
|
}
|
||||||
|
|
||||||
return false, fmt.Errorf("unable to open %s: %s", repoPath, err)
|
return false, errors.New(gotext.Get("unable to open %s: %s", repoPath, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
worktree, err := repo.Worktree()
|
worktree, err := repo.Worktree()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("unable to open worktree of %s: %s", repoPath, err)
|
return false, errors.New(gotext.Get("unable to open worktree of %s: %s", repoPath, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
patterns, err := GetExcludesFiles()
|
patterns, err := GetExcludesFiles()
|
||||||
@ -42,14 +42,14 @@ func IsClean(repoPath string) (bool, error) {
|
|||||||
|
|
||||||
status, err := worktree.Status()
|
status, err := worktree.Status()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("unable to query status of %s: %s", repoPath, err)
|
return false, errors.New(gotext.Get("unable to query status of %s: %s", repoPath, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.String() != "" {
|
if status.String() != "" {
|
||||||
noNewline := strings.TrimSuffix(status.String(), "\n")
|
noNewline := strings.TrimSuffix(status.String(), "\n")
|
||||||
log.Debugf("git status: %s: %s", repoPath, noNewline)
|
log.Debugf(gotext.Get("git status: %s: %s", repoPath, noNewline))
|
||||||
} else {
|
} else {
|
||||||
log.Debugf("git status: %s: clean", repoPath)
|
log.Debugf(gotext.Get("git status: %s: clean", repoPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
return status.IsClean(), nil
|
return status.IsClean(), nil
|
||||||
@ -85,7 +85,7 @@ func parseGitConfig() (*gitConfigPkg.Config, error) {
|
|||||||
globalGitConfig := filepath.Join(usr.HomeDir, ".gitconfig")
|
globalGitConfig := filepath.Join(usr.HomeDir, ".gitconfig")
|
||||||
if _, err := os.Stat(globalGitConfig); err != nil {
|
if _, err := os.Stat(globalGitConfig); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
log.Debugf("no %s exists, not reading any global gitignore config", globalGitConfig)
|
log.Debugf(gotext.Get("no %s exists, not reading any global gitignore config", globalGitConfig))
|
||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
return cfg, err
|
return cfg, err
|
||||||
@ -127,7 +127,7 @@ func parseExcludesFile(excludesfile string) ([]gitignore.Pattern, error) {
|
|||||||
|
|
||||||
if _, err := os.Stat(excludesfile); err != nil {
|
if _, err := os.Stat(excludesfile); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
log.Debugf("no %s exists, skipping reading gitignore paths", excludesfile)
|
log.Debugf(gotext.Get("no %s exists, skipping reading gitignore paths", excludesfile))
|
||||||
return ps, nil
|
return ps, nil
|
||||||
}
|
}
|
||||||
return ps, err
|
return ps, err
|
||||||
@ -146,7 +146,7 @@ func parseExcludesFile(excludesfile string) ([]gitignore.Pattern, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("read global ignore paths: %s", strings.Join(pathsRaw, " "))
|
log.Debugf(gotext.Get("read global ignore paths: %s", strings.Join(pathsRaw, " ")))
|
||||||
|
|
||||||
return ps, nil
|
return ps, nil
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,13 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
"github.com/go-git/go-git/v5/config"
|
"github.com/go-git/go-git/v5/config"
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateRemote creates a new git remote in a repository
|
// CreateRemote creates a new git remote in a repository
|
||||||
func CreateRemote(repo *git.Repository, name, url string, dryRun bool) error {
|
func CreateRemote(repo *git.Repository, name, url string, dryRun bool) error {
|
||||||
if dryRun {
|
if dryRun {
|
||||||
log.Debugf("dry run: remote %s (%s) not created", name, url)
|
log.Debugf(gotext.Get("dry run: remote %s (%s) not created", name, url))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user