diff --git a/cmd/cli/commands/apply/apply.go b/cmd/cli/commands/apply/apply.go new file mode 100644 index 0000000..fa67048 --- /dev/null +++ b/cmd/cli/commands/apply/apply.go @@ -0,0 +1,42 @@ +package apply + +import ( + "context" + "flag" + "fmt" + "mirror-sync/pkg/project" + "os" + + "github.com/google/subcommands" +) + +type ( + ApplyCmd struct { + } +) + +func (*ApplyCmd) Name() string { return "apply" } +func (*ApplyCmd) Synopsis() string { return "apply the current project settings" } +func (*ApplyCmd) Usage() string { + return `Usage: git-sync apply + +apply the current project settings + +Options: +` +} + +func (p *ApplyCmd) SetFlags(f *flag.FlagSet) { +} + +func (p *ApplyCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { + projectConfig, err := project.LoadCurrent() + if err != nil { + fmt.Fprintf(os.Stderr, "error: %s\n", err) + return subcommands.ExitFailure + } + + + + return subcommands.ExitSuccess +} diff --git a/cmd/cli/commands/version/version.go b/cmd/cli/commands/version/version.go new file mode 100644 index 0000000..91358aa --- /dev/null +++ b/cmd/cli/commands/version/version.go @@ -0,0 +1,44 @@ +package version + +import ( + "context" + "flag" + "fmt" + "mirror-sync/pkg/constants" + "runtime" + "strconv" + + "github.com/google/subcommands" +) + +type ( + VersionCmd struct { + } +) + +func (*VersionCmd) Name() string { return "version" } +func (*VersionCmd) Synopsis() string { return "show version and system information" } +func (*VersionCmd) Usage() string { + return `Usage: cloudsave version + +Print the version of the software + +Options: +` +} + +func (p *VersionCmd) SetFlags(f *flag.FlagSet) { +} + +func (p *VersionCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { + local() + return subcommands.ExitSuccess +} + +func local() { + fmt.Println("Client: git-sync cli") + fmt.Println(" Version: " + constants.Version) + fmt.Println(" API version: " + strconv.Itoa(constants.ApiVersion)) + fmt.Println(" Go version: " + runtime.Version()) + fmt.Println(" OS/Arch: " + runtime.GOOS + "/" + runtime.GOARCH) +} diff --git a/cmd/cli/main.go b/cmd/cli/main.go new file mode 100644 index 0000000..28cdddc --- /dev/null +++ b/cmd/cli/main.go @@ -0,0 +1,25 @@ +package main + +import ( + "context" + "flag" + "mirror-sync/cmd/cli/commands/apply" + "mirror-sync/cmd/cli/commands/version" + "os" + + "github.com/google/subcommands" +) + +func main() { + subcommands.Register(subcommands.HelpCommand(), "help") + subcommands.Register(subcommands.FlagsCommand(), "help") + subcommands.Register(subcommands.CommandsCommand(), "help") + subcommands.Register(&version.VersionCmd{}, "help") + + subcommands.Register(&apply.ApplyCmd{}, "projects") + + flag.Parse() + ctx := context.Background() + + os.Exit(int(subcommands.Execute(ctx))) +} diff --git a/go.mod b/go.mod index f1ca3b1..0e88035 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,8 @@ go 1.25 require ( github.com/go-chi/chi/v5 v5.2.3 github.com/go-git/go-git/v6 v6.0.0-20250929195514-145daf2492dd + github.com/goccy/go-yaml v1.18.0 + github.com/google/subcommands v1.2.0 ) require ( diff --git a/go.sum b/go.sum index b2b5a8e..15f6735 100644 --- a/go.sum +++ b/go.sum @@ -29,8 +29,12 @@ github.com/go-git/go-git-fixtures/v5 v5.1.1 h1:OH8i1ojV9bWfr0ZfasfpgtUXQHQyVS8HX github.com/go-git/go-git-fixtures/v5 v5.1.1/go.mod h1:Altk43lx3b1ks+dVoAG2300o5WWUnktvfY3VI6bcaXU= github.com/go-git/go-git/v6 v6.0.0-20250929195514-145daf2492dd h1:30HEd5KKVM7GgMJ1GSNuYxuZXEg8Pdlngp6T51faxoc= github.com/go-git/go-git/v6 v6.0.0-20250929195514-145daf2492dd/go.mod h1:lz8PQr/p79XpFq5ODVBwRJu5LnOF8Et7j95ehqmCMJU= +github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= +github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= +github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= diff --git a/pkg/project/file.go b/pkg/project/file.go new file mode 100644 index 0000000..a18f9ba --- /dev/null +++ b/pkg/project/file.go @@ -0,0 +1,72 @@ +package project + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/goccy/go-yaml" +) + +type ( + MainFile struct { + Repositories map[string]RepositoryDescriptor `yaml:"repositories"` + ProjectName string `yaml:"project_name"` + } + + RepositoryDescriptor struct { + Storage GitStorage `yaml:"storage"` + Schedule string `yaml:"schedule"` + } + + GitStorage struct { + Source string `yaml:"source"` + Destination string `yaml:"destination"` + } +) + +var ( + ErrOS error = errors.New("failed to get os parameters") + ErrIO error = errors.New("failed to open file") + ErrParsing error = errors.New("failed to parse file") +) + +func LoadCurrent() (Project, error) { + wd, err := os.Getwd() + if err != nil { + return Project{}, fmt.Errorf("%w: cannot get current working directory path: %s", ErrOS, err) + } + + f, err := os.OpenFile("./git-compose.yaml", os.O_RDONLY, 0) + if err != nil { + return Project{}, fmt.Errorf("%w: %s", ErrIO, err) + } + defer f.Close() + + var mainFile MainFile + d := yaml.NewDecoder(f) + if err := d.Decode(&mainFile); err != nil { + return Project{}, fmt.Errorf("%w: %s", ErrParsing, err) + } + + pr := Project{ + Name: filepath.Base(wd), + } + + if len(strings.TrimSpace(mainFile.ProjectName)) > 0 { + pr.Name = mainFile.ProjectName + } + + for repoName, repo := range mainFile.Repositories { + pr.Repositories = append(pr.Repositories, Repository{ + Name: fmt.Sprintf("%s-%s", pr.Name, strings.ToLower(repoName)), + Source: repo.Storage.Source, + Destination: repo.Storage.Destination, + Schedule: repo.Schedule, + }) + } + + return pr, nil +} diff --git a/pkg/project/project.go b/pkg/project/project.go new file mode 100644 index 0000000..0d5c974 --- /dev/null +++ b/pkg/project/project.go @@ -0,0 +1,15 @@ +package project + +type ( + Project struct { + Name string `json:"name"` + Repositories []Repository `json:"repositories"` + } + + Repository struct { + Name string `json:"name"` + Schedule string `json:"schedule"` + Source string `json:"source"` + Destination string `json:"destination"` + } +)