diff --git a/internal/cli/cli.go b/internal/cli/cli.go index e65a04c..2be1c1a 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -9,23 +9,24 @@ import ( ) type SquareCli struct { - Rest *rest.RestClient Config *config.Config } -func NewSquareCli() (squareCli *SquareCli) { +func NewSquareCli() *SquareCli { config, err := config.Load() if err != nil { panic("could not load config file") } - restClient := rest.NewClient(config.AuthToken) - squareCli = &SquareCli{ + squareCli := &SquareCli{ Config: config, - Rest: restClient, } - return + return squareCli +} + +func (squareCli *SquareCli) Rest() *rest.RestClient { + return rest.NewClient(squareCli.Config.AuthToken) } func (squareCli *SquareCli) Err() io.Writer { diff --git a/internal/command/app/backup.go b/internal/command/app/backup.go new file mode 100644 index 0000000..b598b5b --- /dev/null +++ b/internal/command/app/backup.go @@ -0,0 +1,83 @@ +package app + +import ( + "fmt" + "io" + "net/http" + "os" + "time" + + "github.com/spf13/cobra" + "github.com/squarecloudofc/cli/internal/cli" + "github.com/squarecloudofc/cli/internal/ui" +) + +func NewBackupCommand(squareCli *cli.SquareCli) *cobra.Command { + cmd := &cobra.Command{ + Use: "backup", + Short: "Create a backup of you application", + RunE: runBackupCommand(squareCli), + } + + return cmd +} + +func runBackupCommand(squareCli *cli.SquareCli) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) (err error) { + var appId string + rest := squareCli.Rest() + + if len(args) > 0 { + appId = args[0] + } + + if len(args) < 1 { + id, err := CreateApplicationSelection(squareCli) + if err != nil { + return err + } + + appId = id + } + + result, err := rest.ApplicationBackup(appId) + if err != nil { + return err + } + + if result.DownloadURL == "" { + fmt.Fprintf(squareCli.Out(), "%s It's not possible to download your backup, please try again later...\n", ui.XMark) + } + + fmt.Fprintln(squareCli.Out(), "Downloading your backup...") + + time := time.Now().Format("2006-01-02 15:04:05") + filename := fmt.Sprintf("Square Cloud - Backup %s.zip", time) + + err = downloadBackup(filename, result.DownloadURL) + if err != nil { + fmt.Fprintf(squareCli.Out(), "%s It's not possible to download your backup, please try again later...\n", ui.XMark) + return + } + + fmt.Fprintf(squareCli.Out(), "%s Your backup is successfuly downloaded to %s\n", ui.CheckMark, filename) + return nil + } +} + +func downloadBackup(destination string, url string) error { + resp, err := http.Get(url) + if err != nil { + return err + } + defer resp.Body.Close() + + out, err := os.Create(destination) + if err != nil { + return err + } + defer out.Close() + + _, err = io.Copy(out, resp.Body) + return err +} diff --git a/internal/command/app/delete.go b/internal/command/app/delete.go index 8225595..3b910eb 100644 --- a/internal/command/app/delete.go +++ b/internal/command/app/delete.go @@ -21,6 +21,7 @@ func NewDeleteCommand(squareCli *cli.SquareCli) *cobra.Command { func runDeleteCommand(squareCli *cli.SquareCli) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) (err error) { var appId string + rest := squareCli.Rest() if len(args) > 0 { appId = args[0] @@ -35,7 +36,7 @@ func runDeleteCommand(squareCli *cli.SquareCli) func(cmd *cobra.Command, args [] appId = id } - success, err := squareCli.Rest.ApplicationDelete(appId) + success, err := rest.ApplicationDelete(appId) if err != nil { return err } diff --git a/internal/command/app/logs.go b/internal/command/app/logs.go index a9dd343..c4f543d 100644 --- a/internal/command/app/logs.go +++ b/internal/command/app/logs.go @@ -20,6 +20,7 @@ func NewLogsCommand(squareCli *cli.SquareCli) *cobra.Command { func runLogsCommand(squareCli *cli.SquareCli) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) (err error) { var appId string + rest := squareCli.Rest() if len(args) > 0 { appId = args[0] @@ -34,7 +35,7 @@ func runLogsCommand(squareCli *cli.SquareCli) func(cmd *cobra.Command, args []st appId = id } - result, err := squareCli.Rest.ApplicationLogs(appId) + result, err := rest.ApplicationLogs(appId) if err != nil { return err } diff --git a/internal/command/app/restart.go b/internal/command/app/restart.go index 1851fb4..a20adda 100644 --- a/internal/command/app/restart.go +++ b/internal/command/app/restart.go @@ -21,6 +21,7 @@ func NewRestartCommand(squareCli *cli.SquareCli) *cobra.Command { func runRestartCommand(squareCli *cli.SquareCli) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) (err error) { var appId string + rest := squareCli.Rest() if len(args) > 0 { appId = args[0] @@ -35,7 +36,7 @@ func runRestartCommand(squareCli *cli.SquareCli) func(cmd *cobra.Command, args [ appId = id } - success, err := squareCli.Rest.ApplicationRestart(appId) + success, err := rest.ApplicationRestart(appId) if err != nil { return err } diff --git a/internal/command/app/root.go b/internal/command/app/root.go index 7909de1..d01e7be 100644 --- a/internal/command/app/root.go +++ b/internal/command/app/root.go @@ -12,7 +12,8 @@ import ( type RunEFunc func(cmd *cobra.Command, args []string) error func CreateApplicationSelection(squareCli *cli.SquareCli) (string, error) { - rapps, err := squareCli.Rest.SelfUser() + rest := squareCli.Rest() + rapps, err := rest.SelfUser() if err != nil { return "", err } @@ -42,6 +43,7 @@ func NewAppCommand(squareCli *cli.SquareCli) *cobra.Command { } cmd.AddCommand( + NewBackupCommand(squareCli), NewDeleteCommand(squareCli), NewLogsCommand(squareCli), NewStartCommand(squareCli), diff --git a/internal/command/app/start.go b/internal/command/app/start.go index 8e0871f..b36235d 100644 --- a/internal/command/app/start.go +++ b/internal/command/app/start.go @@ -21,6 +21,7 @@ func NewStartCommand(squareCli *cli.SquareCli) *cobra.Command { func runStartCommand(squareCli *cli.SquareCli) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) (err error) { var appId string + rest := squareCli.Rest() if len(args) > 0 { appId = args[0] @@ -35,7 +36,7 @@ func runStartCommand(squareCli *cli.SquareCli) func(cmd *cobra.Command, args []s appId = id } - success, err := squareCli.Rest.ApplicationStart(appId) + success, err := rest.ApplicationStart(appId) if err != nil { return } diff --git a/internal/command/app/status.go b/internal/command/app/status.go index e6adb41..3e2836f 100644 --- a/internal/command/app/status.go +++ b/internal/command/app/status.go @@ -25,6 +25,7 @@ func NewStatusCommand(squareCli *cli.SquareCli) *cobra.Command { func runStatusCommand(squareCli *cli.SquareCli) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) (err error) { var appId string + rest := squareCli.Rest() if len(args) > 0 { appId = args[0] @@ -39,7 +40,7 @@ func runStatusCommand(squareCli *cli.SquareCli) func(cmd *cobra.Command, args [] appId = id } - data, err := squareCli.Rest.ApplicationStatus(appId) + data, err := rest.ApplicationStatus(appId) if err != nil { return err diff --git a/internal/command/app/stop.go b/internal/command/app/stop.go index 71dd1a6..fd48549 100644 --- a/internal/command/app/stop.go +++ b/internal/command/app/stop.go @@ -21,6 +21,7 @@ func NewStopCommand(squareCli *cli.SquareCli) *cobra.Command { func runStopCommand(squareCli *cli.SquareCli) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) (err error) { var appId string + rest := squareCli.Rest() if len(args) > 0 { appId = args[0] @@ -35,7 +36,7 @@ func runStopCommand(squareCli *cli.SquareCli) func(cmd *cobra.Command, args []st appId = id } - success, err := squareCli.Rest.ApplicationStop(appId) + success, err := rest.ApplicationStop(appId) if err != nil { return } diff --git a/internal/command/apps.go b/internal/command/apps.go index 1e8a67e..2819ce2 100644 --- a/internal/command/apps.go +++ b/internal/command/apps.go @@ -23,7 +23,8 @@ func NewAppsCommand(squareCli *cli.SquareCli) *cobra.Command { func runAppsCommand(squareCli *cli.SquareCli) RunEFunc { return func(cmd *cobra.Command, args []string) (err error) { - self, err := squareCli.Rest.SelfUser() + rest := squareCli.Rest() + self, err := rest.SelfUser() if err != nil { return } diff --git a/internal/command/commit.go b/internal/command/commit.go index 914db05..cc3b77d 100644 --- a/internal/command/commit.go +++ b/internal/command/commit.go @@ -9,6 +9,7 @@ import ( "github.com/spf13/cobra" "github.com/squarecloudofc/cli/internal/cli" "github.com/squarecloudofc/cli/internal/squareconfig" + "github.com/squarecloudofc/cli/internal/squareignore" "github.com/squarecloudofc/cli/internal/ui" "github.com/squarecloudofc/cli/pkg/zipper" ) @@ -25,7 +26,9 @@ func NewCommitCommand(squareCli *cli.SquareCli) *cobra.Command { func runCommitCommand(squareCli *cli.SquareCli) RunEFunc { return func(cmd *cobra.Command, args []string) (err error) { - self, err := squareCli.Rest.SelfUser() + rest := squareCli.Rest() + + self, err := rest.SelfUser() if err != nil { return err } @@ -41,12 +44,12 @@ func runCommitCommand(squareCli *cli.SquareCli) RunEFunc { } if config.IsCreated() { - fmt.Fprintln(squareCli.Out(), "seems you don't have a squarecloud.config file, please create one") + fmt.Fprintln(squareCli.Out(), "Seems you don't have a squarecloud.config file, please create one") return } if config.ID == "" { - fmt.Fprintln(squareCli.Out(), "your squarecloud.config file don't have ID property") + fmt.Fprintln(squareCli.Out(), "Your squarecloud.config file don't have ID property") } workDir, err := os.Getwd() @@ -62,12 +65,17 @@ func runCommitCommand(squareCli *cli.SquareCli) RunEFunc { defer file.Close() defer os.Remove(file.Name()) - err = zipper.ZipFolder(workDir, file) + ignoreFiles, err := squareignore.Load() + if err != nil { + ignoreFiles = []string{} + } + + err = zipper.ZipFolder(workDir, file, ignoreFiles) if err != nil { return err } - success, err := squareCli.Rest.ApplicationCommit(config.ID, file.Name()) + success, err := rest.ApplicationCommit(config.ID, file.Name()) if err != nil { return err } diff --git a/internal/command/whoami.go b/internal/command/whoami.go index b690843..58ef1c2 100644 --- a/internal/command/whoami.go +++ b/internal/command/whoami.go @@ -20,7 +20,8 @@ func NewWhoamiCommand(squareCli *cli.SquareCli) *cobra.Command { func runWhoamiCommand(squareCli *cli.SquareCli) RunEFunc { return func(cmd *cobra.Command, args []string) (err error) { - self, err := squareCli.Rest.SelfUser() + rest := squareCli.Rest() + self, err := rest.SelfUser() if err != nil { return err } diff --git a/internal/command/zip.go b/internal/command/zip.go index c2ea718..7812b26 100644 --- a/internal/command/zip.go +++ b/internal/command/zip.go @@ -4,9 +4,12 @@ import ( "fmt" "os" "path" + "path/filepath" "github.com/spf13/cobra" "github.com/squarecloudofc/cli/internal/cli" + "github.com/squarecloudofc/cli/internal/squareignore" + "github.com/squarecloudofc/cli/internal/ui" "github.com/squarecloudofc/cli/pkg/zipper" ) @@ -22,27 +25,40 @@ func NewZipCommand(squareCli *cli.SquareCli) *cobra.Command { func runZipCommand(squareCli *cli.SquareCli) RunEFunc { return func(cmd *cobra.Command, args []string) (err error) { - fmt.Fprintln(squareCli.Out(), "zipping your aplication") workDir, err := os.Getwd() if err != nil { return err } - zipfilename := path.Join(workDir, "source.zip") + workDirName := filepath.Base(workDir) + + zipfilename := path.Join(workDir, workDirName+".zip") + if _, err := os.Lstat(zipfilename); err == nil { + err := os.Remove(zipfilename) + if err != nil { + fmt.Fprintln(squareCli.Err(), "source.zip already exists and its not possible to delete it") + } + } + file, err := os.CreateTemp("", "*.zip") if err != nil { return err } defer file.Close() - err = zipper.ZipFolder(workDir, file) + ignoreFiles, err := squareignore.Load() + if err != nil { + ignoreFiles = []string{} + } + + err = zipper.ZipFolder(workDir, file, ignoreFiles) if err != nil { return err } os.Rename(file.Name(), zipfilename) - fmt.Fprintf(squareCli.Out(), "your source has successfuly zipped") + fmt.Fprintf(squareCli.Out(), "%s Your source has successfuly zipped to %s.zip\n", ui.CheckMark, workDirName) return nil } } diff --git a/internal/squareignore/squareignore.go b/internal/squareignore/squareignore.go new file mode 100644 index 0000000..59fdd4e --- /dev/null +++ b/internal/squareignore/squareignore.go @@ -0,0 +1,35 @@ +package squareignore + +import ( + "errors" + "os" + "strings" +) + +const SquareIgnoreFile = ".squareignore" + +func Load() ([]string, error) { + _, err := os.Lstat(SquareIgnoreFile) + if err != nil { + if os.IsNotExist(err) { + return nil, errors.New(".squareignore file does not exists") + } + + return nil, err + } + + file, err := os.ReadFile(SquareIgnoreFile) + if err != nil { + return nil, err + } + + trimmed := strings.TrimSpace(string(file)) + var filtered []string + for _, e := range strings.Split(trimmed, "\n") { + if e != "" { + filtered = append(filtered, e) + } + } + + return filtered, nil +} diff --git a/pkg/zipper/zipper.go b/pkg/zipper/zipper.go index 809b7bd..acd39fa 100644 --- a/pkg/zipper/zipper.go +++ b/pkg/zipper/zipper.go @@ -13,8 +13,7 @@ var ( DefaultIgnoredFiles = []string{"node_modules/", ".git/", ".vscode/", ".github/", ".cache/", "package-lock.json"} ) -func shouldIgnoreFile(filedir string, file os.FileInfo) bool { - var ignoreEntries []string +func shouldIgnoreFile(filedir string, file os.FileInfo, ignoreEntries []string) bool { ignoreEntries = append(ignoreEntries, DefaultIgnoredFiles...) for _, entry := range ignoreEntries { @@ -32,13 +31,13 @@ func shouldIgnoreFile(filedir string, file os.FileInfo) bool { return false } -func ZipFolder(folder string, file *os.File) error { +func ZipFolder(folder string, destination *os.File, ignoreFiles []string) error { wd, err := os.Getwd() if err != nil { return err } - w := zip.NewWriter(file) + w := zip.NewWriter(destination) defer w.Close() return filepath.Walk(folder, func(path string, info os.FileInfo, err error) error { @@ -47,7 +46,7 @@ func ZipFolder(folder string, file *os.File) error { } absolutepath, _ := strings.CutPrefix(path, fmt.Sprintf("%s/", wd)) - if shouldIgnoreFile(absolutepath, info) { + if shouldIgnoreFile(absolutepath, info, ignoreFiles) { return nil }